[MNG-4633] Reactor artifact resolution in weave mode

Resolves artifacts from within reactor build.
No longer requires artifacts to be present in local repository before building weave mode ;)

git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@935334 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Kristian Rosenvold 2010-04-18 11:36:37 +00:00
parent e3c7c2633d
commit 69c68d06c5
12 changed files with 377 additions and 213 deletions

View File

@ -42,7 +42,7 @@ import org.apache.maven.repository.RepositorySystem;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
@Component(role=ProjectDependenciesResolver.class)
@Component(role = ProjectDependenciesResolver.class)
public class DefaultProjectDependenciesResolver
implements ProjectDependenciesResolver
{
@ -63,18 +63,31 @@ public class DefaultProjectDependenciesResolver
Collection<String> scopesToResolve, MavenSession session )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return resolve( Collections.singleton( project ), scopesToCollect, scopesToResolve, session );
Set<MavenProject> mavenProjects = Collections.singleton( project );
return resolveImpl( mavenProjects, scopesToCollect, scopesToResolve, session,
getIgnorableArtifacts( mavenProjects ) );
}
public Set<Artifact> resolve( Collection<? extends MavenProject> projects, Collection<String> scopesToResolve,
MavenSession session )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return resolve( projects, null, scopesToResolve, session );
return resolveImpl( projects, null, scopesToResolve, session, getIgnorableArtifacts( projects ) );
}
public Set<Artifact> resolve( Collection<? extends MavenProject> projects, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session )
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
Set<Artifact> ignoreableArtifacts )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return resolveImpl( Collections.singleton( project ), scopesToCollect, scopesToResolve, session,
getIgnorableArtifacts( ignoreableArtifacts ) );
}
private Set<Artifact> resolveImpl( Collection<? extends MavenProject> projects, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
Set<String> projectIds )
throws ArtifactResolutionException, ArtifactNotFoundException
{
Set<Artifact> resolved = new LinkedHashSet<Artifact>();
@ -84,18 +97,18 @@ public class DefaultProjectDependenciesResolver
return resolved;
}
if ( ( scopesToCollect == null || scopesToCollect.isEmpty() )
&& ( scopesToResolve == null || scopesToResolve.isEmpty() ) )
if ( ( scopesToCollect == null || scopesToCollect.isEmpty() ) &&
( scopesToResolve == null || scopesToResolve.isEmpty() ) )
{
return resolved;
}
/*
Logic for transitve global exclusions
List<String> exclusions = new ArrayList<String>();
for ( Dependency d : project.getDependencies() )
{
if ( d.getExclusions() != null )
@ -106,10 +119,10 @@ public class DefaultProjectDependenciesResolver
}
}
}
ArtifactFilter scopeFilter = new ScopeArtifactFilter( scope );
ArtifactFilter filter;
ArtifactFilter filter;
if ( ! exclusions.isEmpty() )
{
@ -118,7 +131,7 @@ public class DefaultProjectDependenciesResolver
else
{
filter = scopeFilter;
}
}
*/
CumulativeScopeArtifactFilter resolutionScopeFilter = new CumulativeScopeArtifactFilter( scopesToResolve );
@ -126,22 +139,16 @@ public class DefaultProjectDependenciesResolver
CumulativeScopeArtifactFilter collectionScopeFilter = new CumulativeScopeArtifactFilter( scopesToCollect );
collectionScopeFilter = new CumulativeScopeArtifactFilter( collectionScopeFilter, resolutionScopeFilter );
ArtifactResolutionRequest request = new ArtifactResolutionRequest()
.setResolveRoot( false )
.setResolveTransitively( true )
.setCollectionFilter( collectionScopeFilter )
.setResolutionFilter( resolutionScopeFilter )
.setLocalRepository( session.getLocalRepository() )
.setOffline( session.isOffline() )
.setForceUpdate( session.getRequest().isUpdateSnapshots() )
.setCache( session.getRepositoryCache() );
ArtifactResolutionRequest request =
new ArtifactResolutionRequest().setResolveRoot( false ).setResolveTransitively( true ).setCollectionFilter(
collectionScopeFilter ).setResolutionFilter( resolutionScopeFilter ).setLocalRepository(
session.getLocalRepository() ).setOffline( session.isOffline() ).setForceUpdate(
session.getRequest().isUpdateSnapshots() ).setCache( session.getRepositoryCache() );
request.setTransferListener( session.getRequest().getTransferListener() );
request.setServers( session.getRequest().getServers() );
request.setMirrors( session.getRequest().getMirrors() );
request.setProxies( session.getRequest().getProxies() );
Set<String> projectIds = null;
for ( MavenProject project : projects )
{
request.setArtifact( new ProjectArtifact( project ) );
@ -157,16 +164,6 @@ public class DefaultProjectDependenciesResolver
}
catch ( MultipleArtifactsNotFoundException e )
{
if ( projectIds == null )
{
projectIds = new HashSet<String>( projects.size() * 2 );
for ( MavenProject p : projects )
{
String key = ArtifactUtils.key( p.getGroupId(), p.getArtifactId(), p.getVersion() );
projectIds.add( key );
}
}
Collection<Artifact> missing = new HashSet<Artifact>( e.getMissingArtifacts() );
@ -191,4 +188,29 @@ public class DefaultProjectDependenciesResolver
return resolved;
}
private Set<String> getIgnorableArtifacts( Collection<? extends MavenProject> projects )
{
Set<String> projectIds = new HashSet<String>( projects.size() * 2 );
for ( MavenProject p : projects )
{
String key = ArtifactUtils.key( p.getGroupId(), p.getArtifactId(), p.getVersion() );
projectIds.add( key );
}
return projectIds;
}
private Set<String> getIgnorableArtifacts( Iterable<Artifact> artifactIterable )
{
Set<String> projectIds = new HashSet<String>();
for ( Artifact artifact : artifactIterable )
{
String key = ArtifactUtils.key( artifact );
projectIds.add( key );
}
return projectIds;
}
}

View File

@ -33,10 +33,10 @@ public interface ProjectDependenciesResolver
/**
* Resolves the transitive dependencies of the specified project.
*
* @param project The project whose dependencies should be resolved, must not be {@code null}.
*
* @param project The project whose dependencies should be resolved, must not be {@code null}.
* @param scopesToResolve The dependency scopes that should be resolved, may be {@code null}.
* @param session The current build session, must not be {@code null}.
* @param session The current build session, must not be {@code null}.
* @return The transitive dependencies of the specified project that match the requested scopes, never {@code null}.
*/
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToResolve, MavenSession session )
@ -44,26 +44,42 @@ public interface ProjectDependenciesResolver
/**
* Resolves the transitive dependencies of the specified project.
*
* @param project The project whose dependencies should be resolved, must not be {@code null}.
*
* @param project The project whose dependencies should be resolved, must not be {@code null}.
* @param scopesToCollect The dependency scopes that should be collected, may be {@code null}.
* @param scopesToResolve The dependency scopes that should be collected and also resolved, may be {@code null}.
* @param session The current build session, must not be {@code null}.
* @param session The current build session, must not be {@code null}.
* @return The transitive dependencies of the specified project that match the requested scopes, never {@code null}.
*/
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session )
throws ArtifactResolutionException, ArtifactNotFoundException;
/**
* Resolves the transitive dependencies of the specified project.
*
* @param project The project whose dependencies should be resolved, must not be {@code null}.
* @param scopesToCollect The dependency scopes that should be collected, may be {@code null}.
* @param scopesToResolve The dependency scopes that should be collected and also resolved, may be {@code null}.
* @param session The current build session, must not be {@code null}.
* @param ignoreableArtifacts Artifacts that need not be resolved
* @return The transitive dependencies of the specified project that match the requested scopes, never {@code null}.
*/
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
Set<Artifact> ignoreableArtifacts )
throws ArtifactResolutionException, ArtifactNotFoundException;
/**
* Resolves the transitive dependencies of the specified projects. Note that dependencies which can't be resolved
* from any repository but are present among the set of specified projects will not cause an exception. Instead,
* those unresolved artifacts will be returned in the result set, allowing the caller to take special care of
* artifacts that haven't been build yet.
*
*
* @param projects The projects whose dependencies should be resolved, may be {@code null}.
* @param scopes The dependency scopes that should be resolved, may be {@code null}.
* @param session The current build session, must not be {@code null}.
* @param scopes The dependency scopes that should be resolved, may be {@code null}.
* @param session The current build session, must not be {@code null}.
* @return The transitive dependencies of the specified projects that match the requested scopes, never {@code null}
* .
*/

View File

@ -14,11 +14,15 @@
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.BuildFailure;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.*;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
@ -27,6 +31,8 @@ import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import java.util.Set;
/**
* Common code that is shared by the LifecycleModuleBuilder and the LifeCycleWeaveBuilder
*
@ -63,7 +69,8 @@ public class BuilderCommon
this.lifecycleDependencyResolver = lifecycleDependencyResolver;
}
public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject project, TaskSegment taskSegment )
public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject project, TaskSegment taskSegment,
Set<Artifact> projectArtifacts )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException,
@ -78,13 +85,14 @@ public class BuilderCommon
// this later by looking at the build plan. Would be better to just batch download everything required
// by the reactor.
lifecycleDependencyResolver.resolveDependencies( taskSegment.isAggregating(), project, session, executionPlan );
lifecycleDependencyResolver.resolveDependencies( taskSegment.isAggregating(), project, session, executionPlan,
projectArtifacts );
return executionPlan;
}
public void handleBuildError( final ReactorContext buildContext, final MavenSession rootSession,
final MavenProject mavenProject, final Exception e, final long buildStartTime )
final MavenProject mavenProject, final Exception e, final long buildStartTime )
{
buildContext.getResult().addException( e );

View File

@ -62,11 +62,12 @@ public class LifecycleDependencyResolver
}
public void resolveDependencies( boolean aggregating, MavenProject currentProject,
MavenSession sessionForThisModule, MavenExecutionPlan executionPlan )
MavenSession sessionForThisModule, MavenExecutionPlan executionPlan,
Set<Artifact> projectArtifacts )
throws LifecycleExecutionException
{
List<MavenProject> projectsToResolve = getProjects( currentProject, sessionForThisModule, aggregating );
resolveDependencies( aggregating, sessionForThisModule, executionPlan, projectsToResolve );
resolveDependencies( aggregating, sessionForThisModule, executionPlan, projectsToResolve, projectArtifacts );
}
public static List<MavenProject> getProjects( MavenProject project, MavenSession session, boolean aggregator )
@ -88,8 +89,8 @@ public class LifecycleDependencyResolver
if ( dependenctContext.isSameButUpdatedProject( session ) )
{
resolveProjectDependencies( dependenctContext.getLastProject(), dependenctContext.getScopesToCollect(),
dependenctContext.getScopesToResolve(), session,
dependenctContext.isAggregating() );
dependenctContext.getScopesToResolve(), session,
dependenctContext.isAggregating(), new HashSet<Artifact>() );
}
dependenctContext.setLastProject( session.getCurrentProject() );
@ -97,30 +98,25 @@ public class LifecycleDependencyResolver
}
private void resolveDependencies( boolean aggregating, MavenSession session, MavenExecutionPlan executionPlan,
List<MavenProject> projectsToResolve )
List<MavenProject> projectsToResolve, Set<Artifact> projectArtifacts )
throws LifecycleExecutionException
{
for ( MavenProject project : projectsToResolve )
{
resolveDependencies( project, aggregating, session, executionPlan );
resolveProjectDependencies( project, executionPlan.getRequiredCollectionScopes(),
executionPlan.getRequiredResolutionScopes(), session, aggregating,
projectArtifacts );
}
}
private void resolveDependencies( MavenProject project, boolean aggregating, MavenSession session,
MavenExecutionPlan executionPlan )
throws LifecycleExecutionException
{
resolveProjectDependencies( project, executionPlan.getRequiredCollectionScopes(),
executionPlan.getRequiredResolutionScopes(), session, aggregating );
}
private void resolveProjectDependencies( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
boolean aggregating )
Collection<String> scopesToResolve, MavenSession session,
boolean aggregating, Set<Artifact> projectArtifacts )
throws LifecycleExecutionException
{
Set<Artifact> artifacts =
getProjectDependencies( project, scopesToCollect, scopesToResolve, session, aggregating );
getProjectDependencies( project, scopesToCollect, scopesToResolve, session, aggregating,
projectArtifacts );
updateProjectArtifacts( project, artifacts );
}
@ -136,7 +132,7 @@ public class LifecycleDependencyResolver
private Set<Artifact> getProjectDependencies( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
boolean aggregating )
boolean aggregating, Set<Artifact> projectArtifacts )
throws LifecycleExecutionException
{
Set<Artifact> artifacts;
@ -144,7 +140,8 @@ public class LifecycleDependencyResolver
{
try
{
artifacts = projectDependenciesResolver.resolve( project, scopesToCollect, scopesToResolve, session );
artifacts = projectDependenciesResolver.resolve( project , scopesToCollect,
scopesToResolve, session, projectArtifacts );
}
catch ( MultipleArtifactsNotFoundException e )
{
@ -153,24 +150,7 @@ public class LifecycleDependencyResolver
* plugins that require dependency resolution although they usually run in phases of the build where project
* artifacts haven't been assembled yet. The prime example of this is "mvn release:prepare".
*/
if ( aggregating && areAllArtifactsInReactor( session.getProjects(), e.getMissingArtifacts() ) )
{
logger.warn( "The following artifacts could not be resolved at this point of the build" +
" but seem to be part of the reactor:" );
for ( Artifact artifact : e.getMissingArtifacts() )
{
logger.warn( "o " + artifact.getId() );
}
logger.warn( "Try running the build up to the lifecycle phase \"package\"" );
artifacts = new LinkedHashSet<Artifact>( e.getResolvedArtifacts() );
}
else
{
throw e;
}
artifacts = handleException( session, aggregating, e );
}
return artifacts;
@ -187,6 +167,36 @@ public class LifecycleDependencyResolver
}
private Set<Artifact> handleException( MavenSession session, boolean aggregating,
MultipleArtifactsNotFoundException e )
throws MultipleArtifactsNotFoundException
{
Set<Artifact> artifacts;/*
* MNG-2277, the check below compensates for our bad plugin support where we ended up with aggregator
* plugins that require dependency resolution although they usually run in phases of the build where project
* artifacts haven't been assembled yet. The prime example of this is "mvn release:prepare".
*/
if ( aggregating && areAllArtifactsInReactor( session.getProjects(), e.getMissingArtifacts() ) )
{
logger.warn( "The following artifacts could not be resolved at this point of the build" +
" but seem to be part of the reactor:" );
for ( Artifact artifact : e.getMissingArtifacts() )
{
logger.warn( "o " + artifact.getId() );
}
logger.warn( "Try running the build up to the lifecycle phase \"package\"" );
artifacts = new LinkedHashSet<Artifact>( e.getResolvedArtifacts() );
}
else
{
throw e;
}
return artifacts;
}
private Set<Artifact> getDependencyArtifacts( MavenProject project, Set<Artifact> artifacts )
{
Set<String> directDependencies = new HashSet<String>( project.getDependencies().size() * 2 );

View File

@ -86,27 +86,61 @@ public class LifecycleExecutionPlanCalculatorImpl
Set<String> requiredDependencyResolutionScopes = new TreeSet<String>();
Set<String> requiredDependencyCollectionScopes = new TreeSet<String>();
final List<MojoExecution> executions =
calculateExecutionPlan( session, project, tasks, requiredDependencyResolutionScopes,
requiredDependencyCollectionScopes );
lifecyclePluginResolver.resolveMissingPluginVersions( project, session );
final List<MojoExecution> executions = calculateMojoExecutions( session, project, tasks );
setupMojoExections( session, project, requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
executions );
final List<ExecutionPlanItem> planItem = defaultLifeCycles.createExecutionPlanItem( project, executions );
return new MavenExecutionPlan( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
planItem, defaultLifeCycles );
return new MavenExecutionPlan( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes, planItem,
defaultLifeCycles );
}
public List<MojoExecution> calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks,
Set<String> requiredDependencyResolutionScopes,
Set<String> requiredDependencyCollectionScopes )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
private void setupMojoExections( MavenSession session, MavenProject project,
Set<String> requiredDependencyResolutionScopes,
Set<String> requiredDependencyCollectionScopes,
List<MojoExecution> mojoExecutions )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, InvalidPluginDescriptorException, NoPluginFoundForPrefixException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
{
lifecyclePluginResolver.resolveMissingPluginVersions( project, session );
for ( MojoExecution mojoExecution : mojoExecutions )
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
if ( mojoDescriptor == null )
{
mojoDescriptor = pluginManager.getMojoDescriptor( mojoExecution.getPlugin(), mojoExecution.getGoal(),
DefaultRepositoryRequest.getRepositoryRequest(
session, project ) );
mojoExecution.setMojoDescriptor( mojoDescriptor );
}
populateMojoExecutionConfiguration( project, mojoExecution,
MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) );
finalizeMojoConfiguration( mojoExecution );
calculateForkedExecutions( mojoExecution, session, project, new HashSet<MojoDescriptor>() );
collectDependencyRequirements( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
mojoExecution );
}
}
private List<MojoExecution> calculateMojoExecutions( MavenSession session, MavenProject project,
List<Object> tasks )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException, LifecyclePhaseNotFoundException
{
final List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
for ( Object task : tasks )
{
@ -138,31 +172,6 @@ public class LifecycleExecutionPlanCalculatorImpl
throw new IllegalStateException( "unexpected task " + task );
}
}
for ( MojoExecution mojoExecution : mojoExecutions )
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( mojoDescriptor == null )
{
mojoDescriptor = pluginManager.getMojoDescriptor( mojoExecution.getPlugin(), mojoExecution.getGoal(),
DefaultRepositoryRequest.getRepositoryRequest(
session, project ) );
mojoExecution.setMojoDescriptor( mojoDescriptor );
}
populateMojoExecutionConfiguration( project, mojoExecution,
MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) );
finalizeMojoConfiguration( mojoExecution );
calculateForkedExecutions( mojoExecution, session, project, new HashSet<MojoDescriptor>() );
collectDependencyRequirements( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
mojoExecution );
}
return mojoExecutions;
}

View File

@ -15,6 +15,7 @@
package org.apache.maven.lifecycle.internal;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.BuildSuccess;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.MavenSession;
@ -23,6 +24,8 @@ import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import java.util.HashSet;
/**
* Builds one or more lifecycles for a full module
*
@ -72,7 +75,8 @@ public class LifecycleModuleBuilder
eventCatapult.fire( ExecutionEvent.Type.ProjectStarted, session, null );
BuilderCommon.attachToThread( currentProject );
MavenExecutionPlan executionPlan = builderCommon.resolveBuildPlan( session, currentProject, taskSegment );
MavenExecutionPlan executionPlan =
builderCommon.resolveBuildPlan( session, currentProject, taskSegment, new HashSet<Artifact>() );
DependencyContext dependencyContext = new DependencyContext( executionPlan, isAggregating );
mojoExecutor.execute( session, executionPlan.getMojoExecutions(), reactorContext.getProjectIndex(),

View File

@ -29,8 +29,8 @@ import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -72,14 +72,10 @@ public class LifecycleWeaveBuilder
@Requirement
private Logger logger;
@Requirement
private LifecycleDependencyResolver lifecycleDependencyResolver;
@Requirement
private ExecutionEventCatapult eventCatapult;
private final Map<MavenProject, MavenExecutionPlan> executionPlans =
Collections.synchronizedMap( new HashMap<MavenProject, MavenExecutionPlan>() );
private Map<MavenProject, MavenExecutionPlan> executionPlans = new HashMap<MavenProject, MavenExecutionPlan>( );
@SuppressWarnings({"UnusedDeclaration"})
@ -87,9 +83,8 @@ public class LifecycleWeaveBuilder
{
}
public LifecycleWeaveBuilder( MojoExecutor mojoExecutor, BuilderCommon builderCommon, Logger logger,
LifecycleDependencyResolver lifecycleDependencyResolver,
ExecutionEventCatapult eventCatapult )
public LifecycleWeaveBuilder(MojoExecutor mojoExecutor, BuilderCommon builderCommon, Logger logger,
ExecutionEventCatapult eventCatapult)
{
this.mojoExecutor = mojoExecutor;
this.builderCommon = builderCommon;
@ -110,14 +105,32 @@ public class LifecycleWeaveBuilder
for ( TaskSegment taskSegment : taskSegments )
{
ProjectBuildList segmentChunks = projectBuilds.getByTaskSegment( taskSegment );
ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( segmentChunks, System.out );
ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( segmentChunks, System.out );
Set<String> projectArtifacts = new HashSet<String>();
Set<Artifact> projectArtifactsA = new HashSet<Artifact>();
for (ProjectSegment segmentChunk : segmentChunks) {
Artifact artifact = segmentChunk.getProject().getArtifact();
if (artifact != null) {
projectArtifacts.add( ArtifactUtils.key(artifact));
projectArtifactsA.add( artifact);
}
}
for ( ProjectSegment projectBuild : segmentChunks )
{
try
{
MavenExecutionPlan executionPlan =
builderCommon.resolveBuildPlan( projectBuild.getSession(), projectBuild.getProject(),
projectBuild.getTaskSegment() );
projectBuild.getTaskSegment(), projectArtifactsA );
for (Artifact dependency : projectBuild.getProject().getDependencyArtifacts()) {
String s = ArtifactUtils.key(dependency);
if ( projectArtifacts.contains(s)){
dependency.setFile( null);
dependency.setResolved( false);
dependency.setRepository( null);
}
}
executionPlans.put( projectBuild.getProject(), executionPlan );
DependencyContext dependencyContext =
new DependencyContext( executionPlan, projectBuild.getTaskSegment().isAggregating() );
@ -182,8 +195,7 @@ public class LifecycleWeaveBuilder
try
{
while ( current != null && !reactorBuildStatus.isHalted() &&
!reactorBuildStatus.isBlackListed( projectBuild.getProject() ) )
while (current != null && !reactorBuildStatus.isHaltedOrBlacklisted( projectBuild.getProject() ))
{
PhaseRecorder phaseRecorder = new PhaseRecorder( projectBuild.getProject() );
@ -191,19 +203,7 @@ public class LifecycleWeaveBuilder
concurrentBuildLogger.createBuildLogItem( projectBuild.getProject(), current );
final Schedule schedule = current.getSchedule();
if ( schedule != null && schedule.isMojoSynchronized() )
{
synchronized ( current.getPlugin() )
{
buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
phaseRecorder );
}
}
else
{
buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
phaseRecorder );
}
buildExecutionPlanItem(current, phaseRecorder, schedule, reactorContext, projectBuild, dependencyContext);
current.setComplete();
builtLogItem.setComplete();
@ -212,62 +212,12 @@ public class LifecycleWeaveBuilder
if ( nextPlanItem != null )
{
boolean mustReResolved = false;
final Schedule scheduleOfNext = nextPlanItem.getSchedule();
if ( scheduleOfNext == null || !scheduleOfNext.isParallel() )
{
for ( MavenProject upstreamProject : projectBuild.getImmediateUpstreamProjects() )
{
final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
final String nextPhase = nextPlanItem.getLifecyclePhase();
final ExecutionPlanItem inSchedule = upstreamPlan.findLastInPhase( nextPhase );
if ( inSchedule != null )
{
if ( upstreamPhaseModifiesArtifactResolutionState( inSchedule ) )
{
String key = ArtifactUtils.key( upstreamProject.getGroupId(),
upstreamProject.getArtifactId(),
upstreamProject.getVersion() );
final Set<Artifact> deps =
projectBuild.getProject().getDependencyArtifacts();
for ( Artifact dep : deps )
{
String depKey =
ArtifactUtils.key( dep.getGroupId(), dep.getArtifactId(),
dep.getVersion() );
if ( key.equals( depKey ) )
{
dep.setResolved( false );
mustReResolved = true;
}
}
}
long startWait = System.currentTimeMillis();
inSchedule.waitUntilDone();
builtLogItem.addWait( upstreamProject, inSchedule, startWait );
}
else if ( !upstreamPlan.containsPhase( nextPhase ) )
{
// Still a bit of a kludge; if we cannot connect in a sensible way to
// the upstream build plan we just revert to waiting for it all to
// complete. Real problem is per-mojo phase->lifecycle mapping
builtLogItem.addDependency( upstreamProject, "No phase tracking possible " );
upstreamPlan.waitUntilAllDone();
}
else
{
builtLogItem.addDependency( upstreamProject, "No schedule" );
}
}
}
if ( mustReResolved )
{
lifecycleDependencyResolver.resolveDependencies( false, projectBuild.getProject(),
projectBuild.getSession(),
executionPlan );
waitForAppropriateUpstreamExecutionsToFinish(builtLogItem, nextPlanItem, projectBuild);
}
reResolveReactorDependencies(nextPlanItem, projectBuild);
}
current = nextPlanItem;
}
@ -293,15 +243,139 @@ public class LifecycleWeaveBuilder
}
return null;
}
};
}
private boolean upstreamPhaseModifiesArtifactResolutionState( ExecutionPlanItem inSchedule )
{
final String phase = inSchedule.getLifecyclePhase();
return "install".equals( phase ) || "compile".equals( phase ) || "test-compile".equals( phase );
private void reResolveReactorDependencies(ExecutionPlanItem nextPlanItem, ProjectSegment projectBuild) {
if ( requiresReResolutionOfUpstreamReactorArtifacts( nextPlanItem ) )
{
reresolveUpstreamProjectArtifacts(projectBuild);
}
else if (requiresReResolutionOfUpstreamTestScopedReactorArtifacts( nextPlanItem))
{
reresolveUpstreamTestScopedArtifacts( projectBuild);
}
}
private void waitForAppropriateUpstreamExecutionsToFinish(BuildLogItem builtLogItem, ExecutionPlanItem nextPlanItem, ProjectSegment projectBuild) throws InterruptedException {
for ( MavenProject upstreamProject : projectBuild.getImmediateUpstreamProjects() )
{
final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
final String nextPhase = nextPlanItem.getLifecyclePhase();
final ExecutionPlanItem inSchedule = upstreamPlan.findLastInPhase( nextPhase );
if ( inSchedule != null )
{
long startWait = System.currentTimeMillis();
inSchedule.waitUntilDone();
builtLogItem.addWait( upstreamProject, inSchedule, startWait );
}
else if ( !upstreamPlan.containsPhase( nextPhase ) )
{
// Still a bit of a kludge; if we cannot connect in a sensible way to
// the upstream build plan we just revert to waiting for it all to
// complete. Real problem is per-mojo phase->lifecycle mapping
builtLogItem.addDependency( upstreamProject, "No phase tracking possible " );
upstreamPlan.waitUntilAllDone();
}
else
{
builtLogItem.addDependency( upstreamProject, "No schedule" );
}
}
}
private void reresolveUpstreamProjectArtifacts(ProjectSegment projectBuild) {
for ( MavenProject upstreamProject : projectBuild.getTransitiveUpstreamProjects() ){
Artifact upStreamArtifact = upstreamProject.getArtifact();
Artifact dependencyArtifact = findDependency(projectBuild.getProject(), upStreamArtifact);
if (dependencyArtifact != null){
dependencyArtifact.setFile( upStreamArtifact.getFile());
dependencyArtifact.setResolved( true );
dependencyArtifact.setRepository( upStreamArtifact.getRepository());
}
}
}
private void reresolveUpstreamTestScopedArtifacts(ProjectSegment projectBuild) {
for ( MavenProject upstreamProject : projectBuild.getTransitiveUpstreamProjects() ){
Artifact upStreamArtifact = findTestScopedArtifact(upstreamProject);
Artifact dependencyArtifact = findDependency(projectBuild.getProject(), upStreamArtifact);
if (dependencyArtifact != null){
dependencyArtifact.setFile( upStreamArtifact.getFile());
dependencyArtifact.setResolved( upStreamArtifact.isResolved());
dependencyArtifact.setRepository( upStreamArtifact.getRepository());
}
}
}
private Artifact findTestScopedArtifact(MavenProject upstreamProject) {
if ( upstreamProject == null){
return null;
}
List<Artifact> artifactList = upstreamProject.getAttachedArtifacts();
for (Artifact artifact : artifactList) {
if (Artifact.SCOPE_TEST.equals( artifact.getScope())){
return artifact;
}
}
return null;
}
private static Artifact findDependency(MavenProject project, Artifact upStreamArtifact) {
if (upStreamArtifact == null){
return null;
}
String key = ArtifactUtils.key( upStreamArtifact.getGroupId(),
upStreamArtifact.getArtifactId(),
upStreamArtifact.getVersion() );
final Set<Artifact> deps = project.getDependencyArtifacts();
for ( Artifact dep : deps )
{
String depKey = ArtifactUtils.key(dep.getGroupId(), dep.getArtifactId(), dep.getVersion());
if ( key.equals( depKey ) )
{
return dep;
}
}
return null;
}
private boolean requiresReResolutionOfUpstreamReactorArtifacts( ExecutionPlanItem nextExecutionPlanItem )
{
final String phase = nextExecutionPlanItem.getLifecyclePhase();
return "package".equals(phase) || "install".equals( phase ) || "compile".equals( phase );
}
private boolean requiresReResolutionOfUpstreamTestScopedReactorArtifacts( ExecutionPlanItem nextExecutionPlanItem )
{
final String phase = nextExecutionPlanItem.getLifecyclePhase();
return "package".equals(phase) || "install".equals( phase ) || "compile".equals( phase ) || "test-compile".equals( phase );
}
private void buildExecutionPlanItem(ExecutionPlanItem current, PhaseRecorder phaseRecorder, Schedule schedule, ReactorContext reactorContext, ProjectSegment projectBuild, DependencyContext dependencyContext) throws LifecycleExecutionException {
if ( schedule != null && schedule.isMojoSynchronized() )
{
synchronized ( current.getPlugin() )
{
buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
phaseRecorder );
}
}
else
{
buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
phaseRecorder );
}
}
private void buildExecutionPlanItem( ReactorContext reactorContext, ExecutionPlanItem node,
ProjectSegment projectBuild, DependencyContext dependencyContext,
PhaseRecorder phaseRecorder )

View File

@ -53,12 +53,18 @@ public final class ProjectSegment
private final MavenSession session;
private final List<MavenProject> nonTransitiveUpstreamProjects;
private final List<MavenProject> transitiveUpstreamProjects;
public ProjectSegment( MavenProject project, TaskSegment taskSegment, MavenSession copiedSession )
{
this.project = project;
this.taskSegment = taskSegment;
this.session = copiedSession;
final ProjectDependencyGraph dependencyGraph = getSession().getProjectDependencyGraph();
nonTransitiveUpstreamProjects = dependencyGraph.getUpstreamProjects( getProject(), false );
transitiveUpstreamProjects = dependencyGraph.getUpstreamProjects( getProject(), true );
}
public MavenSession getSession()
@ -78,8 +84,12 @@ public final class ProjectSegment
public List<MavenProject> getImmediateUpstreamProjects()
{
final ProjectDependencyGraph dependencyGraph = getSession().getProjectDependencyGraph();
return dependencyGraph.getUpstreamProjects( getProject(), false );
return nonTransitiveUpstreamProjects;
}
public List<MavenProject> getTransitiveUpstreamProjects()
{
return transitiveUpstreamProjects;
}
@Override

View File

@ -16,6 +16,7 @@
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
@ -23,6 +24,8 @@ import org.apache.maven.lifecycle.internal.stub.LoggerStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependenciesResolverStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
import java.util.HashSet;
/**
* @author Kristian Rosenvold
*/
@ -40,7 +43,8 @@ public class BuilderCommonTest
final BuilderCommon builderCommon = getBuilderCommon();
final MavenExecutionPlan plan =
builderCommon.resolveBuildPlan( session1, ProjectDependencyGraphStub.A, taskSegment1 );
builderCommon.resolveBuildPlan( session1, ProjectDependencyGraphStub.A, taskSegment1,
new HashSet<Artifact>() );
assertEquals( LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan().size(), plan.size() );
}

View File

@ -122,8 +122,7 @@ public class LifecycleWeaveBuilderTest
final LoggerStub loggerStub = new LoggerStub();
final LifecycleDependencyResolver lifecycleDependencyResolver =
new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), loggerStub );
return new LifecycleWeaveBuilder( mojoExecutor, builderCommon, loggerStub, lifecycleDependencyResolver,
new ExecutionEventCatapultStub() );
return new LifecycleWeaveBuilder( mojoExecutor, builderCommon, loggerStub, new ExecutionEventCatapultStub() );
}
private BuilderCommon getBuilderCommon()

View File

@ -51,4 +51,12 @@ public class ProjectDependenciesResolverStub
{
return new HashSet<Artifact>();
}
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
Set<Artifact> ignoreableArtifacts )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return new HashSet<Artifact>();
}
}

View File

@ -190,10 +190,10 @@ public class ProjectDependencyGraphStub
public List<MavenProject> getUpstreamProjects( MavenProject project, boolean transitive )
{
if ( transitive )
/* if ( transitive )
{
throw new RuntimeException( "Not implemented yet" );
}
}*/
List<MavenProject> result = new ArrayList<MavenProject>();
final List<Dependency> dependencies = getDependencies();
for ( Dependency dependency : dependencies )