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

me.ccampo.maven.git.version.plugin.VersionInferenceExtension Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to you 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 me.ccampo.maven.git.version.plugin;

import me.ccampo.maven.git.version.core.VersionException;
import me.ccampo.maven.git.version.core.strategy.VersionStrategy;
import me.ccampo.maven.git.version.plugin.util.GroupArtifactVersion;
import me.ccampo.maven.git.version.plugin.util.ModelProvider;
import me.ccampo.maven.git.version.plugin.util.PluginConfig;
import me.ccampo.maven.git.version.plugin.util.PluginConfigProvider;
import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * Maven Extension that will update all the projects in the reactor with an externally managed version.
 * 

* This extension MUST be configured as a plugin in order to be configured. *

* 'strategy' - The configuration for an ExternalVersionStrategy. * 'hint' - A component hint to load the ExternalVersionStrategy. * * @author Brian Demers * @author Chris Campo */ @Component(role = AbstractMavenLifecycleParticipant.class, hint = "version-inference") public class VersionInferenceExtension extends AbstractMavenLifecycleParticipant { @Requirement private Logger logger; @Requirement private PlexusContainer container; private Map projectGavs = new HashMap<>(); private PluginConfigProvider pluginConfigProvider; private ModelProvider modelProvider; @Override public void afterProjectsRead(final MavenSession session) throws MavenExecutionException { init(); for (final MavenProject mavenProject : session.getAllProjects()) { setProjectVersion(mavenProject); } // Need to do a second pass here since our projectGavs map is populated now for (final MavenProject mavenProject : session.getAllProjects()) { final PluginConfig pluginConfig = pluginConfigProvider.getForProject(mavenProject); if (pluginConfig != null) { if (pluginConfig.shouldUpdateDependencies) { setDependencyVersions(mavenProject); } setParentVersion(mavenProject); createNewVersionPom(mavenProject); } } } // This is a clutch to work around Plexus's complete lack of constructor injection private void init() { Objects.requireNonNull(logger); Objects.requireNonNull(container); if (pluginConfigProvider == null) { pluginConfigProvider = new PluginConfigProvider(container); } if (modelProvider == null) { modelProvider = new ModelProvider(); } if (projectGavs == null) { projectGavs = new HashMap<>(); } } private void setProjectVersion(final MavenProject mavenProject) throws MavenExecutionException { // Get the plugin config final PluginConfig pluginConfig = pluginConfigProvider.getForProject(mavenProject); if (pluginConfig != null) { // Store the old version before changing it final String oldVersion = mavenProject.getVersion(); // Now use the strategy to figure out the new version final String newVersion = getNewVersion(pluginConfig.versionStrategy, mavenProject); logger.info("Inferred project version: " + newVersion); final String oldFinalName = mavenProject.getBuild().getFinalName(); final String newFinalName = oldFinalName.replaceFirst(Pattern.quote(oldVersion), newVersion); logger.info("Inferred project.build.finalName: " + newFinalName); // Now that we have the new version, we update the project versions. mavenProject.setVersion(newVersion); mavenProject.getArtifact().setVersion(newVersion); VersionRange versionRange = VersionRange.createFromVersion(newVersion); mavenProject.getArtifact().setVersionRange(versionRange); mavenProject.getBuild().setFinalName(newFinalName); final GroupArtifactVersion oldProjectVersion = GroupArtifactVersion.of(mavenProject.getGroupId(), mavenProject.getArtifactId(), oldVersion); projectGavs.put(oldProjectVersion, newVersion); } } /** * In the case where the plugin is configured to update project dependency * versions, we loop through the dependencies of the project and check if * that each dependency is actually one of the projects contained in this * POM (with the exception of the project itself, since it can never depend * on the latest version of itself). If a dependency is a project of this * POM, we update its version to the latest inferred version. */ private void setDependencyVersions(final MavenProject mavenProject) { final GroupArtifactVersion projectGav = GroupArtifactVersion.fromMavenProject(mavenProject); mavenProject.getDependencies().forEach(dependency -> { final GroupArtifactVersion dependencyGav = GroupArtifactVersion.of( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); if (!projectGav.equals(dependencyGav) && projectGavs.containsKey(dependencyGav)) { final String newVersion = projectGavs.get(dependencyGav); dependency.setVersion(newVersion); if (logger.isInfoEnabled()) { logger.info("Setting project " + projectGav + " dependency " + dependencyGav + " to version " + newVersion); } } }); } private void setParentVersion(final MavenProject mavenProject) throws MavenExecutionException { // Update model version. The project's version has been updated so we can just use it here. final Model model = modelProvider.getModel(mavenProject); model.setVersion(mavenProject.getVersion()); // Update model parent version if (model.getParent() != null) { final GroupArtifactVersion parentGav = GroupArtifactVersion.of( model.getParent().getGroupId(), model.getParent().getArtifactId(), model.getParent().getVersion() ); final String newVersionForParent = projectGavs.get(parentGav); if (newVersionForParent != null) { model.getParent().setVersion(newVersionForParent); } } // Nothing else to do. if (mavenProject.getParent() == null) { return; } /* * At this point, we've only updated the versions of the individual projects. * Now we need to update the references between the updated projects. */ final MavenProject parent = mavenProject.getParent(); if (projectGavs.containsKey(GroupArtifactVersion.fromMavenProject(parent))) { // We need to update the parent //TODO: implement -ccampo 2019-01-16 logger.warn("Need to update parent (not implemented)"); } } private String getNewVersion(final VersionStrategy strategy, final MavenProject mavenProject) throws MavenExecutionException { final Optional newVersion; try { newVersion = Optional.ofNullable(strategy.getVersion(mavenProject)); } catch (final VersionException e) { throw new MavenExecutionException(e.getMessage(), e); } return newVersion.orElseThrow(() -> { final String msg = "Unable to infer new version; strategy returned null."; return new MavenExecutionException(msg, mavenProject.getFile()); }).trim(); } private void createNewVersionPom(final MavenProject mavenProject) throws MavenExecutionException { final PluginConfig pluginConfig = pluginConfigProvider.getForProject(mavenProject); final File newPom; try { if (pluginConfig.shouldGenerateTemporaryFile) { newPom = File.createTempFile("pom", ".version-inference"); } else { newPom = new File(mavenProject.getBasedir(), "pom.xml.new-version"); } } catch (final IOException e) { throw new MavenExecutionException(e.getMessage(), e); } if (pluginConfig.shouldDeleteTemporaryFile) { newPom.deleteOnExit(); } if (logger.isDebugEnabled()) { logger.debug(VersionInferenceExtension.class.getSimpleName() + ": using new pom file => " + newPom); } final Model model = modelProvider.getModel(mavenProject); // Write the new pom to disk try (final Writer fileWriter = new FileWriter(newPom)) { new MavenXpp3Writer().write(fileWriter, model); } catch (final IOException e) { throw new MavenExecutionException(e.getMessage(), e); } mavenProject.setFile(newPom); } /* * The following setters are primarily used to facilitate testing. Probably not used in practice. */ @SuppressWarnings("unused") public void setLogger(final Logger logger) { this.logger = logger; } @SuppressWarnings("unused") public void setContainer(final PlexusContainer container) { this.container = container; } @SuppressWarnings("unused") public void setProjectGavs(final Map projectGavs) { this.projectGavs = projectGavs; } @SuppressWarnings("unused") public void setPluginConfigProvider(final PluginConfigProvider pluginConfigProvider) { this.pluginConfigProvider = pluginConfigProvider; } @SuppressWarnings("unused") public void setModelProvider(final ModelProvider modelProvider) { this.modelProvider = modelProvider; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy