All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itemis.maven.plugins.unleash.steps.actions.AbstractVersionsStep Maven / Gradle / Ivy

Go to download

This plugin provides a generic alternative to the error-prone default release plugin provided by Maven. It is designed to require a minimal effort of work for releasing modules and being extensible to integrate in every project setup.

There is a newer version: 3.2.0
Show newest version
package com.itemis.maven.plugins.unleash.steps.actions;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Profile;
import org.apache.maven.project.MavenProject;
import org.codehaus.mojo.versions.api.PomHelper;
import org.w3c.dom.Document;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.itemis.maven.aether.ArtifactCoordinates;
import com.itemis.maven.plugins.cdi.CDIMojoProcessingStep;
import com.itemis.maven.plugins.cdi.logging.Logger;
import com.itemis.maven.plugins.unleash.ReleaseMetadata;
import com.itemis.maven.plugins.unleash.ReleasePhase;
import com.itemis.maven.plugins.unleash.util.PomUtil;

/**
 * An abstract step for version upgrades in POMs.
 *
 * @author Pei-Tang Huang
 * @since 2.6.1
 */
public abstract class AbstractVersionsStep implements CDIMojoProcessingStep {
  @Inject
  protected Logger log;

  @Inject
  protected ReleaseMetadata metadata;

  @Inject
  @Named("reactorProjects")
  protected List reactorProjects;

  protected Map cachedPOMs;

  @Inject
  @Named("updateReactorDependencyVersion")
  protected boolean updateReactorDependencyVersion;

  // Raw models is only used for dependency version updating currently.
  // This may cause inconsistencies between reactorProjects and updated POMs.
  // However, I have no confidence in spread it out of this step.
  // TODO make the whole plugin work on raw models? (after having integration tests...)
  private LoadingCache rawModels = CacheBuilder.newBuilder()
      .build(new CacheLoader() {
        @Override
        public Model load(MavenProject project) throws Exception {
          return PomHelper.getRawModel(project);
        }
      });

  protected Document loadAndProcess(MavenProject project) {
    Document document = PomUtil.parsePOM(project).get();
    setProjectVersion(project, document);
    setParentVersion(project, document);
    if (this.updateReactorDependencyVersion) {
      setProjectReactorDependenciesVersion(project, document);
      setProjectReactorDependencyManagementVersion(project, document);
      setProfilesReactorDependenciesVersion(project, document);
      setProfilesReactorDependencyManagementVersion(project, document);
    }
    return document;
  }

  private void setProjectVersion(MavenProject project, Document document) {
    Map coordinatesByPhase = this.metadata
        .getArtifactCoordinatesByPhase(project.getGroupId(), project.getArtifactId());
    String oldVersion = coordinatesByPhase.get(previousReleasePhase()).getVersion();
    String newVersion = coordinatesByPhase.get(currentReleasePhase()).getVersion();
    logProjectVersionUpdate(project, oldVersion, newVersion);
    PomUtil.setProjectVersion(project.getModel(), document, newVersion);
  }

  protected void logProjectVersionUpdate(MavenProject project, String oldVersion, String newVersion) {
    if (this.log.isDebugEnabled()) {
      this.log.debug("\tUpdate of module version '" + project.getGroupId() + ":" + project.getArtifact() + "' ["
          + oldVersion + " => " + newVersion + "]");
    }
  }

  private void setParentVersion(MavenProject project, Document document) {
    Parent parent = project.getModel().getParent();
    if (parent != null) {
      Map coordinatesByPhase = this.metadata
          .getArtifactCoordinatesByPhase(parent.getGroupId(), parent.getArtifactId());
      ArtifactCoordinates oldCoordinates = coordinatesByPhase.get(previousReleasePhase());
      ArtifactCoordinates newCoordinates = coordinatesByPhase.get(currentReleasePhase());

      // null indicates that the parent is not part of the reactor projects since no release version had been calculated
      // for it
      if (newCoordinates != null) {
        logParentVersionUpdate(project, oldCoordinates, newCoordinates);
        PomUtil.setParentVersion(project.getModel(), document, newCoordinates.getVersion());
      }
    }
  }

  protected void logParentVersionUpdate(MavenProject project, ArtifactCoordinates oldCoordinates,
      ArtifactCoordinates newCoordinates) {
    if (this.log.isDebugEnabled()) {
      this.log.debug("\tUpdate of parent version of module '" + project.getGroupId() + ":" + project.getArtifact()
          + "' [" + oldCoordinates.getVersion() + " => " + newCoordinates.getVersion() + "]");
    }
  }

  private void setProjectReactorDependenciesVersion(MavenProject project, Document document) {
    final String dependenciesPath = "/";
    List dependencies = this.rawModels.getUnchecked(project).getDependencies();
    for (Dependency dependency : dependencies) {
      trySetDependencyVersionFromReactorProjects(project, document, dependenciesPath, dependency);
    }
  }

  private void setProjectReactorDependencyManagementVersion(MavenProject project, Document document) {
    DependencyManagement dependencyManagement = this.rawModels.getUnchecked(project).getDependencyManagement();
    if (dependencyManagement != null) {
      String dependenciesPath = "/dependencyManagement";
      List dependencies = dependencyManagement.getDependencies();
      for (Dependency dependency : dependencies) {
        trySetDependencyVersionFromReactorProjects(project, document, dependenciesPath, dependency);
      }
    }
  }

  private void setProfilesReactorDependenciesVersion(MavenProject project, Document document) {
    List profiles = this.rawModels.getUnchecked(project).getProfiles();
    for (Profile profile : profiles) {
      final String dependenciesPath = "/profiles/profile[id[text()='" + profile.getId() + "']]";
      List dependencies = profile.getDependencies();
      for (Dependency dependency : dependencies) {
        trySetDependencyVersionFromReactorProjects(project, document, dependenciesPath, dependency);
      }
    }
  }

  private void setProfilesReactorDependencyManagementVersion(MavenProject project, Document document) {
    List profiles = this.rawModels.getUnchecked(project).getProfiles();
    for (Profile profile : profiles) {
      final String dependenciesPath = "/profiles/profile[id[text()='" + profile.getId() + "']]/dependencyManagement";
      DependencyManagement dependencyManagement = profile.getDependencyManagement();
      if (dependencyManagement != null) {
        List dependencies = dependencyManagement.getDependencies();
        for (Dependency dependency : dependencies) {
          trySetDependencyVersionFromReactorProjects(project, document, dependenciesPath, dependency);
        }
      }
    }
  }

  protected abstract ReleasePhase previousReleasePhase();

  protected abstract ReleasePhase currentReleasePhase();

  private void trySetDependencyVersionFromReactorProjects(MavenProject project, Document document,
      String dependenciesPath, Dependency dependency) {
    for (MavenProject reactorProject : this.reactorProjects) {
      if (isReactorDependency(reactorProject, dependency)) {
        Map coordinatesByPhase = this.metadata
            .getArtifactCoordinatesByPhase(dependency.getGroupId(), dependency.getArtifactId());
        ArtifactCoordinates oldCoordinates = coordinatesByPhase.get(previousReleasePhase());
        ArtifactCoordinates newCoordinates = coordinatesByPhase.get(currentReleasePhase());

        if (newCoordinates == null || oldCoordinates == null) {
          // the dependency is not part of the reactor projects since no release version had been calculated for it

        } else if (dependency.getVersion() == null) {
          // version was managed somewhere

        } else if (Objects.equals(dependency.getVersion(), oldCoordinates.getVersion())) {
          this.log.debug(
              "\tUpdate of dependency '" + dependency.getGroupId() + ":" + dependency.getArtifactId() + "' version in '"
                  + dependenciesPath + "' of module '" + project.getGroupId() + ":" + project.getArtifact() + "' ["
                  + oldCoordinates.getVersion() + " => " + newCoordinates.getVersion() + "]");
          PomUtil.setDependencyVersion(dependency, document, dependenciesPath, newCoordinates.getVersion());
        }
      }
    }
  }

  private boolean isReactorDependency(MavenProject project, Dependency dependency) {
    String groupId = dependency.getGroupId();
    String artifactId = dependency.getArtifactId();

    Model model = this.rawModels.getUnchecked(project);
    String reactorGroupId = model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId();
    String reactorArtifactId = model.getArtifactId();

    return Objects.equals(groupId, reactorGroupId) && Objects.equals(artifactId, reactorArtifactId);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy