com.exentes.maven.versions.UseReleasesMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.exentes.maven.versions.UseReleasesMojo.java

Source

/*
 * 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;
    }
}