org.apache.maven.plugin.invoker.InstallMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-invoker-plugin Show documentation
Show all versions of maven-invoker-plugin Show documentation
The Maven Invoker Plugin is used to run a set of Maven projects. The plugin can determine whether each project
execution is successful, and optionally can verify the output generated from a given project execution.
package org.apache.maven.plugin.invoker;
/*
* 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.
*/
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.installer.ArtifactInstaller;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.FileUtils;
/**
* Installs the project artifacts of the main build into the local repository as a preparation to run the sub projects.
* More precisely, all artifacts of the project itself, all its locally reachable parent POMs and all its dependencies
* from the reactor will be installed to the local repository.
*
* @since 1.2
* @author Paul Gier
* @author Benjamin Bentmann
* @version $Id: InstallMojo.java 1671476 2015-04-06 03:53:29Z dantran $
*/
// CHECKSTYLE_OFF: LineLength
@Mojo( name = "install", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST, requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true )
// CHECKSTYLE_ON: LineLength
public class InstallMojo
extends AbstractMojo
{
/**
* Maven artifact install component to copy artifacts to the local repository.
*/
@Component
private ArtifactInstaller installer;
/**
* The component used to create artifacts.
*/
@Component
private ArtifactFactory artifactFactory;
/**
* The component used to create artifacts.
*/
@Component
private ArtifactRepositoryFactory repositoryFactory;
/**
*/
@Parameter( property = "localRepository", required = true, readonly = true )
private ArtifactRepository localRepository;
/**
* The path to the local repository into which the project artifacts should be installed for the integration tests.
* If not set, the regular local repository will be used. To prevent soiling of your regular local repository with
* possibly broken artifacts, it is strongly recommended to use an isolated repository for the integration tests
* (e.g. ${project.build.directory}/it-repo
).
*/
@Parameter( property = "invoker.localRepositoryPath" )
private File localRepositoryPath;
/**
* The current Maven project.
*/
@Parameter( defaultValue = "${project}", readonly = true, required = true )
private MavenProject project;
/**
* The set of Maven projects in the reactor build.
*/
@Parameter( defaultValue = "${reactorProjects}", readonly = true )
private Collection reactorProjects;
/**
* A flag used to disable the installation procedure. This is primarily intended for usage from the command line to
* occasionally adjust the build.
*
* @since 1.4
*/
@Parameter( property = "invoker.skip", defaultValue = "false" )
private boolean skipInstallation;
/**
* The identifiers of already installed artifacts, used to avoid multiple installation of the same artifact.
*/
private Collection installedArtifacts;
/**
* The identifiers of already copied artifacts, used to avoid multiple installation of the same artifact.
*/
private Collection copiedArtifacts;
/**
* Extra dependencies that need to be installed on the local repository.
* Format:
*
*
* groupId:artifactId:version:type:classifier
*
*
* Examples:
*
*
* org.apache.maven.plugins:maven-clean-plugin:2.4:maven-plugin
* org.apache.maven.plugins:maven-clean-plugin:2.4:jar:javadoc
*
*
* If the type is 'maven-plugin' the plugin will try to resolve the artifact using plugin remote repositories,
* instead of using artifact remote repositories.
*
* @since 1.6
*/
@Parameter
private String[] extraArtifacts;
/**
*/
@Component
private ArtifactResolver resolver;
/**
*/
@Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true )
private List remoteArtifactRepositories;
/**
*/
@Parameter( defaultValue = "${project.pluginArtifactRepositories}", readonly = true )
private List remotePluginRepositories;
/**
*/
@Component
private ArtifactMetadataSource artifactMetadataSource;
/**
* Performs this mojo's tasks.
*
* @throws MojoExecutionException If the artifacts could not be installed.
*/
public void execute()
throws MojoExecutionException
{
if ( skipInstallation )
{
getLog().info( "Skipping artifact installation per configuration." );
return;
}
ArtifactRepository testRepository = createTestRepository();
installedArtifacts = new HashSet();
copiedArtifacts = new HashSet();
installProjectDependencies( project, reactorProjects, testRepository );
installProjectParents( project, testRepository );
installProjectArtifacts( project, testRepository );
installExtraArtifacts( testRepository, extraArtifacts );
}
/**
* Creates the local repository for the integration tests. If the user specified a custom repository location, the
* custom repository will have the same identifier, layout and policies as the real local repository. That means
* apart from the location, the custom repository will be indistinguishable from the real repository such that its
* usage is transparent to the integration tests.
*
* @return The local repository for the integration tests, never null
.
* @throws MojoExecutionException If the repository could not be created.
*/
private ArtifactRepository createTestRepository()
throws MojoExecutionException
{
ArtifactRepository testRepository = localRepository;
if ( localRepositoryPath != null )
{
try
{
if ( !localRepositoryPath.exists() && !localRepositoryPath.mkdirs() )
{
throw new IOException( "Failed to create directory: " + localRepositoryPath );
}
testRepository =
repositoryFactory.createArtifactRepository( localRepository.getId(),
localRepositoryPath.toURL().toExternalForm(),
localRepository.getLayout(),
localRepository.getSnapshots(),
localRepository.getReleases() );
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to create local repository: " + localRepositoryPath, e );
}
}
return testRepository;
}
/**
* Installs the specified artifact to the local repository. Note: This method should only be used for artifacts that
* originate from the current (reactor) build. Artifacts that have been grabbed from the user's local repository
* should be installed to the test repository via {@link #copyArtifact(File, Artifact, ArtifactRepository)}.
*
* @param file The file associated with the artifact, must not be null
. This is in most cases the value
* of artifact.getFile()
with the exception of the main artifact from a project with
* packaging "pom". Projects with packaging "pom" have no main artifact file. They have however artifact
* metadata (e.g. site descriptors) which needs to be installed.
* @param artifact The artifact to install, must not be null
.
* @param testRepository The local repository to install the artifact to, must not be null
.
* @throws MojoExecutionException If the artifact could not be installed (e.g. has no associated file).
*/
private void installArtifact( File file, Artifact artifact, ArtifactRepository testRepository )
throws MojoExecutionException
{
try
{
if ( file == null )
{
throw new IllegalStateException( "Artifact has no associated file: " + artifact.getId() );
}
if ( !file.isFile() )
{
throw new IllegalStateException( "Artifact is not fully assembled: " + file );
}
if ( installedArtifacts.add( artifact.getId() ) )
{
installer.install( file, artifact, testRepository );
}
else
{
getLog().debug( "Not re-installing " + artifact + ", " + file );
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to install artifact: " + artifact, e );
}
}
/**
* Installs the specified artifact to the local repository. This method serves basically the same purpose as
* {@link #installArtifact(File, Artifact, ArtifactRepository)} but is meant for artifacts that have been resolved
* from the user's local repository (and not the current build outputs). The subtle difference here is that
* artifacts from the repository have already undergone transformations and these manipulations should not be redone
* by the artifact installer. For this reason, this method performs plain copy operations to install the artifacts.
*
* @param file The file associated with the artifact, must not be null
.
* @param artifact The artifact to install, must not be null
.
* @param testRepository The local repository to install the artifact to, must not be null
.
* @throws MojoExecutionException If the artifact could not be installed (e.g. has no associated file).
*/
private void copyArtifact( File file, Artifact artifact, ArtifactRepository testRepository )
throws MojoExecutionException
{
try
{
if ( file == null )
{
throw new IllegalStateException( "Artifact has no associated file: " + artifact.getId() );
}
if ( !file.isFile() )
{
throw new IllegalStateException( "Artifact is not fully assembled: " + file );
}
if ( copiedArtifacts.add( artifact.getId() ) )
{
File destination = new File( testRepository.getBasedir(), testRepository.pathOf( artifact ) );
getLog().debug( "Installing " + file + " to " + destination );
copyFileIfDifferent( file, destination );
MetadataUtils.createMetadata( destination, artifact );
}
else
{
getLog().debug( "Not re-installing " + artifact + ", " + file );
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to stage artifact: " + artifact, e );
}
}
private void copyFileIfDifferent( File src, File dst )
throws IOException
{
if ( src.lastModified() != dst.lastModified() || src.length() != dst.length() )
{
FileUtils.copyFile( src, dst );
dst.setLastModified( src.lastModified() );
}
}
/**
* Installs the main artifact and any attached artifacts of the specified project to the local repository.
*
* @param mvnProject The project whose artifacts should be installed, must not be null
.
* @param testRepository The local repository to install the artifacts to, must not be null
.
* @throws MojoExecutionException If any artifact could not be installed.
*/
private void installProjectArtifacts( MavenProject mvnProject, ArtifactRepository testRepository )
throws MojoExecutionException
{
try
{
// Install POM (usually attached as metadata but that happens only as a side effect of the Install Plugin)
installProjectPom( mvnProject, testRepository );
// Install the main project artifact (if the project has one, e.g. has no "pom" packaging)
Artifact mainArtifact = mvnProject.getArtifact();
if ( mainArtifact.getFile() != null )
{
installArtifact( mainArtifact.getFile(), mainArtifact, testRepository );
}
// Install any attached project artifacts
Collection attachedArtifacts = (Collection) mvnProject.getAttachedArtifacts();
for ( Artifact attachedArtifact : attachedArtifacts )
{
installArtifact( attachedArtifact.getFile(), attachedArtifact, testRepository );
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to install project artifacts: " + mvnProject, e );
}
}
/**
* Installs the (locally reachable) parent POMs of the specified project to the local repository. The parent POMs
* from the reactor must be installed or the forked IT builds will fail when using a clean repository.
*
* @param mvnProject The project whose parent POMs should be installed, must not be null
.
* @param testRepository The local repository to install the POMs to, must not be null
.
* @throws MojoExecutionException If any POM could not be installed.
*/
private void installProjectParents( MavenProject mvnProject, ArtifactRepository testRepository )
throws MojoExecutionException
{
try
{
for ( MavenProject parent = mvnProject.getParent(); parent != null; parent = parent.getParent() )
{
if ( parent.getFile() == null )
{
copyParentPoms( parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), testRepository );
break;
}
installProjectPom( parent, testRepository );
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to install project parents: " + mvnProject, e );
}
}
/**
* Installs the POM of the specified project to the local repository.
*
* @param mvnProject The project whose POM should be installed, must not be null
.
* @param testRepository The local repository to install the POM to, must not be null
.
* @throws MojoExecutionException If the POM could not be installed.
*/
private void installProjectPom( MavenProject mvnProject, ArtifactRepository testRepository )
throws MojoExecutionException
{
try
{
Artifact pomArtifact = null;
if ( "pom".equals( mvnProject.getPackaging() ) )
{
pomArtifact = mvnProject.getArtifact();
}
if ( pomArtifact == null )
{
pomArtifact =
artifactFactory.createProjectArtifact( mvnProject.getGroupId(), mvnProject.getArtifactId(),
mvnProject.getVersion() );
}
installArtifact( mvnProject.getFile(), pomArtifact, testRepository );
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to install POM: " + mvnProject, e );
}
}
/**
* Installs the dependent projects from the reactor to the local repository. The dependencies on other modules from
* the reactor must be installed or the forked IT builds will fail when using a clean repository.
*
* @param mvnProject The project whose dependent projects should be installed, must not be null
.
* @param reactorProjects The set of projects in the reactor build, must not be null
.
* @param testRepository The local repository to install the POMs to, must not be null
.
* @throws MojoExecutionException If any dependency could not be installed.
*/
private void installProjectDependencies( MavenProject mvnProject, Collection reactorProjects,
ArtifactRepository testRepository )
throws MojoExecutionException
{
// keep track if we have passed mvnProject in reactorProjects
boolean foundCurrent = false;
// ... into dependencies that were resolved from reactor projects ...
Collection dependencyProjects = new LinkedHashSet();
// index available reactor projects
Map projects = new HashMap();
for ( MavenProject reactorProject : reactorProjects )
{
String projectId =
reactorProject.getGroupId() + ':' + reactorProject.getArtifactId() + ':' + reactorProject.getVersion();
projects.put( projectId, reactorProject );
// only add projects of reactor build previous to this mvnProject
foundCurrent |= ( mvnProject.equals( reactorProject ) );
if ( !foundCurrent )
{
dependencyProjects.add( projectId );
}
}
// group transitive dependencies (even those that don't contribute to the class path like POMs) ...
Collection artifacts = (Collection) mvnProject.getArtifacts();
// ... and those that were resolved from the (local) repo
Collection dependencyArtifacts = new LinkedHashSet();
for ( Artifact artifact : artifacts )
{
// workaround for MNG-2961 to ensure the base version does not contain a timestamp
artifact.isSnapshot();
String projectId = artifact.getGroupId() + ':' + artifact.getArtifactId() + ':' + artifact.getBaseVersion();
if ( !projects.containsKey( projectId ) )
{
dependencyArtifacts.add( artifact );
}
}
// install dependencies
try
{
// copy dependencies that where resolved from the local repo
for ( Artifact artifact : dependencyArtifacts )
{
copyArtifact( artifact, testRepository );
}
// install dependencies that were resolved from the reactor
for ( String projectId : dependencyProjects )
{
MavenProject dependencyProject = projects.get( projectId );
installProjectArtifacts( dependencyProject, testRepository );
installProjectParents( dependencyProject, testRepository );
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Failed to install project dependencies: " + mvnProject, e );
}
}
private void copyArtifact( Artifact artifact, ArtifactRepository testRepository )
throws MojoExecutionException
{
copyPoms( artifact, testRepository );
Artifact depArtifact =
artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(),
artifact.getBaseVersion(), artifact.getType(),
artifact.getClassifier() );
File artifactFile = artifact.getFile();
copyArtifact( artifactFile, depArtifact, testRepository );
}
private void copyPoms( Artifact artifact, ArtifactRepository testRepository )
throws MojoExecutionException
{
Artifact pomArtifact =
artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(),
artifact.getBaseVersion() );
File pomFile = new File( localRepository.getBasedir(), localRepository.pathOf( pomArtifact ) );
if ( pomFile.isFile() )
{
copyArtifact( pomFile, pomArtifact, testRepository );
copyParentPoms( pomFile, testRepository );
}
}
/**
* Installs all parent POMs of the specified POM file that are available in the local repository.
*
* @param pomFile The path to the POM file whose parents should be installed, must not be null
.
* @param testRepository The local repository to install the POMs to, must not be null
.
* @throws MojoExecutionException If any (existing) parent POM could not be installed.
*/
private void copyParentPoms( File pomFile, ArtifactRepository testRepository )
throws MojoExecutionException
{
Model model = PomUtils.loadPom( pomFile );
Parent parent = model.getParent();
if ( parent != null )
{
copyParentPoms( parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), testRepository );
}
}
/**
* Installs the specified POM and all its parent POMs to the local repository.
*
* @param groupId The group id of the POM which should be installed, must not be null
.
* @param artifactId The artifact id of the POM which should be installed, must not be null
.
* @param version The version of the POM which should be installed, must not be null
.
* @param testRepository The local repository to install the POMs to, must not be null
.
* @throws MojoExecutionException If any (existing) parent POM could not be installed.
*/
private void copyParentPoms( String groupId, String artifactId, String version, ArtifactRepository testRepository )
throws MojoExecutionException
{
Artifact pomArtifact = artifactFactory.createProjectArtifact( groupId, artifactId, version );
if ( installedArtifacts.contains( pomArtifact.getId() ) || copiedArtifacts.contains( pomArtifact.getId() ) )
{
getLog().debug( "Not re-installing " + pomArtifact );
return;
}
File pomFile = new File( localRepository.getBasedir(), localRepository.pathOf( pomArtifact ) );
if ( pomFile.isFile() )
{
copyArtifact( pomFile, pomArtifact, testRepository );
copyParentPoms( pomFile, testRepository );
}
}
private void installExtraArtifacts( ArtifactRepository testRepository, String[] extraArtifacts )
throws MojoExecutionException
{
if ( extraArtifacts == null )
{
return;
}
Artifact originatingArtifact = project.getArtifact();
for ( String extraArtifact : extraArtifacts )
{
String[] gav = extraArtifact.split( ":" );
if ( gav.length < 3 || gav.length > 5 )
{
throw new MojoExecutionException( "Invalid artifact " + extraArtifact );
}
String groupId = gav[0];
String artifactId = gav[1];
String version = gav[2];
String type = "jar";
if ( gav.length > 3 )
{
type = gav[3];
}
String classifier = null;
if ( gav.length == 5 )
{
classifier = gav[4];
}
List remoteRepositories;
if ( "maven-plugin".equals( type ) )
{
remoteRepositories = this.remotePluginRepositories;
}
else
{
remoteRepositories = this.remoteArtifactRepositories;
}
Artifact artifact = null;
try
{
artifact =
artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type, classifier );
ArtifactResolutionResult arr =
resolver.resolveTransitively( Collections.singleton( artifact ), originatingArtifact,
remoteRepositories, localRepository, artifactMetadataSource );
if ( !groupId.equals( artifact.getGroupId() ) || !artifactId.equals( artifact.getArtifactId() )
|| !version.equals( artifact.getVersion() ) )
{
artifact =
artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type, classifier );
copyPoms( artifact, testRepository );
}
for ( Artifact arrArtifact : (Set) arr.getArtifacts() )
{
copyArtifact( arrArtifact, testRepository );
}
}
catch ( Exception e )
{
throw new MojoExecutionException( "Unable to resolve dependencies for: " + artifact, e );
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy