Java tutorial
/* * Copyright 2011 Exentes * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.exentes.maven.versions; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.SetMultimap; import com.google.common.collect.Sets; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.Restriction; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Dependency; import org.apache.maven.model.io.ModelWriter; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.sonatype.aether.RepositorySystem; import org.sonatype.aether.resolution.ArtifactRequest; import org.sonatype.aether.resolution.ArtifactResolutionException; import org.sonatype.aether.resolution.ArtifactResult; import org.sonatype.aether.util.artifact.DefaultArtifact; import java.io.IOException; import java.util.*; import static com.exentes.maven.versions.VersionMojoUtils.*; /** * @author Sergey Tavanets * @goal use-releases * @requiresDependencyCollection test * @aggregator */ public class UseReleasesMojo extends AbstractMojo { /** * @parameter expression="${session}" * @required * @readonly */ protected MavenSession session; /** * @component */ protected RepositorySystem repositorySystem; /** * @component */ protected ModelWriter modelWriter; /** * if {@code true} the plugin goal will not be executed * @parameter expression="${versions.plugin.skip}" default-value="false" */ protected boolean skip; /** * if {@code true} plugin goal execution will fail the build if there are errors during execution. if {@code false} * errors will be logged but the build will continue * @parameter expression="${versions.plugin.failBuild}" default-value="true" */ protected boolean failBuild; /** * @parameter expression="${dryRun}" default-value="false" */ protected boolean dryRun; @Override public void execute() throws MojoExecutionException, MojoFailureException { if (!skip) { Collection<String> errors = processProject(); if (errors.size() > 0) { StringBuilder errorBuilder = new StringBuilder( "Failed to migrate snapshot dependecies to releases\n"); Joiner.on('\n').appendTo(errorBuilder, errors); if (failBuild) { throw new MojoExecutionException(errorBuilder.toString()); } else { getLog().error(errorBuilder.toString()); } } } else { getLog().info("version:use-releases version update is skipped"); } } private Collection<String> processProject() throws MojoFailureException { List<String> errors = Lists.newArrayList(); getLog().info("Processing all projects snapshots..."); SetMultimap<Artifact, MavenProject> allSnapshotProjectArtifacts = VersionMojoUtils .allSnapshotProjectArtifacts(session); Map<String, Dependency> allDependenciesMap = allDependenciesMap(session); Map<Object, MavenProject> origins = origins(session); Set<MavenProject> projectsToUpdate = Sets.newHashSet(); for (Map.Entry<Artifact, Collection<MavenProject>> artifactWithProjects : allSnapshotProjectArtifacts .asMap().entrySet()) { Artifact snapshotArtifact = artifactWithProjects.getKey(); Collection<MavenProject> projects = artifactWithProjects.getValue(); try { ArtifactResult artifactResult = resolveReleasedArtifact(snapshotArtifact); for (MavenProject project : projects) { Dependency dependencyToUpdate = allDependenciesMap .get(projectArtifactKey(project, snapshotArtifact)); if (isPropertyPlaceholder(dependencyToUpdate.getVersion())) { MavenProject projectToUpdate = origins.get(dependencyToUpdate); String propertyName = getPropertyName(dependencyToUpdate.getVersion()); Properties projectProperties = projectToUpdate.getOriginalModel().getProperties(); if (projectProperties != null && projectProperties.containsKey(propertyName)) { String newVersion = null; String versionPropertyValue = projectProperties.getProperty(propertyName); VersionRange versionRange = VersionRange.createFromVersionSpec(versionPropertyValue); if (versionRange.getRecommendedVersion() == null) { int restrictionIndex = 0; for (Restriction restriction : versionRange.getRestrictions()) { if (restriction.isUpperBoundInclusive()) { if (snapshotArtifact.getVersion() .equals(restriction.getUpperBound().toString())) { DefaultArtifactVersion updatedVersion = new DefaultArtifactVersion( artifactResult.getArtifact().getVersion()); Restriction updatedRestriction = new Restriction( restriction.getUpperBound().equals(restriction.getLowerBound()) ? updatedVersion : restriction.getLowerBound(), restriction.isLowerBoundInclusive(), updatedVersion, restriction.isUpperBoundInclusive()); versionRange.getRestrictions().set(restrictionIndex, updatedRestriction); newVersion = versionRange.toString(); break; } } restrictionIndex++; } } else { newVersion = artifactResult.getArtifact().getVersion(); } if (newVersion != null) { projectProperties.setProperty(propertyName, newVersion); projectsToUpdate.add(projectToUpdate); getLog().info("Version property {" + propertyName + "} in the project [" + projectToUpdate.getId() + "] set to the value: " + artifactResult.getArtifact().getVersion()); getLog().info("Snapshot dependency [" + snapshotArtifact + "] is replaced with [" + artifactResult.getArtifact() + "] in the project: [" + projectToUpdate.getId() + "]"); } else { errors.add("Dependency version value '" + versionPropertyValue + "' defined as a value of property '" + propertyName + "' not supported"); } } else { errors.add("Property [" + propertyName + "] not found in the project [" + projectsToUpdate + "] properties. The artifact version cannot be resolved"); } } else if (snapshotArtifact.getVersion().equals(dependencyToUpdate.getVersion())) { MavenProject projectToUpdate = origins.get(dependencyToUpdate); projectsToUpdate.add(projectToUpdate); dependencyToUpdate.setVersion(artifactResult.getArtifact().getVersion()); getLog().info("Snapshot dependency [" + snapshotArtifact + "] is replaced with [" + artifactResult.getArtifact() + "] in the project: [" + projectToUpdate.getId() + "]"); } else if (dependencyToUpdate.getVersion() == null) { errors.add("Unknown version for the dependency [" + dependencyToUpdate + "]"); } else { // check if this is version range try { VersionRange versionRange = VersionRange .createFromVersionSpec(dependencyToUpdate.getVersion()); if (versionRange.getRecommendedVersion() == null) { // this this a version range. now all inclusive upper bounds should be inspected and the one which match resolved snapshot version must be upgraded int restrictionIndex = 0; for (Restriction restriction : versionRange.getRestrictions()) { if (restriction.isUpperBoundInclusive()) { if (isPropertyPlaceholder(restriction.getUpperBound().toString())) { // try to update a property which is used as an upper version boundary String propertyName = getPropertyName( restriction.getUpperBound().toString()); getLog().info("property name: " + propertyName); MavenProject projectToUpdate = origins.get(dependencyToUpdate); Properties projectProperties = projectToUpdate.getOriginalModel() .getProperties(); if (projectProperties != null && projectProperties.containsKey(propertyName) && projectProperties.getProperty(propertyName) .equals(snapshotArtifact.getVersion())) { projectProperties.setProperty(propertyName, artifactResult.getArtifact().getVersion()); projectsToUpdate.add(projectToUpdate); getLog().info( "Version property {" + propertyName + "} in the project [" + projectToUpdate.getId() + "] set to the value: " + artifactResult.getArtifact().getVersion()); getLog().info("Snapshot dependency [" + snapshotArtifact + "] is replaced with [" + artifactResult.getArtifact() + "] in the project: [" + projectToUpdate.getId() + "]"); break; } } else { if (snapshotArtifact.getVersion() .equals(restriction.getUpperBound().toString())) { DefaultArtifactVersion updatedVersion = new DefaultArtifactVersion( artifactResult.getArtifact().getVersion()); Restriction updatedRestriction = new Restriction( restriction.getUpperBound().equals( restriction.getLowerBound()) ? updatedVersion : restriction.getLowerBound(), restriction.isLowerBoundInclusive(), updatedVersion, restriction.isUpperBoundInclusive()); versionRange.getRestrictions().set(restrictionIndex, updatedRestriction); MavenProject projectToUpdate = origins.get(dependencyToUpdate); projectsToUpdate.add(projectToUpdate); dependencyToUpdate.setVersion(versionRange.toString()); getLog().info("Snapshot dependency [" + snapshotArtifact + "] is replaced with [" + dependencyToUpdate + "] in the project: [" + projectToUpdate.getId() + "]"); break; } } } restrictionIndex++; } } else { errors.add("Dependency version value [" + dependencyToUpdate.getVersion() + "] not supported"); } } catch (InvalidVersionSpecificationException e) { errors.add("Invalid version specified: " + dependencyToUpdate.getVersion() + ". Exception when parsing version: " + e.getMessage()); } } } } catch (ArtifactResolutionException e) { getLog().info(e); errors.add("Failed to resolve a RELEASE version for [" + snapshotArtifact + "]. Exception: " + e.getMessage()); } catch (InvalidVersionSpecificationException e) { errors.add("Invalid version specified: " + snapshotArtifact.getVersion() + ". Exception when parsing version: " + e.getMessage()); } } if (!dryRun) { for (MavenProject project : projectsToUpdate) { try { modelWriter.write(project.getFile(), null, project.getOriginalModel()); } catch (IOException e) { throw new MojoFailureException("Error writing POM", e); } } } return errors; } private ArtifactResult resolveReleasedArtifact(Artifact snapshotArtifact) throws ArtifactResolutionException { String version = releaseVersion(snapshotArtifact.getVersion()); ArtifactRequest request = new ArtifactRequest(); request.setArtifact(new DefaultArtifact(snapshotArtifact.getGroupId(), snapshotArtifact.getArtifactId(), snapshotArtifact.getClassifier(), snapshotArtifact.getType(), version)) .setRepositories(session.getTopLevelProject().getRemoteProjectRepositories()); ArtifactResult artifactResult = repositorySystem.resolveArtifact(session.getRepositorySession(), request); if (artifactResult.isResolved()) { getLog().debug("Found release snapshotArtifact: " + artifactResult.getArtifact()); } return artifactResult; } }