mirror of https://github.com/apache/maven.git
[MNG-6118] Make Maven aware of all projects in a multi module project when using -f or when changing directory to a submodule.
This closes #373
This commit is contained in:
parent
8393b9e0d9
commit
a5b292ddf8
|
@ -21,7 +21,6 @@ package org.apache.maven.graph;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -36,7 +35,6 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.DefaultMaven;
|
||||
import org.apache.maven.MavenExecutionException;
|
||||
import org.apache.maven.ProjectCycleException;
|
||||
import org.apache.maven.artifact.ArtifactUtils;
|
||||
|
@ -46,20 +44,17 @@ import org.apache.maven.execution.MavenSession;
|
|||
import org.apache.maven.execution.ProjectDependencyGraph;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.model.building.DefaultModelProblem;
|
||||
import org.apache.maven.model.building.ModelProblem;
|
||||
import org.apache.maven.model.building.ModelProblemUtils;
|
||||
import org.apache.maven.model.building.ModelSource;
|
||||
import org.apache.maven.model.building.Result;
|
||||
import org.apache.maven.model.building.UrlModelSource;
|
||||
import org.apache.maven.project.DuplicateProjectException;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuilder;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
import org.apache.maven.project.ProjectBuildingResult;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
import org.apache.maven.project.collector.MultiModuleCollectionStrategy;
|
||||
import org.apache.maven.project.collector.PomlessCollectionStrategy;
|
||||
import org.apache.maven.project.collector.RequestPomCollectionStrategy;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.codehaus.plexus.util.dag.CycleDetectedException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
|
||||
|
@ -71,15 +66,24 @@ import static java.util.Comparator.comparing;
|
|||
public class DefaultGraphBuilder
|
||||
implements GraphBuilder
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger( DefaultGraphBuilder.class );
|
||||
|
||||
private final BuildResumptionDataRepository buildResumptionDataRepository;
|
||||
private final PomlessCollectionStrategy pomlessCollectionStrategy;
|
||||
private final MultiModuleCollectionStrategy multiModuleCollectionStrategy;
|
||||
private final RequestPomCollectionStrategy requestPomCollectionStrategy;
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
protected ProjectBuilder projectBuilder;
|
||||
|
||||
@Inject
|
||||
private BuildResumptionDataRepository buildResumptionDataRepository;
|
||||
public DefaultGraphBuilder( BuildResumptionDataRepository buildResumptionDataRepository,
|
||||
PomlessCollectionStrategy pomlessCollectionStrategy,
|
||||
MultiModuleCollectionStrategy multiModuleCollectionStrategy,
|
||||
RequestPomCollectionStrategy requestPomCollectionStrategy )
|
||||
{
|
||||
this.buildResumptionDataRepository = buildResumptionDataRepository;
|
||||
this.pomlessCollectionStrategy = pomlessCollectionStrategy;
|
||||
this.multiModuleCollectionStrategy = multiModuleCollectionStrategy;
|
||||
this.requestPomCollectionStrategy = requestPomCollectionStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ProjectDependencyGraph> build( MavenSession session )
|
||||
|
@ -91,7 +95,7 @@ public class DefaultGraphBuilder
|
|||
if ( result == null )
|
||||
{
|
||||
final List<MavenProject> projects = getProjectsForMavenReactor( session );
|
||||
validateProjects( projects );
|
||||
validateProjects( projects, session.getRequest() );
|
||||
enrichRequestFromResumptionData( projects, session.getRequest() );
|
||||
result = reactorDependencyGraph( session, projects );
|
||||
}
|
||||
|
@ -133,6 +137,7 @@ public class DefaultGraphBuilder
|
|||
{
|
||||
ProjectDependencyGraph projectDependencyGraph = new DefaultProjectDependencyGraph( projects );
|
||||
List<MavenProject> activeProjects = projectDependencyGraph.getSortedProjects();
|
||||
activeProjects = trimProjectsToRequest( activeProjects, projectDependencyGraph, session.getRequest() );
|
||||
activeProjects = trimSelectedProjects( activeProjects, projectDependencyGraph, session.getRequest() );
|
||||
activeProjects = trimResumedProjects( activeProjects, projectDependencyGraph, session.getRequest() );
|
||||
activeProjects = trimExcludedProjects( activeProjects, session.getRequest() );
|
||||
|
@ -145,6 +150,26 @@ public class DefaultGraphBuilder
|
|||
return Result.success( projectDependencyGraph );
|
||||
}
|
||||
|
||||
private List<MavenProject> trimProjectsToRequest( List<MavenProject> activeProjects,
|
||||
ProjectDependencyGraph graph,
|
||||
MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
List<MavenProject> result = activeProjects;
|
||||
|
||||
if ( request.getPom() != null )
|
||||
{
|
||||
result = getProjectsInRequestScope( request, activeProjects );
|
||||
|
||||
List<MavenProject> sortedProjects = graph.getSortedProjects();
|
||||
result.sort( comparing( sortedProjects::indexOf ) );
|
||||
|
||||
result = includeAlsoMakeTransitively( result, request, graph );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MavenProject> trimSelectedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
|
||||
MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
|
@ -287,6 +312,28 @@ public class DefaultGraphBuilder
|
|||
}
|
||||
}
|
||||
|
||||
private List<MavenProject> getProjectsInRequestScope( MavenExecutionRequest request, List<MavenProject> projects )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
if ( request.getPom() == null )
|
||||
{
|
||||
return projects;
|
||||
}
|
||||
|
||||
MavenProject requestPomProject = projects.stream()
|
||||
.filter( project -> request.getPom().equals( project.getFile() ) )
|
||||
.findFirst()
|
||||
.orElseThrow( () -> new MavenExecutionException(
|
||||
"Could not find a project in reactor matching the request POM", request.getPom() ) );
|
||||
|
||||
List<MavenProject> modules = requestPomProject.getCollectedProjects() != null
|
||||
? requestPomProject.getCollectedProjects() : Collections.emptyList();
|
||||
|
||||
List<MavenProject> result = new ArrayList<>( modules );
|
||||
result.add( requestPomProject );
|
||||
return result;
|
||||
}
|
||||
|
||||
private String formatProjects( List<MavenProject> projects )
|
||||
{
|
||||
StringBuilder projectNames = new StringBuilder();
|
||||
|
@ -361,76 +408,32 @@ public class DefaultGraphBuilder
|
|||
throws ProjectBuildingException
|
||||
{
|
||||
MavenExecutionRequest request = session.getRequest();
|
||||
|
||||
request.getProjectBuildingRequest().setRepositorySession( session.getRepositorySession() );
|
||||
|
||||
List<MavenProject> projects = new ArrayList<>();
|
||||
|
||||
// We have no POM file.
|
||||
//
|
||||
// 1. Collect project for invocation without a POM.
|
||||
if ( request.getPom() == null )
|
||||
{
|
||||
ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
|
||||
MavenProject project = projectBuilder.build( modelSource, request.getProjectBuildingRequest() )
|
||||
.getProject();
|
||||
project.setExecutionRoot( true );
|
||||
projects.add( project );
|
||||
request.setProjectPresent( false );
|
||||
return pomlessCollectionStrategy.collectProjects( request );
|
||||
}
|
||||
|
||||
// 2. Collect projects for all modules in the multi-module project.
|
||||
List<MavenProject> projects = multiModuleCollectionStrategy.collectProjects( request );
|
||||
if ( !projects.isEmpty() )
|
||||
{
|
||||
return projects;
|
||||
}
|
||||
|
||||
List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
|
||||
collectProjects( projects, files, request );
|
||||
return projects;
|
||||
// 3. Collect projects for explicitly requested POM.
|
||||
return requestPomCollectionStrategy.collectProjects( request );
|
||||
}
|
||||
|
||||
private void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
|
||||
throws ProjectBuildingException
|
||||
{
|
||||
ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();
|
||||
|
||||
List<ProjectBuildingResult> results = projectBuilder.build( files, request.isRecursive(),
|
||||
projectBuildingRequest );
|
||||
|
||||
boolean problems = false;
|
||||
|
||||
for ( ProjectBuildingResult result : results )
|
||||
{
|
||||
projects.add( result.getProject() );
|
||||
|
||||
if ( !result.getProblems().isEmpty() && logger.isWarnEnabled() )
|
||||
{
|
||||
logger.warn( "" );
|
||||
logger.warn( "Some problems were encountered while building the effective model for "
|
||||
+ result.getProject().getId() );
|
||||
|
||||
for ( ModelProblem problem : result.getProblems() )
|
||||
{
|
||||
String loc = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
|
||||
logger.warn( problem.getMessage() + ( StringUtils.isNotEmpty( loc ) ? " @ " + loc : "" ) );
|
||||
}
|
||||
|
||||
problems = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( problems )
|
||||
{
|
||||
logger.warn( "" );
|
||||
logger.warn( "It is highly recommended to fix these problems"
|
||||
+ " because they threaten the stability of your build." );
|
||||
logger.warn( "" );
|
||||
logger.warn( "For this reason, future Maven versions might no"
|
||||
+ " longer support building such malformed projects." );
|
||||
logger.warn( "" );
|
||||
}
|
||||
}
|
||||
|
||||
private void validateProjects( List<MavenProject> projects )
|
||||
private void validateProjects( List<MavenProject> projects, MavenExecutionRequest request )
|
||||
throws MavenExecutionException
|
||||
{
|
||||
Map<String, MavenProject> projectsMap = new HashMap<>();
|
||||
|
||||
for ( MavenProject p : projects )
|
||||
List<MavenProject> projectsInRequestScope = getProjectsInRequestScope( request, projects );
|
||||
for ( MavenProject p : projectsInRequestScope )
|
||||
{
|
||||
String projectKey = ArtifactUtils.key( p.getGroupId(), p.getArtifactId(), p.getVersion() );
|
||||
|
||||
|
@ -449,9 +452,8 @@ public class DefaultGraphBuilder
|
|||
|
||||
if ( projectsMap.containsKey( pluginKey ) )
|
||||
{
|
||||
logger.warn( project.getName() + " uses " + plugin.getKey()
|
||||
+ " as extensions, which is not possible within the same reactor build. "
|
||||
+ "This plugin was pulled from the local repository!" );
|
||||
LOGGER.warn( "{} uses {} as extensions, which is not possible within the same reactor build. "
|
||||
+ "This plugin was pulled from the local repository!", project.getName(), plugin.getKey() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ public class DefaultModelBuildingListener
|
|||
catch ( PluginResolutionException | PluginManagerException | PluginVersionResolutionException e )
|
||||
{
|
||||
event.getProblems().add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
|
||||
.setMessage( "Unresolveable build extension: " + e.getMessage() )
|
||||
.setMessage( "Unresolvable build extension: " + e.getMessage() )
|
||||
.setException( e ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
package org.apache.maven.project.collector;
|
||||
|
||||
/*
|
||||
* 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 org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.model.building.ModelProblem;
|
||||
import org.apache.maven.model.building.ModelProblemUtils;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuilder;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
import org.apache.maven.project.ProjectBuildingResult;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility to collect projects for a given set of pom.xml files.
|
||||
*/
|
||||
@Named
|
||||
@Singleton
|
||||
public class DefaultProjectsCollector implements ProjectsCollector
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger( DefaultProjectsCollector.class );
|
||||
private final ProjectBuilder projectBuilder;
|
||||
|
||||
@Inject
|
||||
public DefaultProjectsCollector( ProjectBuilder projectBuilder )
|
||||
{
|
||||
this.projectBuilder = projectBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
|
||||
throws ProjectBuildingException
|
||||
{
|
||||
ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest();
|
||||
|
||||
List<ProjectBuildingResult> results = projectBuilder.build( files, request.isRecursive(),
|
||||
projectBuildingRequest );
|
||||
|
||||
boolean problems = false;
|
||||
|
||||
for ( ProjectBuildingResult result : results )
|
||||
{
|
||||
projects.add( result.getProject() );
|
||||
|
||||
if ( !result.getProblems().isEmpty() && LOGGER.isWarnEnabled() )
|
||||
{
|
||||
LOGGER.warn( "" );
|
||||
LOGGER.warn( "Some problems were encountered while building the effective model for {}",
|
||||
result.getProject().getId() );
|
||||
|
||||
for ( ModelProblem problem : result.getProblems() )
|
||||
{
|
||||
String loc = ModelProblemUtils.formatLocation( problem, result.getProjectId() );
|
||||
LOGGER.warn( "{}{}", problem.getMessage(), ( StringUtils.isNotEmpty( loc ) ? " @ " + loc : "" ) );
|
||||
}
|
||||
|
||||
problems = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( problems )
|
||||
{
|
||||
LOGGER.warn( "" );
|
||||
LOGGER.warn( "It is highly recommended to fix these problems"
|
||||
+ " because they threaten the stability of your build." );
|
||||
LOGGER.warn( "" );
|
||||
LOGGER.warn( "For this reason, future Maven versions might no"
|
||||
+ " longer support building such malformed projects." );
|
||||
LOGGER.warn( "" );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
package org.apache.maven.project.collector;
|
||||
|
||||
/*
|
||||
* 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 org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.model.building.ModelProblem;
|
||||
import org.apache.maven.model.locator.ModelLocator;
|
||||
import org.apache.maven.plugin.PluginManagerException;
|
||||
import org.apache.maven.plugin.PluginResolutionException;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
import org.apache.maven.project.ProjectBuildingResult;
|
||||
import org.eclipse.aether.resolution.ArtifactResolutionException;
|
||||
import org.eclipse.aether.transfer.ArtifactNotFoundException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Strategy for collecting Maven projects from the multi-module project root, even when executed in a submodule.
|
||||
*/
|
||||
@Named( "MultiModuleCollectionStrategy" )
|
||||
@Singleton
|
||||
public class MultiModuleCollectionStrategy implements ProjectCollectionStrategy
|
||||
{
|
||||
private final Logger logger = LoggerFactory.getLogger( getClass() );
|
||||
private final ModelLocator modelLocator;
|
||||
private final ProjectsCollector projectsCollector;
|
||||
|
||||
@Inject
|
||||
public MultiModuleCollectionStrategy( ModelLocator modelLocator, ProjectsCollector projectsCollector )
|
||||
{
|
||||
this.modelLocator = modelLocator;
|
||||
this.projectsCollector = projectsCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MavenProject> collectProjects( MavenExecutionRequest request ) throws ProjectBuildingException
|
||||
{
|
||||
File moduleProjectPomFile = getMultiModuleProjectPomFile( request );
|
||||
List<File> files = Collections.singletonList( moduleProjectPomFile.getAbsoluteFile() );
|
||||
try
|
||||
{
|
||||
List<MavenProject> projects = new ArrayList<>();
|
||||
projectsCollector.collectProjects( projects, files, request );
|
||||
boolean isRequestedProjectCollected = isRequestedProjectCollected( request, projects );
|
||||
if ( isRequestedProjectCollected )
|
||||
{
|
||||
return projects;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug( "Multi module project collection failed: {}"
|
||||
+ "Detected a POM file next to a .mvn folder in a parent directory ({}). "
|
||||
+ "Maven assumed that POM file to be the parent of the requested project ({}), but it turned "
|
||||
+ "out that it was not. Another project collection strategy will be executed as result.",
|
||||
System.lineSeparator(), moduleProjectPomFile.getAbsolutePath(),
|
||||
request.getPom().getAbsolutePath() );
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
catch ( ProjectBuildingException e )
|
||||
{
|
||||
boolean fallThrough = isModuleOutsideRequestScopeDependingOnPluginModule( request, e );
|
||||
|
||||
if ( fallThrough )
|
||||
{
|
||||
logger.debug( "Multi module project collection failed: {}"
|
||||
+ "Detected that one of the modules of this multi module project uses another module as "
|
||||
+ "plugin extension which still needed to be built. This is not possible within the same "
|
||||
+ "reactor build. Another project collection strategy will be executed as result.",
|
||||
System.lineSeparator() );
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private File getMultiModuleProjectPomFile( MavenExecutionRequest request )
|
||||
{
|
||||
if ( request.getPom().getParentFile().equals( request.getMultiModuleProjectDirectory() ) )
|
||||
{
|
||||
return request.getPom();
|
||||
}
|
||||
else
|
||||
{
|
||||
File multiModuleProjectPom = modelLocator.locatePom( request.getMultiModuleProjectDirectory() );
|
||||
if ( !multiModuleProjectPom.exists() )
|
||||
{
|
||||
logger.info( "Maven detected that the requested POM file is part of a multi module project, "
|
||||
+ "but could not find a pom.xml file in the multi module root directory: '"
|
||||
+ request.getMultiModuleProjectDirectory() + "'. " );
|
||||
logger.info( "The reactor is limited to all projects under: " + request.getPom().getParent() );
|
||||
return request.getPom();
|
||||
}
|
||||
|
||||
return multiModuleProjectPom;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* multiModuleProjectDirectory in MavenExecutionRequest is not always the parent of the request pom.
|
||||
* We should always check whether the request pom project is collected.
|
||||
* The integration tests for MNG-6223 are examples for this scenario.
|
||||
*
|
||||
* @return true if the collected projects contain the requested project (for example with -f)
|
||||
*/
|
||||
private boolean isRequestedProjectCollected( MavenExecutionRequest request, List<MavenProject> projects )
|
||||
{
|
||||
return projects.stream()
|
||||
.map( MavenProject::getFile )
|
||||
.anyMatch( request.getPom()::equals );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method finds out whether collecting projects failed because of the following scenario:
|
||||
* - A multi module project containing a module which is a plugin and another module which depends on it.
|
||||
* - Just the plugin is being built with the -f <pom> flag.
|
||||
* - Because of inter-module dependency collection, all projects in the multi-module project are collected.
|
||||
* - The plugin is not yet installed in a repository.
|
||||
*
|
||||
* Therefore the build fails because the plugin is not found and plugins cannot be built in the same session.
|
||||
*
|
||||
* The integration test for <a href="https://issues.apache.org/jira/browse/MNG-5572">MNG-5572</a> is an
|
||||
* example of this scenario.
|
||||
*
|
||||
* @return true if the module which fails to collect the inter-module plugin is not part of the build.
|
||||
*/
|
||||
private boolean isModuleOutsideRequestScopeDependingOnPluginModule( MavenExecutionRequest request,
|
||||
ProjectBuildingException exception )
|
||||
{
|
||||
return exception.getResults().stream()
|
||||
.map( ProjectBuildingResult::getProject )
|
||||
.filter( Objects::nonNull )
|
||||
.filter( project -> request.getPom().equals( project.getFile() ) )
|
||||
.findFirst()
|
||||
.map( requestPomProject ->
|
||||
{
|
||||
List<MavenProject> modules = requestPomProject.getCollectedProjects() != null
|
||||
? requestPomProject.getCollectedProjects() : Collections.emptyList();
|
||||
List<MavenProject> projectsInRequestScope = new ArrayList<>( modules );
|
||||
projectsInRequestScope.add( requestPomProject );
|
||||
|
||||
Predicate<ProjectBuildingResult> projectsOutsideOfRequestScope =
|
||||
pr -> !projectsInRequestScope.contains( pr.getProject() );
|
||||
|
||||
Predicate<Exception> pluginArtifactNotFoundException =
|
||||
exc -> exc instanceof PluginManagerException
|
||||
&& exc.getCause() instanceof PluginResolutionException
|
||||
&& exc.getCause().getCause() instanceof ArtifactResolutionException
|
||||
&& exc.getCause().getCause().getCause() instanceof ArtifactNotFoundException;
|
||||
|
||||
Predicate<Plugin> isPluginPartOfRequestScope = plugin -> projectsInRequestScope.stream()
|
||||
.anyMatch( project -> project.getGroupId().equals( plugin.getGroupId() )
|
||||
&& project.getArtifactId().equals( plugin.getArtifactId() )
|
||||
&& project.getVersion().equals( plugin.getVersion() ) );
|
||||
|
||||
return exception.getResults().stream()
|
||||
.filter( projectsOutsideOfRequestScope )
|
||||
.flatMap( projectBuildingResult -> projectBuildingResult.getProblems().stream() )
|
||||
.map( ModelProblem::getException )
|
||||
.filter( pluginArtifactNotFoundException )
|
||||
.map( exc -> ( ( PluginResolutionException ) exc.getCause() ).getPlugin() )
|
||||
.anyMatch( isPluginPartOfRequestScope );
|
||||
} ).orElse( false );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.apache.maven.project.collector;
|
||||
|
||||
/*
|
||||
* 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 org.apache.maven.DefaultMaven;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.model.building.ModelSource;
|
||||
import org.apache.maven.model.building.UrlModelSource;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuilder;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Strategy to collect projects for building when the Maven invocation is not in a folder that contains a pom.xml.
|
||||
*/
|
||||
@Named( "PomlessCollectionStrategy" )
|
||||
@Singleton
|
||||
public class PomlessCollectionStrategy
|
||||
implements ProjectCollectionStrategy
|
||||
{
|
||||
private final ProjectBuilder projectBuilder;
|
||||
|
||||
@Inject
|
||||
public PomlessCollectionStrategy( ProjectBuilder projectBuilder )
|
||||
{
|
||||
this.projectBuilder = projectBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MavenProject> collectProjects( final MavenExecutionRequest request )
|
||||
throws ProjectBuildingException
|
||||
{
|
||||
ProjectBuildingRequest buildingRequest = request.getProjectBuildingRequest();
|
||||
ModelSource modelSource = new UrlModelSource( DefaultMaven.class.getResource( "project/standalone.xml" ) );
|
||||
MavenProject project = projectBuilder.build( modelSource, buildingRequest ).getProject();
|
||||
project.setExecutionRoot( true );
|
||||
request.setProjectPresent( false );
|
||||
|
||||
final List<MavenProject> result = new ArrayList<>();
|
||||
result.add( project );
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.apache.maven.project.collector;
|
||||
|
||||
/*
|
||||
* 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 org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes strategies for finding projects that Maven could build.
|
||||
*/
|
||||
public interface ProjectCollectionStrategy
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws ProjectBuildingException
|
||||
*/
|
||||
List<MavenProject> collectProjects( final MavenExecutionRequest request )
|
||||
throws ProjectBuildingException;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.apache.maven.project.collector;
|
||||
|
||||
/*
|
||||
* 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 org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Facade to collect projects for a given set of pom.xml files.
|
||||
*/
|
||||
public interface ProjectsCollector
|
||||
{
|
||||
/**
|
||||
* Collect Maven projects from a list of POM files.
|
||||
* @param projects List that will be filled with the found projects.
|
||||
* @param files List of POM files.
|
||||
* @param request The {@link MavenExecutionRequest}
|
||||
* @throws ProjectBuildingException In case the POMs are not used.
|
||||
*/
|
||||
void collectProjects( List<MavenProject> projects, List<File> files, MavenExecutionRequest request )
|
||||
throws ProjectBuildingException;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package org.apache.maven.project.collector;
|
||||
|
||||
/*
|
||||
* 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 org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuildingException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Strategy to collect projects based on the <code>-f</code> CLI parameter or the pom.xml in the working directory.
|
||||
*/
|
||||
@Named( "RequestPomCollectionStrategy" )
|
||||
@Singleton
|
||||
public class RequestPomCollectionStrategy implements ProjectCollectionStrategy
|
||||
{
|
||||
private final ProjectsCollector projectsCollector;
|
||||
|
||||
@Inject
|
||||
public RequestPomCollectionStrategy( ProjectsCollector projectsCollector )
|
||||
{
|
||||
this.projectsCollector = projectsCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MavenProject> collectProjects( MavenExecutionRequest request ) throws ProjectBuildingException
|
||||
{
|
||||
List<File> files = Collections.singletonList( request.getPom().getAbsoluteFile() );
|
||||
List<MavenProject> projects = new ArrayList<>();
|
||||
projectsCollector.collectProjects( projects, files, request );
|
||||
return projects;
|
||||
}
|
||||
}
|
|
@ -116,6 +116,11 @@ public abstract class AbstractCoreMavenComponentTestCase
|
|||
.setPluginArtifactRepositories( getPluginArtifactRepositories() )
|
||||
.setGoals( Arrays.asList( "package" ) );
|
||||
|
||||
if ( pom != null )
|
||||
{
|
||||
request.setMultiModuleProjectDirectory( pom.getParentFile() );
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,37 +19,45 @@ package org.apache.maven.graph;
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.maven.execution.BuildResumptionDataRepository;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.execution.ProjectDependencyGraph;
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.model.Parent;
|
||||
import org.apache.maven.model.building.Result;
|
||||
import org.apache.maven.model.locator.DefaultModelLocator;
|
||||
import org.apache.maven.model.locator.ModelLocator;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.ProjectBuilder;
|
||||
import org.apache.maven.project.ProjectBuildingRequest;
|
||||
import org.apache.maven.project.ProjectBuildingResult;
|
||||
import org.apache.maven.project.collector.DefaultProjectsCollector;
|
||||
import org.apache.maven.project.collector.MultiModuleCollectionStrategy;
|
||||
import org.apache.maven.project.collector.PomlessCollectionStrategy;
|
||||
import org.apache.maven.project.collector.ProjectsCollector;
|
||||
import org.apache.maven.project.collector.RequestPomCollectionStrategy;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.function.Function.identity;
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static org.apache.maven.execution.MavenExecutionRequest.*;
|
||||
import static org.apache.maven.execution.MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM;
|
||||
import static org.apache.maven.execution.MavenExecutionRequest.REACTOR_MAKE_UPSTREAM;
|
||||
import static org.apache.maven.graph.DefaultGraphBuilderTest.ScenarioBuilder.scenario;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
@ -59,22 +67,39 @@ import static org.mockito.Mockito.when;
|
|||
@RunWith( Parameterized.class )
|
||||
public class DefaultGraphBuilderTest
|
||||
{
|
||||
/*
|
||||
The multi-module structure in this project is displayed as follows:
|
||||
|
||||
module-parent
|
||||
└─── module-independent (without parent declaration)
|
||||
module-a
|
||||
module-b (depends on module-a)
|
||||
module-c
|
||||
└─── module-c-1
|
||||
module-c-2 (depends on module-b)
|
||||
*/
|
||||
private static final String PARENT_MODULE = "module-parent";
|
||||
private static final String INDEPENDENT_MODULE = "module-independent";
|
||||
private static final String MODULE_A = "module-a";
|
||||
private static final String MODULE_B = "module-b"; // depends on module-a
|
||||
private static final String MODULE_C = "module-c"; // depends on module-b
|
||||
private static final String MODULE_B = "module-b";
|
||||
private static final String MODULE_C = "module-c";
|
||||
private static final String MODULE_C_1 = "module-c-1";
|
||||
private static final String MODULE_C_2 = "module-c-2";
|
||||
|
||||
@InjectMocks
|
||||
private DefaultGraphBuilder graphBuilder;
|
||||
|
||||
@Mock
|
||||
private ProjectBuilder projectBuilder;
|
||||
private final ProjectBuilder projectBuilder = mock( ProjectBuilder.class );
|
||||
private final MavenSession session = mock( MavenSession.class );
|
||||
private final MavenExecutionRequest mavenExecutionRequest = mock( MavenExecutionRequest.class );
|
||||
|
||||
@Mock
|
||||
private MavenSession session;
|
||||
private final ProjectsCollector projectsCollector = new DefaultProjectsCollector( projectBuilder );
|
||||
|
||||
@Mock
|
||||
private MavenExecutionRequest mavenExecutionRequest;
|
||||
// Not using mocks for these strategies - a mock would just copy the actual implementation.
|
||||
|
||||
private final ModelLocator modelLocator = new DefaultModelLocator();
|
||||
private final PomlessCollectionStrategy pomlessCollectionStrategy = new PomlessCollectionStrategy( projectBuilder );
|
||||
private final MultiModuleCollectionStrategy multiModuleCollectionStrategy = new MultiModuleCollectionStrategy( modelLocator, projectsCollector );
|
||||
private final RequestPomCollectionStrategy requestPomCollectionStrategy = new RequestPomCollectionStrategy( projectsCollector );
|
||||
|
||||
private Map<String, MavenProject> artifactIdProjectMap;
|
||||
|
||||
|
@ -85,73 +110,85 @@ public class DefaultGraphBuilderTest
|
|||
private final String parameterResumeFrom;
|
||||
private final String parameterMakeBehavior;
|
||||
private final List<String> parameterExpectedResult;
|
||||
private final File parameterRequestedPom;
|
||||
|
||||
@Parameters(name = "{index}. {0}")
|
||||
public static Collection<Object[]> parameters()
|
||||
{
|
||||
return asList(
|
||||
scenario( "Full reactor" )
|
||||
.expectResult( asList( INDEPENDENT_MODULE, MODULE_A, MODULE_B, MODULE_C ) ),
|
||||
scenario( "Full reactor in order" )
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_C_1, MODULE_A, MODULE_B, MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Selected project" )
|
||||
.selectedProjects( singletonList( MODULE_B ) )
|
||||
.expectResult( singletonList( MODULE_B ) ),
|
||||
.selectedProjects( MODULE_B )
|
||||
.expectResult( MODULE_B ),
|
||||
scenario( "Excluded project" )
|
||||
.excludedProjects( singletonList( MODULE_B ) )
|
||||
.expectResult( asList( INDEPENDENT_MODULE, MODULE_A, MODULE_C ) ),
|
||||
.excludedProjects( MODULE_B )
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_C_1, MODULE_A, MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Resuming from project" )
|
||||
.resumeFrom( MODULE_B )
|
||||
.expectResult( asList( MODULE_B, MODULE_C ) ),
|
||||
.expectResult( MODULE_B, MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Selected project with also make dependencies" )
|
||||
.selectedProjects( singletonList( MODULE_C ) )
|
||||
.selectedProjects( MODULE_C_2 )
|
||||
.makeBehavior( REACTOR_MAKE_UPSTREAM )
|
||||
.expectResult( asList( MODULE_A, MODULE_B, MODULE_C ) ),
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_A, MODULE_B, MODULE_C_2 ),
|
||||
scenario( "Selected project with also make dependents" )
|
||||
.selectedProjects( singletonList( MODULE_B ) )
|
||||
.selectedProjects( MODULE_B )
|
||||
.makeBehavior( REACTOR_MAKE_DOWNSTREAM )
|
||||
.expectResult( asList( MODULE_B, MODULE_C ) ),
|
||||
.expectResult( MODULE_B, MODULE_C_2 ),
|
||||
scenario( "Resuming from project with also make dependencies" )
|
||||
.makeBehavior( REACTOR_MAKE_UPSTREAM )
|
||||
.resumeFrom( MODULE_C )
|
||||
.expectResult( asList( MODULE_A, MODULE_B, MODULE_C ) ),
|
||||
scenario( "Selected project with resume from an also make dependency (MNG-4960 IT#1)" )
|
||||
.selectedProjects( singletonList( MODULE_C ) )
|
||||
.resumeFrom( MODULE_C_2 )
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_A, MODULE_B, MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Selected project with resume from and also make dependency (MNG-4960 IT#1)" )
|
||||
.selectedProjects( MODULE_C_2 )
|
||||
.resumeFrom( MODULE_B )
|
||||
.makeBehavior( REACTOR_MAKE_UPSTREAM )
|
||||
.expectResult( asList( MODULE_A, MODULE_B, MODULE_C ) ),
|
||||
scenario( "Selected project with resume from an also make dependent (MNG-4960 IT#2)" )
|
||||
.selectedProjects( singletonList( MODULE_B ) )
|
||||
.resumeFrom( MODULE_C )
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_A, MODULE_B, MODULE_C_2 ),
|
||||
scenario( "Selected project with resume from and also make dependent (MNG-4960 IT#2)" )
|
||||
.selectedProjects( MODULE_B )
|
||||
.resumeFrom( MODULE_C_2 )
|
||||
.makeBehavior( REACTOR_MAKE_DOWNSTREAM )
|
||||
.expectResult( singletonList( MODULE_C ) ),
|
||||
.expectResult( MODULE_C_2 ),
|
||||
scenario( "Excluding an also make dependency from selectedProject does take its transitive dependency" )
|
||||
.selectedProjects( singletonList( MODULE_C ) )
|
||||
.excludedProjects( singletonList( MODULE_B ) )
|
||||
.selectedProjects( MODULE_C_2 )
|
||||
.excludedProjects( MODULE_B )
|
||||
.makeBehavior( REACTOR_MAKE_UPSTREAM )
|
||||
.expectResult( asList( MODULE_A, MODULE_C ) ),
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_A, MODULE_C_2 ),
|
||||
scenario( "Excluding an also make dependency from resumeFrom does take its transitive dependency" )
|
||||
.resumeFrom( MODULE_C )
|
||||
.excludedProjects( singletonList( MODULE_B ) )
|
||||
.resumeFrom( MODULE_C_2 )
|
||||
.excludedProjects( MODULE_B )
|
||||
.makeBehavior( REACTOR_MAKE_UPSTREAM )
|
||||
.expectResult( asList( MODULE_A, MODULE_C ) ),
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_A, MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Resume from exclude project downstream" )
|
||||
.resumeFrom( MODULE_A )
|
||||
.excludedProjects( singletonList( MODULE_B ) )
|
||||
.expectResult( asList( MODULE_A, MODULE_C ) ),
|
||||
.excludedProjects( MODULE_B )
|
||||
.expectResult( MODULE_A, MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Exclude the project we are resuming from (as proposed in MNG-6676)" )
|
||||
.resumeFrom( MODULE_B )
|
||||
.excludedProjects( singletonList( MODULE_B ) )
|
||||
.expectResult( singletonList( MODULE_C ) ),
|
||||
.excludedProjects( MODULE_B )
|
||||
.expectResult( MODULE_C_2, INDEPENDENT_MODULE ),
|
||||
scenario( "Selected projects in wrong order are resumed correctly in order" )
|
||||
.selectedProjects( asList( MODULE_C, MODULE_B, MODULE_A ) )
|
||||
.selectedProjects( MODULE_C_2, MODULE_B, MODULE_A )
|
||||
.resumeFrom( MODULE_B )
|
||||
.expectResult( asList( MODULE_B, MODULE_C ) ),
|
||||
.expectResult( MODULE_B, MODULE_C_2 ),
|
||||
scenario( "Duplicate projects are filtered out" )
|
||||
.selectedProjects( asList( MODULE_A, MODULE_A ) )
|
||||
.expectResult( singletonList( MODULE_A ) )
|
||||
.selectedProjects( MODULE_A, MODULE_A )
|
||||
.expectResult( MODULE_A ),
|
||||
scenario( "Select reactor by specific pom" )
|
||||
.requestedPom( MODULE_C )
|
||||
.expectResult( MODULE_C, MODULE_C_1, MODULE_C_2 ),
|
||||
scenario( "Select reactor by specific pom with also make dependencies" )
|
||||
.requestedPom( MODULE_C )
|
||||
.makeBehavior( REACTOR_MAKE_UPSTREAM )
|
||||
.expectResult( PARENT_MODULE, MODULE_C, MODULE_C_1, MODULE_A, MODULE_B, MODULE_C_2 ),
|
||||
scenario( "Select reactor by specific pom with also make dependents" )
|
||||
.requestedPom( MODULE_B )
|
||||
.makeBehavior( REACTOR_MAKE_DOWNSTREAM )
|
||||
.expectResult( MODULE_B, MODULE_C_2 )
|
||||
);
|
||||
}
|
||||
|
||||
public DefaultGraphBuilderTest( String description, List<String> selectedProjects, List<String> excludedProjects, String resumedFrom, String makeBehavior, List<String> expectedReactorProjects )
|
||||
public DefaultGraphBuilderTest( String description, List<String> selectedProjects, List<String> excludedProjects, String resumedFrom, String makeBehavior, List<String> expectedReactorProjects, File requestedPom )
|
||||
{
|
||||
this.parameterDescription = description;
|
||||
this.parameterSelectedProjects = selectedProjects;
|
||||
|
@ -159,6 +196,7 @@ public class DefaultGraphBuilderTest
|
|||
this.parameterResumeFrom = resumedFrom;
|
||||
this.parameterMakeBehavior = makeBehavior;
|
||||
this.parameterExpectedResult = expectedReactorProjects;
|
||||
this.parameterRequestedPom = requestedPom;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -171,6 +209,7 @@ public class DefaultGraphBuilderTest
|
|||
when( mavenExecutionRequest.getSelectedProjects() ).thenReturn( selectedProjects );
|
||||
when( mavenExecutionRequest.getExcludedProjects() ).thenReturn( excludedProjects );
|
||||
when( mavenExecutionRequest.getMakeBehavior() ).thenReturn( parameterMakeBehavior );
|
||||
when( mavenExecutionRequest.getPom() ).thenReturn( parameterRequestedPom );
|
||||
if ( StringUtils.isNotEmpty( parameterResumeFrom ) )
|
||||
{
|
||||
when( mavenExecutionRequest.getResumeFrom() ).thenReturn( ":" + parameterResumeFrom );
|
||||
|
@ -190,40 +229,47 @@ public class DefaultGraphBuilderTest
|
|||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
MockitoAnnotations.initMocks( this );
|
||||
graphBuilder = new DefaultGraphBuilder(
|
||||
mock( BuildResumptionDataRepository.class ),
|
||||
pomlessCollectionStrategy,
|
||||
multiModuleCollectionStrategy,
|
||||
requestPomCollectionStrategy
|
||||
);
|
||||
|
||||
ProjectBuildingRequest projectBuildingRequest = mock( ProjectBuildingRequest.class );
|
||||
ProjectBuildingResult projectBuildingResult1 = mock( ProjectBuildingResult.class );
|
||||
ProjectBuildingResult projectBuildingResult2 = mock( ProjectBuildingResult.class );
|
||||
ProjectBuildingResult projectBuildingResult3 = mock( ProjectBuildingResult.class );
|
||||
ProjectBuildingResult projectBuildingResult4 = mock( ProjectBuildingResult.class );
|
||||
MavenProject projectIndependentModule = getMavenProject( "independent-module" );
|
||||
MavenProject projectModuleA = getMavenProject( "module-a" );
|
||||
MavenProject projectModuleB = getMavenProject( "module-b" );
|
||||
MavenProject projectModuleC = getMavenProject( "module-c" );
|
||||
projectModuleB.setDependencies( singletonList( toDependency( projectModuleA) ) );
|
||||
projectModuleC.setDependencies( singletonList( toDependency( projectModuleB) ) );
|
||||
// Create projects
|
||||
MavenProject projectParent = getMavenProject( PARENT_MODULE );
|
||||
MavenProject projectIndependentModule = getMavenProject( INDEPENDENT_MODULE );
|
||||
MavenProject projectModuleA = getMavenProject( MODULE_A, projectParent );
|
||||
MavenProject projectModuleB = getMavenProject( MODULE_B, projectParent );
|
||||
MavenProject projectModuleC = getMavenProject( MODULE_C, projectParent );
|
||||
MavenProject projectModuleC1 = getMavenProject( MODULE_C_1, projectModuleC );
|
||||
MavenProject projectModuleC2 = getMavenProject( MODULE_C_2, projectModuleC );
|
||||
|
||||
artifactIdProjectMap = Stream.of( projectParent, projectIndependentModule, projectModuleA, projectModuleB, projectModuleC, projectModuleC1, projectModuleC2 )
|
||||
.collect( Collectors.toMap( MavenProject::getArtifactId, identity() ) );
|
||||
|
||||
// Set dependencies and modules
|
||||
projectModuleB.setDependencies( singletonList( toDependency( projectModuleA ) ) );
|
||||
projectModuleC2.setDependencies( singletonList( toDependency( projectModuleB ) ) );
|
||||
projectParent.setCollectedProjects( asList( projectIndependentModule, projectModuleA, projectModuleB, projectModuleC, projectModuleC1, projectModuleC2 ) );
|
||||
projectModuleC.setCollectedProjects( asList( projectModuleC1, projectModuleC2 ) );
|
||||
|
||||
// Set up needed mocks
|
||||
when( session.getRequest() ).thenReturn( mavenExecutionRequest );
|
||||
when( session.getProjects() ).thenReturn( null ); // needed, otherwise it will be an empty list by default
|
||||
when( mavenExecutionRequest.getProjectBuildingRequest() ).thenReturn( mock( ProjectBuildingRequest.class ) );
|
||||
List<ProjectBuildingResult> projectBuildingResults = createProjectBuildingResultMocks( artifactIdProjectMap.values() );
|
||||
when( projectBuilder.build( anyList(), anyBoolean(), any( ProjectBuildingRequest.class ) ) ).thenReturn( projectBuildingResults );
|
||||
}
|
||||
|
||||
when( mavenExecutionRequest.getProjectBuildingRequest() ).thenReturn( projectBuildingRequest );
|
||||
when( mavenExecutionRequest.getPom() ).thenReturn( new File( "/tmp/unit-test" ) );
|
||||
|
||||
when( projectBuildingResult1.getProject() ).thenReturn( projectIndependentModule );
|
||||
when( projectBuildingResult2.getProject() ).thenReturn( projectModuleA );
|
||||
when( projectBuildingResult3.getProject() ).thenReturn( projectModuleB );
|
||||
when( projectBuildingResult4.getProject() ).thenReturn( projectModuleC );
|
||||
|
||||
when( projectBuilder.build( anyList(), anyBoolean(), any( ProjectBuildingRequest.class ) ) )
|
||||
.thenReturn( asList( projectBuildingResult1, projectBuildingResult2, projectBuildingResult3, projectBuildingResult4 ) );
|
||||
|
||||
artifactIdProjectMap = ImmutableMap.of(
|
||||
INDEPENDENT_MODULE, projectIndependentModule,
|
||||
MODULE_A, projectModuleA,
|
||||
MODULE_B, projectModuleB,
|
||||
MODULE_C, projectModuleC
|
||||
);
|
||||
private MavenProject getMavenProject( String artifactId, MavenProject parentProject )
|
||||
{
|
||||
MavenProject project = getMavenProject( artifactId );
|
||||
Parent parent = new Parent();
|
||||
parent.setGroupId( parentProject.getGroupId() );
|
||||
parent.setArtifactId( parentProject.getArtifactId() );
|
||||
project.getModel().setParent( parent );
|
||||
return project;
|
||||
}
|
||||
|
||||
private MavenProject getMavenProject( String artifactId )
|
||||
|
@ -232,6 +278,8 @@ public class DefaultGraphBuilderTest
|
|||
mavenProject.setGroupId( "unittest" );
|
||||
mavenProject.setArtifactId( artifactId );
|
||||
mavenProject.setVersion( "1.0" );
|
||||
mavenProject.setPomFile( new File ( artifactId, "pom.xml" ) );
|
||||
mavenProject.setCollectedProjects( new ArrayList<>() );
|
||||
return mavenProject;
|
||||
}
|
||||
|
||||
|
@ -244,6 +292,17 @@ public class DefaultGraphBuilderTest
|
|||
return dependency;
|
||||
}
|
||||
|
||||
private List<ProjectBuildingResult> createProjectBuildingResultMocks( Collection<MavenProject> projects )
|
||||
{
|
||||
return projects.stream()
|
||||
.map( project -> {
|
||||
ProjectBuildingResult result = mock( ProjectBuildingResult.class );
|
||||
when( result.getProject() ).thenReturn( project );
|
||||
return result;
|
||||
} )
|
||||
.collect( Collectors.toList() );
|
||||
}
|
||||
|
||||
static class ScenarioBuilder
|
||||
{
|
||||
private String description;
|
||||
|
@ -251,6 +310,7 @@ public class DefaultGraphBuilderTest
|
|||
private List<String> excludedProjects = emptyList();
|
||||
private String resumeFrom = "";
|
||||
private String makeBehavior = "";
|
||||
private File requestedPom = new File( PARENT_MODULE, "pom.xml" );
|
||||
|
||||
private ScenarioBuilder() { }
|
||||
|
||||
|
@ -261,15 +321,15 @@ public class DefaultGraphBuilderTest
|
|||
return scenarioBuilder;
|
||||
}
|
||||
|
||||
public ScenarioBuilder selectedProjects( List<String> selectedProjects )
|
||||
public ScenarioBuilder selectedProjects( String... selectedProjects )
|
||||
{
|
||||
this.selectedProjects = selectedProjects;
|
||||
this.selectedProjects = asList( selectedProjects );
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScenarioBuilder excludedProjects( List<String> excludedProjects )
|
||||
public ScenarioBuilder excludedProjects( String... excludedProjects )
|
||||
{
|
||||
this.excludedProjects = excludedProjects;
|
||||
this.excludedProjects = asList( excludedProjects );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -285,10 +345,16 @@ public class DefaultGraphBuilderTest
|
|||
return this;
|
||||
}
|
||||
|
||||
public Object[] expectResult( List<String> expectedReactorProjects )
|
||||
public ScenarioBuilder requestedPom( String requestedPom )
|
||||
{
|
||||
this.requestedPom = new File( requestedPom, "pom.xml" );
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object[] expectResult( String... expectedReactorProjects )
|
||||
{
|
||||
return new Object[] {
|
||||
description, selectedProjects, excludedProjects, resumeFrom, makeBehavior, expectedReactorProjects
|
||||
description, selectedProjects, excludedProjects, resumeFrom, makeBehavior, asList( expectedReactorProjects ), requestedPom
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue