Replaced old build-plan mess with a single recursive plan instance that tracks direct invocation forks as well as lifecycle forks. All unit tests run, and I'm running integration tests now, to see if this fixes it0013.

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@541938 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2007-05-26 21:06:12 +00:00
parent 4c3d71313b
commit 10febbbda0
33 changed files with 1104 additions and 2018 deletions

View File

@ -143,5 +143,11 @@ under the License.
<artifactId>plexus-active-collections</artifactId> <artifactId>plexus-active-collections</artifactId>
<version>1.0-beta-1</version> <version>1.0-beta-1</version>
</dependency> </dependency>
<dependency>
<groupId>easymock</groupId>
<artifactId>easymock</artifactId>
<version>1.2_Java1.3</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -28,7 +28,6 @@ import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException
import org.apache.maven.context.BuildContextManager; import org.apache.maven.context.BuildContextManager;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager; import org.apache.maven.execution.ReactorManager;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.binding.MojoBindingFactory; import org.apache.maven.lifecycle.binding.MojoBindingFactory;
import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.plan.BuildPlan; import org.apache.maven.lifecycle.plan.BuildPlan;
@ -63,34 +62,31 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Stack;
/** /**
* @author <a href="mailto:jason@maven.org">Jason van Zyl</a> * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
* @author <a href="mailto:brett@apache.org">Brett Porter</a> * @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @version $Id: DefaultLifecycleExecutor.java,v 1.16 2005/03/04 09:04:25 * @version $Id$
* jdcasey Exp $ * @todo because of aggregation, we ended up with cli-ish stuff in here (like line() and the project logging, without
* @todo because of aggregation, we ended up with cli-ish stuff in here (like line() and the project logging, without much of the event handling) * much of the event handling)
*/ */
public class DefaultLifecycleExecutor public class DefaultLifecycleExecutor extends AbstractLogEnabled implements LifecycleExecutor
extends AbstractLogEnabled
implements LifecycleExecutor
{ {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Components // Components
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
private PluginManager pluginManager; private PluginManager pluginManager;
private PluginLoader pluginLoader; private PluginLoader pluginLoader;
private BuildPlanner buildPlanner; private BuildPlanner buildPlanner;
private ArtifactHandlerManager artifactHandlerManager; private ArtifactHandlerManager artifactHandlerManager;
private MojoBindingFactory mojoBindingFactory; private MojoBindingFactory mojoBindingFactory;
private LifecycleBindingManager lifecycleBindingManager;
private BuildContextManager buildContextManager; private BuildContextManager buildContextManager;
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -98,14 +94,13 @@ public class DefaultLifecycleExecutor
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** /**
* Execute a task. Each task may be a phase in the lifecycle or the * Execute a task. Each task may be a phase in the lifecycle or the execution of a mojo.
* execution of a mojo. *
*
* @param session * @param session
* @param rm * @param rm
* @param dispatcher * @param dispatcher
*/ */
public void execute( MavenSession session, ReactorManager rm, EventDispatcher dispatcher ) public void execute( final MavenSession session, final ReactorManager rm, final EventDispatcher dispatcher )
throws BuildFailureException, LifecycleExecutionException throws BuildFailureException, LifecycleExecutionException
{ {
// TODO: This is dangerous, particularly when it's just a collection of loose-leaf projects being built // TODO: This is dangerous, particularly when it's just a collection of loose-leaf projects being built
@ -114,7 +109,7 @@ public class DefaultLifecycleExecutor
List goals = session.getGoals(); List goals = session.getGoals();
if ( goals.isEmpty() && rootProject != null ) if ( goals.isEmpty() && ( rootProject != null ) )
{ {
String goal = rootProject.getDefaultGoal(); String goal = rootProject.getDefaultGoal();
@ -146,8 +141,8 @@ public class DefaultLifecycleExecutor
executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher ); executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher );
} }
private void executeTaskSegments( List taskSegments, ReactorManager rm, MavenSession session, private void executeTaskSegments( final List taskSegments, final ReactorManager rm, final MavenSession session,
MavenProject rootProject, EventDispatcher dispatcher ) final MavenProject rootProject, final EventDispatcher dispatcher )
throws LifecycleExecutionException, BuildFailureException throws LifecycleExecutionException, BuildFailureException
{ {
for ( Iterator it = taskSegments.iterator(); it.hasNext(); ) for ( Iterator it = taskSegments.iterator(); it.hasNext(); )
@ -165,11 +160,11 @@ public class DefaultLifecycleExecutor
getLogger().info( " " + segment ); getLogger().info( " " + segment );
line(); line();
String target = rootProject.getId() + " ( " + segment + " )"; String target = rootProject.getId() + " ( " + segment + " )";
getLogger().debug( "Constructing build plan for " + target ); getLogger().debug( "Constructing build plan for " + target );
// !! This is ripe for refactoring to an aspect. // !! This is ripe for refactoring to an aspect.
// Event monitoring. // Event monitoring.
String event = MavenEvents.PROJECT_EXECUTION; String event = MavenEvents.PROJECT_EXECUTION;
@ -183,23 +178,22 @@ public class DefaultLifecycleExecutor
// for the fork being executed, plus a stack of projects used in the ancestor execution contexts. // for the fork being executed, plus a stack of projects used in the ancestor execution contexts.
LifecycleExecutionContext ctx = new LifecycleExecutionContext( rootProject ); LifecycleExecutionContext ctx = new LifecycleExecutionContext( rootProject );
ctx.store( buildContextManager ); ctx.store( buildContextManager );
// NEW: Build up the execution plan, including configuration. // NEW: Build up the execution plan, including configuration.
List mojoBindings = getLifecycleBindings( segment.getTasks(), rootProject, target ); List mojoBindings = getLifecycleBindings( segment.getTasks(), rootProject, target );
// NEW: Then, iterate over each binding in that plan, and execute the associated mojo. // NEW: Then, iterate over each binding in that plan, and execute the associated mojo.
// only call once, with the top-level project (assumed to be provided as a parameter)... // only call once, with the top-level project (assumed to be provided as a parameter)...
for ( Iterator mojoIterator = mojoBindings.iterator(); mojoIterator.hasNext(); ) for ( Iterator mojoIterator = mojoBindings.iterator(); mojoIterator.hasNext(); )
{ {
MojoBinding binding = (MojoBinding) mojoIterator.next(); MojoBinding binding = (MojoBinding) mojoIterator.next();
executeGoalAndHandleFailures( binding, session, dispatcher, event, rm, buildStartTime, executeGoalAndHandleFailures( binding, session, dispatcher, event, rm, buildStartTime, target );
target );
} }
// clean up the execution context, so we don't pollute for future project-executions. // clean up the execution context, so we don't pollute for future project-executions.
LifecycleExecutionContext.delete( buildContextManager ); LifecycleExecutionContext.delete( buildContextManager );
rm.registerBuildSuccess( rootProject, System.currentTimeMillis() - buildStartTime ); rm.registerBuildSuccess( rootProject, System.currentTimeMillis() - buildStartTime );
dispatcher.dispatchEnd( event, target ); dispatcher.dispatchEnd( event, target );
@ -212,8 +206,7 @@ public class DefaultLifecycleExecutor
getLogger().info( " " + segment ); getLogger().info( " " + segment );
getLogger().info( getLogger().info( "This project has been banned from further executions due to previous failures." );
"This project has been banned from further executions due to previous failures." );
line(); line();
} }
@ -238,7 +231,7 @@ public class DefaultLifecycleExecutor
line(); line();
String target = currentProject.getId() + " ( " + segment + " )"; String target = currentProject.getId() + " ( " + segment + " )";
// !! This is ripe for refactoring to an aspect. // !! This is ripe for refactoring to an aspect.
// Event monitoring. // Event monitoring.
String event = MavenEvents.PROJECT_EXECUTION; String event = MavenEvents.PROJECT_EXECUTION;
@ -246,23 +239,25 @@ public class DefaultLifecycleExecutor
long buildStartTime = System.currentTimeMillis(); long buildStartTime = System.currentTimeMillis();
dispatcher.dispatchStart( event, target ); dispatcher.dispatchStart( event, target );
LifecycleExecutionContext ctx = new LifecycleExecutionContext( currentProject ); LifecycleExecutionContext ctx = new LifecycleExecutionContext( currentProject );
ctx.store( buildContextManager ); ctx.store( buildContextManager );
List mojoBindings = getLifecycleBindings( segment.getTasks(), currentProject, target ); List mojoBindings = getLifecycleBindings( segment.getTasks(), currentProject, target );
for ( Iterator mojoIterator = mojoBindings.iterator(); mojoIterator.hasNext(); ) for ( Iterator mojoIterator = mojoBindings.iterator(); mojoIterator.hasNext(); )
{ {
MojoBinding mojoBinding = (MojoBinding) mojoIterator.next(); MojoBinding mojoBinding = (MojoBinding) mojoIterator.next();
getLogger().debug( "Mojo: " + mojoBinding.getGoal() + " has config:\n" + mojoBinding.getConfiguration() ); getLogger().debug(
executeGoalAndHandleFailures( mojoBinding, session, dispatcher, event, rm, "Mojo: " + mojoBinding.getGoal() + " has config:\n"
buildStartTime, target ); + mojoBinding.getConfiguration() );
executeGoalAndHandleFailures( mojoBinding, session, dispatcher, event, rm, buildStartTime,
target );
} }
LifecycleExecutionContext.delete( buildContextManager ); LifecycleExecutionContext.delete( buildContextManager );
rm.registerBuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime ); rm.registerBuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
dispatcher.dispatchEnd( event, target ); dispatcher.dispatchEnd( event, target );
@ -276,7 +271,7 @@ public class DefaultLifecycleExecutor
getLogger().info( " " + segment ); getLogger().info( " " + segment );
getLogger().info( getLogger().info(
"This project has been banned from further executions due to previous failures." ); "This project has been banned from further executions due to previous failures." );
line(); line();
} }
@ -286,43 +281,43 @@ public class DefaultLifecycleExecutor
} }
/** /**
* Retrieves the build plan for the current project, given the specified list of tasks. This * Retrieves the build plan for the current project, given the specified list of tasks. This build plan will consist
* build plan will consist of MojoBindings, each fully configured to execute, which enables us * of MojoBindings, each fully configured to execute, which enables us to enumerate the full build plan to the debug
* to enumerate the full build plan to the debug log-level, complete with the configuration each * log-level, complete with the configuration each mojo will use.
* mojo will use.
*/ */
private List getLifecycleBindings( List tasks, MavenProject project, String targetDescription ) private List getLifecycleBindings( final List tasks, final MavenProject project, final String targetDescription )
throws LifecycleExecutionException throws LifecycleExecutionException
{ {
List mojoBindings; List mojoBindings;
try try
{ {
BuildPlan plan = buildPlanner.constructBuildPlan( tasks, project ); BuildPlan plan = buildPlanner.constructBuildPlan( tasks, project );
if ( getLogger().isDebugEnabled() ) if ( getLogger().isDebugEnabled() )
{ {
getLogger().debug( "\n\nOur build plan is:\n" + BuildPlanUtils.listBuildPlan( plan, project, lifecycleBindingManager, false ) + "\n\n" ); getLogger().debug( "\n\nOur build plan is:\n" + BuildPlanUtils.listBuildPlan( plan, false ) + "\n\n" );
} }
mojoBindings = plan.getPlanMojoBindings( project, lifecycleBindingManager ); mojoBindings = plan.renderExecutionPlan( new Stack() );
} }
catch ( LifecycleException e ) catch ( LifecycleException e )
{ {
throw new LifecycleExecutionException( "Failed to construct build plan for: " + targetDescription + ". Reason: " throw new LifecycleExecutionException( "Failed to construct build plan for: " + targetDescription
+ e.getMessage(), e ); + ". Reason: " + e.getMessage(), e );
} }
return mojoBindings; return mojoBindings;
} }
private void executeGoalAndHandleFailures( MojoBinding mojoBinding, MavenSession session, EventDispatcher dispatcher, String event, ReactorManager rm, private void executeGoalAndHandleFailures( final MojoBinding mojoBinding, final MavenSession session,
long buildStartTime, String target ) final EventDispatcher dispatcher, final String event,
final ReactorManager rm, final long buildStartTime, final String target )
throws BuildFailureException, LifecycleExecutionException throws BuildFailureException, LifecycleExecutionException
{ {
// NEW: Retrieve/use the current project stored in the execution context, for consistency. // NEW: Retrieve/use the current project stored in the execution context, for consistency.
LifecycleExecutionContext ctx = LifecycleExecutionContext.read( buildContextManager ); LifecycleExecutionContext ctx = LifecycleExecutionContext.read( buildContextManager );
MavenProject project = ctx.getCurrentProject(); MavenProject project = ctx.getCurrentProject();
// NEW: Since the MojoBinding instances are configured when the build plan is constructed, // NEW: Since the MojoBinding instances are configured when the build plan is constructed,
// all that remains to be done here is to load the PluginDescriptor, construct a MojoExecution // all that remains to be done here is to load the PluginDescriptor, construct a MojoExecution
// instance, and call PluginManager.executeMojo( execution ). The MojoExecutor is constructed // instance, and call PluginManager.executeMojo( execution ). The MojoExecutor is constructed
@ -342,16 +337,16 @@ public class DefaultLifecycleExecutor
} }
else else
{ {
throw new LifecycleExecutionException( "Failed to load plugin for: " + MojoBindingUtils.toString( mojoBinding ) throw new LifecycleExecutionException( "Failed to load plugin for: "
+ ". Reason: " + e.getMessage(), e ); + MojoBindingUtils.toString( mojoBinding ) + ". Reason: " + e.getMessage(), e );
} }
} }
if ( pluginDescriptor != null ) if ( pluginDescriptor != null )
{ {
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() ); MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() );
MojoExecution mojoExecution = new MojoExecution( mojoDescriptor ); MojoExecution mojoExecution = new MojoExecution( mojoDescriptor );
mojoExecution.setConfiguration( (Xpp3Dom) mojoBinding.getConfiguration() ); mojoExecution.setConfiguration( (Xpp3Dom) mojoBinding.getConfiguration() );
try try
@ -360,8 +355,8 @@ public class DefaultLifecycleExecutor
} }
catch ( PluginManagerException e ) catch ( PluginManagerException e )
{ {
throw new LifecycleExecutionException( "Internal error in the plugin manager executing goal '" + throw new LifecycleExecutionException( "Internal error in the plugin manager executing goal '"
mojoDescriptor.getId() + "': " + e.getMessage(), e ); + mojoDescriptor.getId() + "': " + e.getMessage(), e );
} }
catch ( ArtifactNotFoundException e ) catch ( ArtifactNotFoundException e )
{ {
@ -390,8 +385,8 @@ public class DefaultLifecycleExecutor
} }
else else
{ {
throw new LifecycleExecutionException( "Failed to load plugin for: " + MojoBindingUtils.toString( mojoBinding ) throw new LifecycleExecutionException( "Failed to load plugin for: "
+ ". Reason: unknown" ); + MojoBindingUtils.toString( mojoBinding ) + ". Reason: unknown" );
} }
} }
catch ( LifecycleExecutionException e ) catch ( LifecycleExecutionException e )
@ -414,10 +409,11 @@ public class DefaultLifecycleExecutor
} }
} }
private boolean handleExecutionFailure( ReactorManager rm, MavenProject project, Exception e, MojoBinding mojoBinding, private boolean handleExecutionFailure( final ReactorManager rm, final MavenProject project, final Exception e,
long buildStartTime ) final MojoBinding mojoBinding, final long buildStartTime )
{ {
rm.registerBuildFailure( project, e, MojoBindingUtils.toString( mojoBinding ), System.currentTimeMillis() - buildStartTime ); rm.registerBuildFailure( project, e, MojoBindingUtils.toString( mojoBinding ), System.currentTimeMillis()
- buildStartTime );
if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) ) if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
{ {
@ -431,7 +427,8 @@ public class DefaultLifecycleExecutor
return false; return false;
} }
private List segmentTaskListByAggregationNeeds( List tasks, MavenSession session, MavenProject rootProject ) private List segmentTaskListByAggregationNeeds( final List tasks, final MavenSession session,
final MavenProject rootProject )
throws LifecycleExecutionException, BuildFailureException throws LifecycleExecutionException, BuildFailureException
{ {
List segments = new ArrayList(); List segments = new ArrayList();
@ -448,7 +445,7 @@ public class DefaultLifecycleExecutor
// simply add it to the current task partition. // simply add it to the current task partition.
if ( LifecycleUtils.isValidPhaseName( task ) ) if ( LifecycleUtils.isValidPhaseName( task ) )
{ {
if ( currentSegment != null && currentSegment.aggregate() ) if ( ( currentSegment != null ) && currentSegment.aggregate() )
{ {
segments.add( currentSegment ); segments.add( currentSegment );
currentSegment = null; currentSegment = null;
@ -471,33 +468,37 @@ public class DefaultLifecycleExecutor
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
// TODO: shouldn't hit this, investigate using the same resolution logic as // TODO: shouldn't hit this, investigate using the same resolution logic as
// others for plugins in the reactor // others for plugins in the reactor
getLogger().info( getLogger().info(
"Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." ); "Cannot find mojo descriptor for: \'" + task
+ "\' - Treating as non-aggregator." );
getLogger().debug( "", e ); getLogger().debug( "", e );
} }
catch ( LifecycleSpecificationException e ) catch ( LifecycleSpecificationException e )
{ {
String message = "Invalid task '" + task + "': you must specify a valid lifecycle phase, or" String message =
+ " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal"; "Invalid task '"
+ task
+ "': you must specify a valid lifecycle phase, or"
+ " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
throw new BuildFailureException( message, e ); throw new BuildFailureException( message, e );
} }
catch ( LifecycleLoaderException e ) catch ( LifecycleLoaderException e )
{ {
String message = "Cannot find plugin to match task '" + task + "'."; String message = "Cannot find plugin to match task '" + task + "'.";
throw new BuildFailureException( message, e ); throw new BuildFailureException( message, e );
} }
// if the mojo descriptor was found, determine aggregator status according to: // if the mojo descriptor was found, determine aggregator status according to:
// 1. whether the mojo declares itself an aggregator // 1. whether the mojo declares itself an aggregator
// 2. whether the mojo DOES NOT require a project to function (implicitly avoid reactor) // 2. whether the mojo DOES NOT require a project to function (implicitly avoid reactor)
if ( mojo != null && ( mojo.isAggregator() || !mojo.isProjectRequired() ) ) if ( ( mojo != null ) && ( mojo.isAggregator() || !mojo.isProjectRequired() ) )
{ {
if ( currentSegment != null && !currentSegment.aggregate() ) if ( ( currentSegment != null ) && !currentSegment.aggregate() )
{ {
segments.add( currentSegment ); segments.add( currentSegment );
currentSegment = null; currentSegment = null;
@ -512,7 +513,7 @@ public class DefaultLifecycleExecutor
} }
else else
{ {
if ( currentSegment != null && currentSegment.aggregate() ) if ( ( currentSegment != null ) && currentSegment.aggregate() )
{ {
segments.add( currentSegment ); segments.add( currentSegment );
currentSegment = null; currentSegment = null;
@ -545,18 +546,18 @@ public class DefaultLifecycleExecutor
/** /**
* @todo Not particularly happy about this. Would like WagonManager and ArtifactTypeHandlerManager to be able to * @todo Not particularly happy about this. Would like WagonManager and ArtifactTypeHandlerManager to be able to
* lookup directly, or have them passed in * lookup directly, or have them passed in
* *
* @todo Move this sort of thing to the tail end of the project-building process * @todo Move this sort of thing to the tail end of the project-building process
*/ */
private Map findArtifactTypeHandlers( MavenSession session ) private Map findArtifactTypeHandlers( final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException throws LifecycleExecutionException, PluginNotFoundException
{ {
Map map = new HashMap(); Map map = new HashMap();
for ( Iterator projectIterator = session.getSortedProjects().iterator(); projectIterator.hasNext(); ) for ( Iterator projectIterator = session.getSortedProjects().iterator(); projectIterator.hasNext(); )
{ {
MavenProject project = (MavenProject) projectIterator.next(); MavenProject project = (MavenProject) projectIterator.next();
for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); ) for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
{ {
Plugin plugin = (Plugin) i.next(); Plugin plugin = (Plugin) i.next();
@ -565,7 +566,8 @@ public class DefaultLifecycleExecutor
{ {
verifyPlugin( plugin, project, session ); verifyPlugin( plugin, project, session );
// TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly // TODO: if moved to the plugin manager we already have the descriptor from above and so do can
// lookup the container directly
try try
{ {
Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE ); Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE );
@ -577,8 +579,8 @@ public class DefaultLifecycleExecutor
} }
catch ( PluginManagerException e ) catch ( PluginManagerException e )
{ {
throw new LifecycleExecutionException( "Error looking up available components from plugin '" + throw new LifecycleExecutionException( "Error looking up available components from plugin '"
plugin.getKey() + "': " + e.getMessage(), e ); + plugin.getKey() + "': " + e.getMessage(), e );
} }
// shudder... // shudder...
@ -596,11 +598,11 @@ public class DefaultLifecycleExecutor
return map; return map;
} }
private PluginDescriptor verifyPlugin( Plugin plugin, MavenProject project, MavenSession session ) private PluginDescriptor verifyPlugin( final Plugin plugin, final MavenProject project, final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException throws LifecycleExecutionException, PluginNotFoundException
{ {
getLogger().debug( "Verifying plugin: " + plugin.getKey() ); getLogger().debug( "Verifying plugin: " + plugin.getKey() );
PluginDescriptor pluginDescriptor; PluginDescriptor pluginDescriptor;
try try
{ {
@ -608,8 +610,8 @@ public class DefaultLifecycleExecutor
} }
catch ( PluginManagerException e ) catch ( PluginManagerException e )
{ {
throw new LifecycleExecutionException( throw new LifecycleExecutionException( "Internal error in the plugin manager getting plugin '"
"Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e ); + plugin.getKey() + "': " + e.getMessage(), e );
} }
catch ( PluginVersionResolutionException e ) catch ( PluginVersionResolutionException e )
{ {
@ -638,14 +640,15 @@ public class DefaultLifecycleExecutor
return pluginDescriptor; return pluginDescriptor;
} }
private MojoDescriptor getMojoDescriptorForDirectInvocation( String task, MavenSession session, MavenProject project ) private MojoDescriptor getMojoDescriptorForDirectInvocation( final String task, final MavenSession session,
final MavenProject project )
throws LifecycleSpecificationException, PluginLoaderException, LifecycleLoaderException throws LifecycleSpecificationException, PluginLoaderException, LifecycleLoaderException
{ {
MojoBinding binding = mojoBindingFactory.parseMojoBinding( task, project, true ); MojoBinding binding = mojoBindingFactory.parseMojoBinding( task, project, true );
PluginDescriptor descriptor = pluginLoader.loadPlugin( binding, project ); PluginDescriptor descriptor = pluginLoader.loadPlugin( binding, project );
MojoDescriptor mojoDescriptor = descriptor.getMojo( binding.getGoal() ); MojoDescriptor mojoDescriptor = descriptor.getMojo( binding.getGoal() );
return mojoDescriptor; return mojoDescriptor;
} }
@ -658,14 +661,14 @@ public class DefaultLifecycleExecutor
{ {
private boolean aggregate; private boolean aggregate;
private List tasks = new ArrayList(); private final List tasks = new ArrayList();
TaskSegment() TaskSegment()
{ {
} }
TaskSegment( boolean aggregate ) TaskSegment( final boolean aggregate )
{ {
this.aggregate = aggregate; this.aggregate = aggregate;
} }
@ -703,7 +706,7 @@ public class DefaultLifecycleExecutor
return aggregate; return aggregate;
} }
void add( String task ) void add( final String task )
{ {
tasks.add( task ); tasks.add( task );
} }

View File

@ -5,11 +5,8 @@ import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException; import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.LifecycleUtils; import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.mapping.LifecycleMapping; import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.lifecycle.model.LifecycleBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings; import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.plan.DirectInvocationModifier;
import org.apache.maven.lifecycle.plan.LifecyclePlannerException;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution; import org.apache.maven.model.PluginExecution;
import org.apache.maven.model.ReportPlugin; import org.apache.maven.model.ReportPlugin;
@ -30,23 +27,20 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
/** /**
* Responsible for the gross construction of LifecycleBindings, or mappings of MojoBinding instances * Responsible for the gross construction of LifecycleBindings, or mappings of MojoBinding instances to different parts
* to different parts of the three lifecycles: clean, build, and site. Also, handles transcribing * of the three lifecycles: clean, build, and site. Also, handles transcribing these LifecycleBindings instances into
* these LifecycleBindings instances into lists of MojoBinding's, which can be consumed by the * lists of MojoBinding's, which can be consumed by the LifecycleExecutor.
* LifecycleExecutor.
* *
* @author jdcasey * @author jdcasey
* *
*/ */
public class DefaultLifecycleBindingManager public class DefaultLifecycleBindingManager implements LifecycleBindingManager, LogEnabled
implements LifecycleBindingManager, LogEnabled
{ {
private ActiveMap bindingsByPackaging; private ActiveMap bindingsByPackaging;
@ -56,7 +50,7 @@ public class DefaultLifecycleBindingManager
private PluginLoader pluginLoader; private PluginLoader pluginLoader;
private MojoBindingFactory mojoBindingFactory; private MojoBindingFactory mojoBindingFactory;
private LegacyLifecycleMappingParser legacyLifecycleMappingParser; private LegacyLifecycleMappingParser legacyLifecycleMappingParser;
private Logger logger; private Logger logger;
@ -68,11 +62,10 @@ public class DefaultLifecycleBindingManager
private List defaultReports; private List defaultReports;
/** /**
* Retrieve the LifecycleBindings given by the lifecycle mapping component/file for the project's * Retrieve the LifecycleBindings given by the lifecycle mapping component/file for the project's packaging. Any
* packaging. Any applicable mojo configuration will be injected into the LifecycleBindings from * applicable mojo configuration will be injected into the LifecycleBindings from the POM.
* the POM.
*/ */
public LifecycleBindings getBindingsForPackaging( MavenProject project ) public LifecycleBindings getBindingsForPackaging( final MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException throws LifecycleLoaderException, LifecycleSpecificationException
{ {
String packaging = project.getPackaging(); String packaging = project.getPackaging();
@ -114,12 +107,11 @@ public class DefaultLifecycleBindingManager
/** /**
* Search all plugins configured in the POM that have extensions == true, looking for either a * Search all plugins configured in the POM that have extensions == true, looking for either a
* {@link LifecycleBindingLoader} instance, or a {@link LifecycleMapping} instance that matches * {@link LifecycleBindingLoader} instance, or a {@link LifecycleMapping} instance that matches the project's
* the project's packaging. For the first match found, construct the corresponding LifecycleBindings * packaging. For the first match found, construct the corresponding LifecycleBindings instance and return it after
* instance and return it after POM configurations have been injected into any appropriate * POM configurations have been injected into any appropriate MojoBinding instances contained within.
* MojoBinding instances contained within.
*/ */
private LifecycleBindings searchPluginsWithExtensions( MavenProject project ) private LifecycleBindings searchPluginsWithExtensions( final MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException throws LifecycleLoaderException, LifecycleSpecificationException
{ {
List plugins = project.getBuildPlugins(); List plugins = project.getBuildPlugins();
@ -136,18 +128,20 @@ public class DefaultLifecycleBindingManager
try try
{ {
loader = (LifecycleBindingLoader) pluginLoader.loadPluginComponent( LifecycleBindingLoader.ROLE, packaging, loader =
plugin, project ); (LifecycleBindingLoader) pluginLoader.loadPluginComponent( LifecycleBindingLoader.ROLE,
packaging, plugin, project );
} }
catch ( ComponentLookupException e ) catch ( ComponentLookupException e )
{ {
logger.debug( LifecycleBindingLoader.ROLE + " for packaging: " + packaging logger.debug( LifecycleBindingLoader.ROLE + " for packaging: " + packaging
+ " could not be retrieved from plugin: " + plugin.getKey() + ".\nReason: " + e.getMessage(), e ); + " could not be retrieved from plugin: " + plugin.getKey() + ".\nReason: "
+ e.getMessage(), e );
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecycleLoaderException( "Failed to load plugin: " + plugin.getKey() + ". Reason: " throw new LifecycleLoaderException( "Failed to load plugin: " + plugin.getKey() + ". Reason: "
+ e.getMessage(), e ); + e.getMessage(), e );
} }
if ( loader != null ) if ( loader != null )
@ -161,18 +155,20 @@ public class DefaultLifecycleBindingManager
LifecycleMapping mapping = null; LifecycleMapping mapping = null;
try try
{ {
mapping = (LifecycleMapping) pluginLoader.loadPluginComponent( LifecycleMapping.ROLE, packaging, plugin, mapping =
project ); (LifecycleMapping) pluginLoader.loadPluginComponent( LifecycleMapping.ROLE, packaging,
plugin, project );
} }
catch ( ComponentLookupException e ) catch ( ComponentLookupException e )
{ {
logger.debug( LifecycleMapping.ROLE + " for packaging: " + packaging logger.debug( LifecycleMapping.ROLE + " for packaging: " + packaging
+ " could not be retrieved from plugin: " + plugin.getKey() + ".\nReason: " + e.getMessage(), e ); + " could not be retrieved from plugin: " + plugin.getKey() + ".\nReason: "
+ e.getMessage(), e );
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecycleLoaderException( "Failed to load plugin: " + plugin.getKey() + ". Reason: " throw new LifecycleLoaderException( "Failed to load plugin: " + plugin.getKey() + ". Reason: "
+ e.getMessage(), e ); + e.getMessage(), e );
} }
if ( mapping != null ) if ( mapping != null )
@ -197,11 +193,10 @@ public class DefaultLifecycleBindingManager
} }
/** /**
* Construct the LifecycleBindings for the default lifecycle mappings, including injection of * Construct the LifecycleBindings for the default lifecycle mappings, including injection of configuration from the
* configuration from the project into each MojoBinding, where appropriate. * project into each MojoBinding, where appropriate.
*/ */
public LifecycleBindings getDefaultBindings( MavenProject project ) public LifecycleBindings getDefaultBindings( final MavenProject project ) throws LifecycleSpecificationException
throws LifecycleSpecificationException
{ {
LifecycleBindings bindings = legacyLifecycleMappingParser.parseDefaultMappings( legacyLifecycles ); LifecycleBindings bindings = legacyLifecycleMappingParser.parseDefaultMappings( legacyLifecycles );
@ -210,16 +205,15 @@ public class DefaultLifecycleBindingManager
return bindings; return bindings;
} }
public void enableLogging( Logger logger ) public void enableLogging( final Logger logger )
{ {
this.logger = logger; this.logger = logger;
} }
/** /**
* Construct the LifecycleBindings that constitute the extra mojos bound to the lifecycle within * Construct the LifecycleBindings that constitute the extra mojos bound to the lifecycle within the POM itself.
* the POM itself.
*/ */
public LifecycleBindings getProjectCustomBindings( MavenProject project ) public LifecycleBindings getProjectCustomBindings( final MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException throws LifecycleLoaderException, LifecycleSpecificationException
{ {
String projectId = project.getId(); String projectId = project.getId();
@ -245,15 +239,16 @@ public class DefaultLifecycleBindingManager
PluginExecution execution = (PluginExecution) execIt.next(); PluginExecution execution = (PluginExecution) execIt.next();
List goals = execution.getGoals(); List goals = execution.getGoals();
if ( goals != null && !goals.isEmpty() ) if ( ( goals != null ) && !goals.isEmpty() )
{ {
for ( Iterator goalIterator = goals.iterator(); goalIterator.hasNext(); ) for ( Iterator goalIterator = goals.iterator(); goalIterator.hasNext(); )
{ {
String goal = (String) goalIterator.next(); String goal = (String) goalIterator.next();
if ( goal == null ) if ( goal == null )
{ {
logger.warn( "Execution: " + execution.getId() + " in plugin: " + plugin.getKey() + " in the POM has a null goal." ); logger.warn( "Execution: " + execution.getId() + " in plugin: " + plugin.getKey()
+ " in the POM has a null goal." );
continue; continue;
} }
@ -278,14 +273,15 @@ public class DefaultLifecycleBindingManager
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecycleLoaderException( "Failed to load plugin: " + plugin + ". Reason: " throw new LifecycleLoaderException( "Failed to load plugin: " + plugin
+ e.getMessage(), e ); + ". Reason: " + e.getMessage(), e );
} }
} }
if ( pluginDescriptor.getMojos() == null ) if ( pluginDescriptor.getMojos() == null )
{ {
logger.error( "Somehow, the PluginDescriptor for plugin: " + plugin.getKey() + " contains no mojos. This is highly irregular. Ignoring..." ); logger.error( "Somehow, the PluginDescriptor for plugin: " + plugin.getKey()
+ " contains no mojos. This is highly irregular. Ignoring..." );
continue; continue;
} }
@ -294,8 +290,9 @@ public class DefaultLifecycleBindingManager
if ( phase == null ) if ( phase == null )
{ {
throw new LifecycleSpecificationException( "No phase specified for goal: " + goal throw new LifecycleSpecificationException( "No phase specified for goal: "
+ " in plugin: " + plugin.getKey() + " from POM: " + projectId ); + goal + " in plugin: " + plugin.getKey() + " from POM: "
+ projectId );
} }
} }
@ -313,12 +310,11 @@ public class DefaultLifecycleBindingManager
} }
/** /**
* Construct the LifecycleBindings that constitute the mojos mapped to the lifecycles by an overlay * Construct the LifecycleBindings that constitute the mojos mapped to the lifecycles by an overlay specified in a
* specified in a plugin. Inject mojo configuration from the POM into all appropriate MojoBinding * plugin. Inject mojo configuration from the POM into all appropriate MojoBinding instances.
* instances.
*/ */
public LifecycleBindings getPluginLifecycleOverlay( PluginDescriptor pluginDescriptor, String lifecycleId, public LifecycleBindings getPluginLifecycleOverlay( final PluginDescriptor pluginDescriptor,
MavenProject project ) final String lifecycleId, final MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException throws LifecycleLoaderException, LifecycleSpecificationException
{ {
Lifecycle lifecycleOverlay = null; Lifecycle lifecycleOverlay = null;
@ -362,21 +358,21 @@ public class DefaultLifecycleBindingManager
// An example of this is the corbertura plugin that needs to call the surefire // An example of this is the corbertura plugin that needs to call the surefire
// plugin in forking mode. // plugin in forking mode.
// //
//<phase> // <phase>
// <id>test</id> // <id>test</id>
// <executions> // <executions>
// <execution> // <execution>
// <goals> // <goals>
// <goal>org.apache.maven.plugins:maven-surefire-plugin:test</goal> // <goal>org.apache.maven.plugins:maven-surefire-plugin:test</goal>
// </goals> // </goals>
// <configuration> // <configuration>
// <classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory> // <classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory>
// <ignoreFailures>true</ignoreFailures> // <ignoreFailures>true</ignoreFailures>
// <forkMode>once</forkMode> // <forkMode>once</forkMode>
// </configuration> // </configuration>
// </execution> // </execution>
// </executions> // </executions>
//</phase> // </phase>
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// //
@ -399,7 +395,8 @@ public class DefaultLifecycleBindingManager
Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration(); Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
if ( phase.getConfiguration() != null ) if ( phase.getConfiguration() != null )
{ {
configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), configuration ); configuration =
Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), configuration );
} }
binding.setConfiguration( configuration ); binding.setConfiguration( configuration );
@ -414,15 +411,16 @@ public class DefaultLifecycleBindingManager
{ {
// Merge in general configuration for a phase. // Merge in general configuration for a phase.
// TODO: this is all kind of backwards from the POMM. Let's align it all under 2.1. // TODO: this is all kind of backwards from the POMM. Let's align it all under 2.1.
// We should create a new lifecycle executor for modelVersion >5.0.0 // We should create a new lifecycle executor for modelVersion >5.0.0
// [jdcasey; 08-March-2007] Not sure what the above to-do references...how _should_ // [jdcasey; 08-March-2007] Not sure what the above to-do references...how _should_
// this work?? // this work??
for ( Iterator j = phaseBindings.iterator(); j.hasNext(); ) for ( Iterator j = phaseBindings.iterator(); j.hasNext(); )
{ {
MojoBinding binding = (MojoBinding) j.next(); MojoBinding binding = (MojoBinding) j.next();
Xpp3Dom configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), Xpp3Dom configuration =
(Xpp3Dom) binding.getConfiguration() ); Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ),
(Xpp3Dom) binding.getConfiguration() );
binding.setConfiguration( configuration ); binding.setConfiguration( configuration );
} }
@ -434,18 +432,17 @@ public class DefaultLifecycleBindingManager
} }
/** /**
* Retrieve the list of MojoBinding instances that correspond to the reports configured for the * Retrieve the list of MojoBinding instances that correspond to the reports configured for the specified project.
* specified project. Inject all appropriate configuration from the POM for each MojoBinding, using * Inject all appropriate configuration from the POM for each MojoBinding, using the following precedence rules:
* the following precedence rules:
* <br/> * <br/>
* <ol> * <ol>
* <li>report-set-level configuration</li> * <li>report-set-level configuration</li>
* <li>reporting-level configuration</li> * <li>reporting-level configuration</li>
* <li>execution-level configuration</li> * <li>execution-level configuration</li>
* <li>plugin-level configuration</li> * <li>plugin-level configuration</li>
* </ol> * </ol>
*/ */
public List getReportBindings( MavenProject project ) public List getReportBindings( final MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException throws LifecycleLoaderException, LifecycleSpecificationException
{ {
if ( project.getModel().getReports() != null ) if ( project.getModel().getReports() != null )
@ -464,7 +461,7 @@ public class DefaultLifecycleBindingManager
List reportSets = reportPlugin.getReportSets(); List reportSets = reportPlugin.getReportSets();
if ( reportSets == null || reportSets.isEmpty() ) if ( ( reportSets == null ) || reportSets.isEmpty() )
{ {
reports.addAll( getReportsForPlugin( reportPlugin, null, project ) ); reports.addAll( getReportsForPlugin( reportPlugin, null, project ) );
} }
@ -485,11 +482,11 @@ public class DefaultLifecycleBindingManager
/** /**
* Retrieve the ReportPlugin instances referenced in the specified POM. * Retrieve the ReportPlugin instances referenced in the specified POM.
*/ */
private List getReportPluginsForProject( MavenProject project ) private List getReportPluginsForProject( final MavenProject project )
{ {
List reportPlugins = project.getReportPlugins(); List reportPlugins = project.getReportPlugins();
if ( project.getReporting() == null || !project.getReporting().isExcludeDefaults() ) if ( ( project.getReporting() == null ) || !project.getReporting().isExcludeDefaults() )
{ {
if ( reportPlugins == null ) if ( reportPlugins == null )
{ {
@ -518,7 +515,8 @@ public class DefaultLifecycleBindingManager
for ( Iterator j = reportPlugins.iterator(); j.hasNext() && !found; ) for ( Iterator j = reportPlugins.iterator(); j.hasNext() && !found; )
{ {
ReportPlugin reportPlugin = (ReportPlugin) j.next(); ReportPlugin reportPlugin = (ReportPlugin) j.next();
if ( reportPlugin.getGroupId().equals( groupId ) && reportPlugin.getArtifactId().equals( artifactId ) ) if ( reportPlugin.getGroupId().equals( groupId )
&& reportPlugin.getArtifactId().equals( artifactId ) )
{ {
found = true; found = true;
} }
@ -541,8 +539,8 @@ public class DefaultLifecycleBindingManager
/** /**
* Retrieve any reports from the specified ReportPlugin which are referenced in the specified POM. * Retrieve any reports from the specified ReportPlugin which are referenced in the specified POM.
*/ */
private List getReportsForPlugin( ReportPlugin reportPlugin, ReportSet reportSet, MavenProject project ) private List getReportsForPlugin( final ReportPlugin reportPlugin, final ReportSet reportSet,
throws LifecycleLoaderException final MavenProject project ) throws LifecycleLoaderException
{ {
PluginDescriptor pluginDescriptor; PluginDescriptor pluginDescriptor;
try try
@ -552,7 +550,7 @@ public class DefaultLifecycleBindingManager
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecycleLoaderException( "Failed to load report plugin: " + reportPlugin.getKey() + ". Reason: " throw new LifecycleLoaderException( "Failed to load report plugin: " + reportPlugin.getKey() + ". Reason: "
+ e.getMessage(), e ); + e.getMessage(), e );
} }
String pluginKey = BindingUtils.createPluginKey( reportPlugin.getGroupId(), reportPlugin.getArtifactId() ); String pluginKey = BindingUtils.createPluginKey( reportPlugin.getGroupId(), reportPlugin.getArtifactId() );
@ -565,7 +563,7 @@ public class DefaultLifecycleBindingManager
// TODO: check ID is correct for reports // TODO: check ID is correct for reports
// if the POM configured no reports, give all from plugin // if the POM configured no reports, give all from plugin
if ( reportSet == null || reportSet.getReports().contains( mojoDescriptor.getGoal() ) ) if ( ( reportSet == null ) || reportSet.getReports().contains( mojoDescriptor.getGoal() ) )
{ {
String id = null; String id = null;
if ( reportSet != null ) if ( reportSet != null )
@ -589,7 +587,7 @@ public class DefaultLifecycleBindingManager
plugin.setGroupId( pluginDescriptor.getGroupId() ); plugin.setGroupId( pluginDescriptor.getGroupId() );
plugin.setArtifactId( pluginDescriptor.getArtifactId() ); plugin.setArtifactId( pluginDescriptor.getArtifactId() );
} }
BindingUtils.injectPluginManagementInfo( plugin, project ); BindingUtils.injectPluginManagementInfo( plugin, project );
Map execMap = plugin.getExecutionsAsMap(); Map execMap = plugin.getExecutionsAsMap();
@ -611,126 +609,4 @@ public class DefaultLifecycleBindingManager
return reports; return reports;
} }
/**
* Determine whether the first list contains all of the same MojoBinding instances, in the same
* order, starting at index zero, as the second list. If so, it is either a perfect super-list
* or an equal list, and return true. Return false otherwise.
*/
private static boolean isSameOrSuperListOfMojoBindings( List superCandidate, List check )
{
if ( superCandidate == null || check == null )
{
return false;
}
if ( superCandidate.size() < check.size() )
{
return false;
}
List superKeys = new ArrayList( superCandidate.size() );
for ( Iterator it = superCandidate.iterator(); it.hasNext(); )
{
MojoBinding binding = (MojoBinding) it.next();
superKeys.add( LifecycleUtils.createMojoBindingKey( binding, true ) );
}
List checkKeys = new ArrayList( check.size() );
for ( Iterator it = check.iterator(); it.hasNext(); )
{
MojoBinding binding = (MojoBinding) it.next();
checkKeys.add( LifecycleUtils.createMojoBindingKey( binding, true ) );
}
return superKeys.subList( 0, checkKeys.size() ).equals( checkKeys );
}
/**
* Traverse the specified LifecycleBindings instance for all of the specified tasks. If the task
* is found to be a phase name, construct the list of all MojoBindings that lead up to that phase
* in that lifecycle, and add them to the master MojoBinding list. If the task is not a phase name,
* treat it as a direct mojo invocation, parse it into a MojoBinding (resolving the plugin prefix
* first if necessary), and add it to the master MojoBinding list. Finally, return the master list.
*/
public List assembleMojoBindingList( List tasks, LifecycleBindings bindings, MavenProject project )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
return assembleMojoBindingList( tasks, bindings, Collections.EMPTY_MAP, project );
}
/**
* Traverse the specified LifecycleBindings instance for all of the specified tasks. If the task
* is found to be a phase name, construct the list of all MojoBindings that lead up to that phase
* in that lifecycle, and add them to the master MojoBinding list. If the task is not a phase name,
* treat it as a direct mojo invocation, parse it into a MojoBinding (resolving the plugin prefix
* first if necessary), and add it to the master MojoBinding list.
*
* Then, iterate through all MojoBindings in the master list, and for each one that maps to an
* entry in directInvocationModifiers, substitute the resultant MojoBinding list from that
* modifier in place of the original MojoBinding.
*
* Finally, return the modified master list.
*/
public List assembleMojoBindingList( List tasks, LifecycleBindings lifecycleBindings, Map directInvocationModifiers,
MavenProject project )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
List planBindings = new ArrayList();
List lastMojoBindings = null;
for ( Iterator it = tasks.iterator(); it.hasNext(); )
{
String task = (String) it.next();
LifecycleBinding binding = LifecycleUtils.findLifecycleBindingForPhase( task, lifecycleBindings );
if ( binding != null )
{
List mojoBindings = LifecycleUtils.getMojoBindingListForLifecycle( task, binding );
// save these so we can reference the originals...
List originalMojoBindings = mojoBindings;
// if these mojo bindings are a superset of the last bindings, only add the difference.
if ( isSameOrSuperListOfMojoBindings( mojoBindings, lastMojoBindings ) )
{
List revised = new ArrayList( mojoBindings );
revised.removeAll( lastMojoBindings );
if ( revised.isEmpty() )
{
continue;
}
mojoBindings = revised;
}
planBindings.addAll( mojoBindings );
lastMojoBindings = originalMojoBindings;
}
else
{
MojoBinding mojoBinding = mojoBindingFactory.parseMojoBinding( task, project, true );
BindingUtils.injectProjectConfiguration( mojoBinding, project );
mojoBinding.setOrigin( "direct invocation" );
String key = LifecycleUtils.createMojoBindingKey( mojoBinding, true );
DirectInvocationModifier modifier = (DirectInvocationModifier) directInvocationModifiers.get( key );
if ( modifier != null )
{
planBindings.addAll( modifier.getModifiedBindings( project, this ) );
}
else
{
planBindings.add( mojoBinding );
}
}
}
return planBindings;
}
} }

View File

@ -3,21 +3,18 @@ package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleLoaderException; import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException; import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.model.LifecycleBindings; import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.plan.LifecyclePlannerException;
import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Responsible for the gross construction of LifecycleBindings, or mappings of MojoBinding instances * Responsible for the gross construction of LifecycleBindings, or mappings of MojoBinding instances to different parts
* to different parts of the three lifecycles: clean, build, and site. Also, handles transcribing * of the three lifecycles: clean, build, and site. Also, handles transcribing these LifecycleBindings instances into
* these LifecycleBindings instances into lists of MojoBinding's, which can be consumed by the * lists of MojoBinding's, which can be consumed by the LifecycleExecutor.
* LifecycleExecutor.
* *
* @author jdcasey * @author jdcasey
* *
*/ */
public interface LifecycleBindingManager public interface LifecycleBindingManager
{ {
@ -25,74 +22,43 @@ public interface LifecycleBindingManager
String ROLE = LifecycleBindingManager.class.getName(); String ROLE = LifecycleBindingManager.class.getName();
/** /**
* Construct the LifecycleBindings for the default lifecycle mappings, including injection of * Construct the LifecycleBindings for the default lifecycle mappings, including injection of configuration from the
* configuration from the project into each MojoBinding, where appropriate. * project into each MojoBinding, where appropriate.
*/ */
LifecycleBindings getDefaultBindings( MavenProject project ) LifecycleBindings getDefaultBindings( MavenProject project ) throws LifecycleSpecificationException;
throws LifecycleSpecificationException;
/** /**
* Retrieve the LifecycleBindings given by the lifecycle mapping component/file for the project's * Retrieve the LifecycleBindings given by the lifecycle mapping component/file for the project's packaging. Any
* packaging. Any applicable mojo configuration will be injected into the LifecycleBindings from * applicable mojo configuration will be injected into the LifecycleBindings from the POM.
* the POM.
*/ */
LifecycleBindings getBindingsForPackaging( MavenProject project ) LifecycleBindings getBindingsForPackaging( MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException; throws LifecycleLoaderException, LifecycleSpecificationException;
/** /**
* Construct the LifecycleBindings that constitute the extra mojos bound to the lifecycle within * Construct the LifecycleBindings that constitute the extra mojos bound to the lifecycle within the POM itself.
* the POM itself.
*/ */
LifecycleBindings getProjectCustomBindings( MavenProject project ) LifecycleBindings getProjectCustomBindings( MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException; throws LifecycleLoaderException, LifecycleSpecificationException;
/** /**
* Construct the LifecycleBindings that constitute the mojos mapped to the lifecycles by an overlay * Construct the LifecycleBindings that constitute the mojos mapped to the lifecycles by an overlay specified in a
* specified in a plugin. Inject mojo configuration from the POM into all appropriate MojoBinding * plugin. Inject mojo configuration from the POM into all appropriate MojoBinding instances.
* instances.
*/ */
LifecycleBindings getPluginLifecycleOverlay( PluginDescriptor pluginDescriptor, String lifecycleId, MavenProject project ) LifecycleBindings getPluginLifecycleOverlay( PluginDescriptor pluginDescriptor, String lifecycleId,
MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException; throws LifecycleLoaderException, LifecycleSpecificationException;
/** /**
* Retrieve the list of MojoBinding instances that correspond to the reports configured for the * Retrieve the list of MojoBinding instances that correspond to the reports configured for the specified project.
* specified project. Inject all appropriate configuration from the POM for each MojoBinding, using * Inject all appropriate configuration from the POM for each MojoBinding, using the following precedence rules:
* the following precedence rules:
* <br/> * <br/>
* <ol> * <ol>
* <li>report-set-level configuration</li> * <li>report-set-level configuration</li>
* <li>reporting-level configuration</li> * <li>reporting-level configuration</li>
* <li>execution-level configuration</li> * <li>execution-level configuration</li>
* <li>plugin-level configuration</li> * <li>plugin-level configuration</li>
* </ol> * </ol>
*/ */
List getReportBindings( MavenProject project ) List getReportBindings( MavenProject project ) throws LifecycleLoaderException, LifecycleSpecificationException;
throws LifecycleLoaderException, LifecycleSpecificationException;
/**
* Traverse the specified LifecycleBindings instance for all of the specified tasks. If the task
* is found to be a phase name, construct the list of all MojoBindings that lead up to that phase
* in that lifecycle, and add them to the master MojoBinding list. If the task is not a phase name,
* treat it as a direct mojo invocation, parse it into a MojoBinding (resolving the plugin prefix
* first if necessary), and add it to the master MojoBinding list.
*
* Then, iterate through all MojoBindings in the master list, and for each one that maps to an
* entry in directInvocationModifiers, substitute the resultant MojoBinding list from that
* modifier in place of the original MojoBinding.
*
* Finally, return the modified master list.
*/
List assembleMojoBindingList( List tasks, LifecycleBindings bindings, Map directInvocationModifiers, MavenProject project )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException;
/**
* Traverse the specified LifecycleBindings instance for all of the specified tasks. If the task
* is found to be a phase name, construct the list of all MojoBindings that lead up to that phase
* in that lifecycle, and add them to the master MojoBinding list. If the task is not a phase name,
* treat it as a direct mojo invocation, parse it into a MojoBinding (resolving the plugin prefix
* first if necessary), and add it to the master MojoBinding list. Finally, return the master list.
*/
List assembleMojoBindingList( List tasks, LifecycleBindings lifecycleBindings, MavenProject project )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException;
} }

View File

@ -0,0 +1,282 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.MojoBindingUtils;
import org.apache.maven.lifecycle.NoSuchPhaseException;
import org.apache.maven.lifecycle.model.LifecycleBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
public class BuildPlan
{
private LifecycleBindings bindings;
private final List tasks;
private final Map forks;
private final List lateBoundMojos;
private List renderedLifecycleMojos = new ArrayList();
private final Map directInvocationBindings;
public BuildPlan( final LifecycleBindings packaging, final LifecycleBindings projectBindings,
final LifecycleBindings defaults, final List tasks )
throws LifecycleSpecificationException, LifecycleLoaderException
{
this( LifecycleUtils.mergeBindings( packaging, projectBindings, defaults, true, false ), tasks );
}
public BuildPlan( final LifecycleBindings bindings, final List tasks )
throws LifecycleSpecificationException, LifecycleLoaderException
{
this.bindings = bindings;
this.tasks = tasks;
forks = new HashMap();
lateBoundMojos = new ArrayList();
directInvocationBindings = new HashMap();
}
private BuildPlan( final LifecycleBindings bindings, final Map forks, final List lateBoundMojos,
final Map directInvocationBindings, final List tasks )
{
this.bindings = LifecycleUtils.cloneBindings( bindings );
this.forks = new HashMap( forks );
this.lateBoundMojos = new ArrayList( lateBoundMojos );
this.tasks = tasks;
this.directInvocationBindings = new HashMap( directInvocationBindings );
}
public void addLifecycleOverlay( final LifecycleBindings overlay )
{
bindings = LifecycleUtils.mergeBindings( overlay, bindings, null, true, true );
}
public void addTask( final String task, final MojoBinding binding )
throws LifecycleSpecificationException, LifecycleLoaderException
{
tasks.add( task );
if ( !LifecycleUtils.isValidPhaseName( task ) )
{
addDirectInvocationBinding( task, binding );
}
}
public LifecycleBindings getLifecycleBindings()
{
return bindings;
}
public List getTasks()
{
return tasks;
}
public void addDirectInvocationBinding( final String key, final MojoBinding binding )
{
directInvocationBindings.put( MojoBindingUtils.createMojoBindingKey( binding, false ), binding );
directInvocationBindings.put( key, binding );
}
public List getLateBoundMojos()
{
return lateBoundMojos;
}
public Map getDirectInvocationBindings()
{
return directInvocationBindings;
}
public Map getForks()
{
return forks;
}
public void addForkedExecution( final MojoBinding mojoBinding, final BuildPlan plan )
{
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
forks.put( key, plan );
}
public void addForkedExecution( final MojoBinding mojoBinding, final List forkedInvocations )
{
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
forks.put( key, forkedInvocations );
}
public void addLateBoundMojo( final MojoBinding mojoBinding )
{
lateBoundMojos.add( MojoBindingUtils.createMojoBindingKey( mojoBinding, false ) );
}
public BuildPlan copy( final List newTasks )
{
return new BuildPlan( bindings, forks, lateBoundMojos, directInvocationBindings, newTasks );
}
public void resetExecutionProgress()
{
renderedLifecycleMojos = new ArrayList();
}
public List renderExecutionPlan( final Stack executionStack )
throws NoSuchPhaseException
{
List plan = new ArrayList();
for ( Iterator it = tasks.iterator(); it.hasNext(); )
{
String task = (String) it.next();
if ( LifecycleUtils.isValidPhaseName( task ) )
{
// find the lifecyle that this task belongs in...
LifecycleBinding binding = LifecycleUtils.findLifecycleBindingForPhase( task, bindings );
// get the list of mojo bindings before or at the specified phase in the lifecycle
List bindingsToAdd = LifecycleUtils.getMojoBindingListForLifecycle( task, binding );
// backup copy for rendered tracking...
List newRendered = new ArrayList( bindingsToAdd );
// if we've already executed part of the lifecycle, just continue with the new bindings.
if ( ( renderedLifecycleMojos != null ) && ( renderedLifecycleMojos.size() < bindingsToAdd.size() ) )
{
bindingsToAdd = bindingsToAdd.subList( renderedLifecycleMojos.size(), bindingsToAdd.size() );
}
// save the current binding list for tracking progress through the lifecycle.
renderedLifecycleMojos = newRendered;
for ( Iterator itMojos = bindingsToAdd.iterator(); itMojos.hasNext(); )
{
MojoBinding mojoBinding = (MojoBinding) itMojos.next();
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
if ( !executionStack.contains( key ) )
{
addResolverIfLateBound( mojoBinding, plan );
plan.addAll( findForkedBindings( mojoBinding, executionStack ) );
}
}
}
else
{
MojoBinding mojoBinding = (MojoBinding) directInvocationBindings.get( task );
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
if ( !executionStack.contains( key ) )
{
addResolverIfLateBound( mojoBinding, plan );
plan.addAll( findForkedBindings( mojoBinding, executionStack ) );
}
}
}
return plan;
}
private void addResolverIfLateBound( final MojoBinding mojoBinding, final List plan )
{
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
if ( lateBoundMojos.contains( key ) )
{
MojoBinding resolveBinding = StateManagementUtils.createResolveLateBoundMojoBinding( mojoBinding );
plan.add( resolveBinding );
}
}
private List findForkedBindings( final MojoBinding mojoBinding, final Stack executionStack )
throws NoSuchPhaseException
{
List bindings = new ArrayList();
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
// let's see if we have any forks...
Object fork = forks.get( key );
executionStack.push( key );
try
{
if ( fork != null )
{
List forkedBindings = new ArrayList();
// if the fork is a build plan, recurse into it and retrieve the execution plan.
if ( fork instanceof BuildPlan )
{
forkedBindings = ( (BuildPlan) fork ).renderExecutionPlan( executionStack );
}
// leave room for new kinds of forks, and do some extra validation...
// if this is a list, it's a list of direct mojo invocations...we have to see if they have their own
// forks.
else if ( fork instanceof List )
{
List directInvocations = (List) fork;
for ( Iterator it = directInvocations.iterator(); it.hasNext(); )
{
MojoBinding invocation = (MojoBinding) it.next();
String invocationKey = MojoBindingUtils.createMojoBindingKey( invocation, false );
if ( executionStack.contains( invocationKey ) )
{
continue;
}
executionStack.push( MojoBindingUtils.createMojoBindingKey( mojoBinding, false ) );
try
{
addResolverIfLateBound( invocation, forkedBindings );
forkedBindings.addAll( findForkedBindings( invocation, executionStack ) );
}
finally
{
executionStack.pop();
}
}
}
if ( !forkedBindings.isEmpty() )
{
bindings.add( StateManagementUtils.createStartForkedExecutionMojoBinding() );
bindings.addAll( forkedBindings );
bindings.add( StateManagementUtils.createClearForkedExecutionMojoBinding() );
}
bindings.add( mojoBinding );
if ( !forkedBindings.isEmpty() )
{
bindings.add( StateManagementUtils.createEndForkedExecutionMojoBinding() );
}
}
else
{
bindings.add( mojoBinding );
}
}
finally
{
executionStack.pop();
}
return bindings;
}
}

View File

@ -1,19 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.project.MavenProject;
import java.util.List;
public interface BuildPlanIfc
extends ModifiablePlanElement
{
List getPlanMojoBindings(MavenProject project, LifecycleBindingManager bindingManager)
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException;
List getTasks();
}

View File

@ -1,20 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.model.LifecycleBindings;
/**
* Modifies an existing set of lifecycle mojo bindings, in order to inject extra behavior, such as
* forked executions, reporting, etc.
*/
public interface BuildPlanModifier extends ModifiablePlanElement
{
/**
* Inject any modifications into the given LifecycleBindings provided by the build plan. In some
* cases, it may be necessary to regenerate the LifecycleBindings instance, so the altered instance
* is returned separately.
*/
LifecycleBindings modifyBindings( LifecycleBindings bindings )
throws LifecyclePlannerException;
}

View File

@ -1,21 +1,17 @@
package org.apache.maven.lifecycle.plan; package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException; import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.MojoBindingUtils; import org.apache.maven.lifecycle.MojoBindingUtils;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils; import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import org.apache.maven.project.MavenProject;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Stack;
/** /**
* Collection of static utility methods used to work with LifecycleBindings and other collections * Collection of static utility methods used to work with LifecycleBindings and other collections of MojoBinding
* of MojoBinding instances that make up a build plan. * instances that make up a build plan.
*/ */
public final class BuildPlanUtils public final class BuildPlanUtils
{ {
@ -25,55 +21,23 @@ public final class BuildPlanUtils
} }
/** /**
* Inject a set of {@link BuildPlanModifier} instances into an existing LifecycleBindings instance. * Render an entire build plan to a String. If extendedInfo == true, include each MojoBinding's configuration in the
* This is a generalization of a piece of code present in almost all scenarios where a build * output.
* plan contains modifiers and is asked to produce an effective list of MojoBinding instances
* that make up the build process. Simply iterate through the modifiers, and apply each one,
* replacing the previous LifecycleBindings instance with the result of the current modifier.
*/ */
public static LifecycleBindings modifyPlanBindings( LifecycleBindings bindings, List planModifiers ) public static String listBuildPlan( final BuildPlan plan, final boolean extendedInfo )
throws LifecyclePlannerException throws LifecycleSpecificationException, LifecyclePlannerException
{ {
LifecycleBindings result; List mojos = plan.renderExecutionPlan( new Stack() );
plan.resetExecutionProgress();
// if the bindings are completely empty, passing in null avoids an extra instance creation return listBuildPlan( mojos, extendedInfo );
// for the purposes of cloning...
if ( bindings != null )
{
result = LifecycleUtils.cloneBindings( bindings );
}
else
{
result = new LifecycleBindings();
}
for ( Iterator it = planModifiers.iterator(); it.hasNext(); )
{
BuildPlanModifier modifier = (BuildPlanModifier) it.next();
result = modifier.modifyBindings( result );
}
return result;
} }
/** /**
* Render an entire build plan to a String. * Render a list containing the MojoBinding instances for an entire build plan to a String. If extendedInfo == true,
* If extendedInfo == true, include each MojoBinding's configuration in the output. * include each MojoBinding's configuration in the output.
*/ */
public static String listBuildPlan( BuildPlan plan, MavenProject project, LifecycleBindingManager lifecycleBindingManager, boolean extendedInfo ) public static String listBuildPlan( final List mojoBindings, final boolean extendedInfo )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
List mojoBindings = plan.getPlanMojoBindings( project, lifecycleBindingManager );
return listBuildPlan( mojoBindings, extendedInfo );
}
/**
* Render a list containing the MojoBinding instances for an entire build plan to a String.
* If extendedInfo == true, include each MojoBinding's configuration in the output.
*/
public static String listBuildPlan( List mojoBindings, boolean extendedInfo )
throws LifecycleSpecificationException, LifecyclePlannerException throws LifecycleSpecificationException, LifecyclePlannerException
{ {
StringBuffer listing = new StringBuffer(); StringBuffer listing = new StringBuffer();
@ -119,7 +83,7 @@ public final class BuildPlanUtils
{ {
listing.append( ' ' ).append( formatMojoListing( binding, indentLevel, extendedInfo ) ); listing.append( ' ' ).append( formatMojoListing( binding, indentLevel, extendedInfo ) );
} }
indentLevel++; indentLevel++;
} }
else else
@ -135,10 +99,10 @@ public final class BuildPlanUtils
} }
/** /**
* Append a newline character, add the next line's number, and indent the new line to the * Append a newline character, add the next line's number, and indent the new line to the appropriate level (which
* appropriate level (which tracks separate forked executions). * tracks separate forked executions).
*/ */
private static void newListingLine( StringBuffer listing, int indentLevel, int counter ) private static void newListingLine( final StringBuffer listing, final int indentLevel, final int counter )
{ {
listing.append( '\n' ); listing.append( '\n' );
@ -155,10 +119,10 @@ public final class BuildPlanUtils
} }
/** /**
* Format a single MojoBinding for inclusion in a build plan listing. If extendedInfo == true, * Format a single MojoBinding for inclusion in a build plan listing. If extendedInfo == true, include the
* include the MojoBinding's configuration in the output. * MojoBinding's configuration in the output.
*/ */
public static String formatMojoListing( MojoBinding binding, int indentLevel, boolean extendedInfo ) public static String formatMojoListing( final MojoBinding binding, final int indentLevel, final boolean extendedInfo )
{ {
StringBuffer listing = new StringBuffer(); StringBuffer listing = new StringBuffer();
@ -169,7 +133,8 @@ public final class BuildPlanUtils
{ {
listing.append( "\nOrigin: " ).append( binding.getOrigin() ); listing.append( "\nOrigin: " ).append( binding.getOrigin() );
listing.append( "\nConfiguration:\n\t" ).append( listing.append( "\nConfiguration:\n\t" ).append(
String.valueOf( binding.getConfiguration() ).replaceAll( "\\n", String.valueOf( binding.getConfiguration() ).replaceAll(
"\\n",
"\n\t" ) ).append( "\n\t" ) ).append(
'\n' ); '\n' );
} }

View File

@ -7,14 +7,13 @@ import org.apache.maven.project.MavenProject;
import java.util.List; import java.util.List;
/** /**
* Responsible for creating a plan of execution for a given project and list of tasks. This build plan * Responsible for creating a plan of execution for a given project and list of tasks. This build plan consists of
* consists of MojoBinding instances that carry all the information necessary to execute a mojo, * MojoBinding instances that carry all the information necessary to execute a mojo, including configuration from the
* including configuration from the POM and other sources. NOTE: the build plan may be constructed * POM and other sources. NOTE: the build plan may be constructed of a main lifecycle binding-set, plus any number of
* of a main lifecycle binding-set, plus any number of lifecycle modifiers and direct-invocation * lifecycle modifiers and direct-invocation modifiers, to handle cases of forked execution.
* modifiers, to handle cases of forked execution.
* *
* @author jdcasey * @author jdcasey
* *
*/ */
public interface BuildPlanner public interface BuildPlanner
{ {

View File

@ -8,7 +8,6 @@ import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.binding.MojoBindingFactory; import org.apache.maven.lifecycle.binding.MojoBindingFactory;
import org.apache.maven.lifecycle.model.LifecycleBindings; import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.loader.PluginLoader; import org.apache.maven.plugin.loader.PluginLoader;
@ -17,21 +16,20 @@ import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.logging.LogEnabled; import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.logging.Logger;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Stack;
/** /**
* Responsible for creating a plan of execution for a given project and list of tasks. This build plan * Responsible for creating a plan of execution for a given project and list of tasks. This build plan consists of
* consists of MojoBinding instances that carry all the information necessary to execute a mojo, * MojoBinding instances that carry all the information necessary to execute a mojo, including configuration from the
* including configuration from the POM and other sources. NOTE: the build plan may be constructed * POM and other sources. NOTE: the build plan may be constructed of a main lifecycle binding-set, plus any number of
* of a main lifecycle binding-set, plus any number of lifecycle modifiers and direct-invocation * lifecycle modifiers and direct-invocation modifiers, to handle cases of forked execution.
* modifiers, to handle cases of forked execution.
* *
* @author jdcasey * @author jdcasey
* *
*/ */
public class DefaultBuildPlanner public class DefaultBuildPlanner
implements BuildPlanner, LogEnabled implements BuildPlanner, LogEnabled
@ -48,159 +46,177 @@ public class DefaultBuildPlanner
/** /**
* Orchestrates construction of the build plan which will be used by the user of LifecycleExecutor. * Orchestrates construction of the build plan which will be used by the user of LifecycleExecutor.
*/ */
public BuildPlan constructBuildPlan( List tasks, MavenProject project ) public BuildPlan constructBuildPlan( final List tasks, final MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException, LifecyclePlannerException throws LifecycleLoaderException, LifecycleSpecificationException, LifecyclePlannerException
{ {
LifecycleBindings defaultBindings = lifecycleBindingManager.getDefaultBindings( project ); LifecycleBindings defaultBindings = lifecycleBindingManager.getDefaultBindings( project );
LifecycleBindings packagingBindings = lifecycleBindingManager.getBindingsForPackaging( project ); LifecycleBindings packagingBindings = lifecycleBindingManager.getBindingsForPackaging( project );
LifecycleBindings projectBindings = lifecycleBindingManager.getProjectCustomBindings( project ); LifecycleBindings projectBindings = lifecycleBindingManager.getProjectCustomBindings( project );
LifecycleBindings merged = LifecycleUtils.mergeBindings( packagingBindings, projectBindings, defaultBindings, true, false ); BuildPlan plan = new BuildPlan( packagingBindings, projectBindings, defaultBindings, tasks );
// foreach task, find the binding list from the merged lifecycle-bindings. initializeDirectInvocations( plan, project );
// if the binding list is a super-set of a previous task, forget the previous task/binding
// list, and use the new one.
// if the binding list is null, treat it like a one-off mojo invocation, and parse/validate
// that it can be called as such.
// as binding lists accumulate, push them onto an aggregated "plan" listing...
BuildPlan plan = new LifecycleBuildPlan( tasks, merged );
// Inject forked lifecycles as plan modifiers for each mojo that has @execute in it. // Inject forked lifecycles as plan modifiers for each mojo that has @execute in it.
addForkedLifecycleModifiers( plan, merged, project, tasks ); addForkedLifecycleModifiers( plan, project );
addReportingLifecycleModifiers( plan, merged, project, tasks ); addReportingLifecycleModifiers( plan, project );
// TODO: Inject relative-ordered project/plugin executions as plan modifiers. // TODO: Inject relative-ordered project/plugin executions as plan modifiers.
return plan; return plan;
} }
public void enableLogging( Logger logger ) private void initializeDirectInvocations( final BuildPlan plan, final MavenProject project )
throws LifecycleSpecificationException, LifecycleLoaderException
{
List tasks = plan.getTasks();
for ( Iterator it = tasks.iterator(); it.hasNext(); )
{
String task = (String) it.next();
if ( !LifecycleUtils.isValidPhaseName( task ) )
{
MojoBinding binding = mojoBindingFactory.parseMojoBinding( task, project, true );
plan.addDirectInvocationBinding( task, binding );
}
}
}
public void enableLogging( final Logger logger )
{ {
this.logger = logger; this.logger = logger;
} }
/** /**
* Traverses all MojoBinding instances discovered from the POM and its packaging-mappings, and * Traverses all MojoBinding instances discovered from the POM and its packaging-mappings, and orchestrates the
* orchestrates the process of injecting any modifiers that are necessary to accommodate forked * process of injecting any modifiers that are necessary to accommodate forked execution.
* execution.
*/ */
private void addForkedLifecycleModifiers( ModifiablePlanElement planElement, LifecycleBindings lifecycleBindings, private void addForkedLifecycleModifiers( final BuildPlan plan, final MavenProject project )
MavenProject project, List tasks )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
List planBindings = lifecycleBindingManager.assembleMojoBindingList( tasks, lifecycleBindings, project ); List planBindings = plan.renderExecutionPlan( new Stack() );
plan.resetExecutionProgress();
for ( Iterator it = planBindings.iterator(); it.hasNext(); ) for ( Iterator it = planBindings.iterator(); it.hasNext(); )
{ {
MojoBinding mojoBinding = (MojoBinding) it.next(); MojoBinding mojoBinding = (MojoBinding) it.next();
findForkModifiers( mojoBinding, planElement, lifecycleBindings, project ); findForkModifiers( mojoBinding, plan, project );
} }
} }
private void findForkModifiers( MojoBinding mojoBinding, ModifiablePlanElement planElement, private void findForkModifiers( final MojoBinding mojoBinding, final BuildPlan plan, final MavenProject project )
LifecycleBindings lifecycleBindings, MavenProject project )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
PluginDescriptor pluginDescriptor; PluginDescriptor pluginDescriptor = null;
try try
{ {
pluginDescriptor = pluginLoader.loadPlugin( mojoBinding, project ); pluginDescriptor = pluginLoader.loadPlugin( mojoBinding, project );
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecyclePlannerException( e.getMessage(), e ); String message =
"Failed to load plugin: " + MojoBindingUtils.createPluginKey( mojoBinding )
+ ". Adding to late-bound plugins list.\nReason: " + e.getMessage();
if ( logger.isDebugEnabled() )
{
logger.debug( message, e );
}
else
{
logger.warn( message );
}
plan.addLateBoundMojo( mojoBinding );
}
if ( pluginDescriptor == null )
{
return;
} }
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() ); MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() );
if ( mojoDescriptor == null ) if ( mojoDescriptor == null )
{ {
throw new LifecyclePlannerException( "Mojo: " + mojoBinding.getGoal() + " does not exist in plugin: " throw new LifecyclePlannerException( "Mojo: " + mojoBinding.getGoal() + " does not exist in plugin: "
+ pluginDescriptor.getId() + "." ); + pluginDescriptor.getId() + "." );
} }
findForkModifiers( mojoBinding, pluginDescriptor, planElement, lifecycleBindings, project, new LinkedList() ); findForkModifiers( mojoBinding, pluginDescriptor, plan, project );
} }
/** /**
* Traverses all MojoBinding instances discovered from the POM and its packaging-mappings, and * Traverses all MojoBinding instances discovered from the POM and its packaging-mappings, and orchestrates the
* orchestrates the process of injecting any modifiers that are necessary to accommodate mojos * process of injecting any modifiers that are necessary to accommodate mojos that require access to the project's
* that require access to the project's configured reports. * configured reports.
*/ */
private void addReportingLifecycleModifiers( ModifiablePlanElement planElement, LifecycleBindings lifecycleBindings, private void addReportingLifecycleModifiers( final BuildPlan plan, final MavenProject project )
MavenProject project, List tasks )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
List planBindings = lifecycleBindingManager.assembleMojoBindingList( tasks, lifecycleBindings, project ); List planBindings = plan.renderExecutionPlan( new Stack() );
plan.resetExecutionProgress();
for ( Iterator it = planBindings.iterator(); it.hasNext(); ) for ( Iterator it = planBindings.iterator(); it.hasNext(); )
{ {
MojoBinding mojoBinding = (MojoBinding) it.next(); MojoBinding mojoBinding = (MojoBinding) it.next();
PluginDescriptor pluginDescriptor; PluginDescriptor pluginDescriptor = null;
try try
{ {
pluginDescriptor = pluginLoader.loadPlugin( mojoBinding, project ); pluginDescriptor = pluginLoader.loadPlugin( mojoBinding, project );
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecyclePlannerException( e.getMessage(), e ); String message =
"Failed to load plugin: " + MojoBindingUtils.createPluginKey( mojoBinding )
+ ". Adding to late-bound plugins list.\nReason: " + e.getMessage();
if ( logger.isDebugEnabled() )
{
logger.debug( message, e );
}
else
{
logger.warn( message );
}
plan.addLateBoundMojo( mojoBinding );
}
if ( pluginDescriptor == null )
{
continue;
} }
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() ); MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() );
if ( mojoDescriptor == null ) if ( mojoDescriptor == null )
{ {
throw new LifecyclePlannerException( "Mojo: " + mojoBinding.getGoal() + " does not exist in plugin: " throw new LifecyclePlannerException( "Mojo: " + mojoBinding.getGoal() + " does not exist in plugin: "
+ pluginDescriptor.getId() + "." ); + pluginDescriptor.getId() + "." );
} }
if ( mojoDescriptor.isRequiresReports() ) if ( mojoDescriptor.isRequiresReports() )
{ {
List reportBindings = lifecycleBindingManager.getReportBindings( project ); List reportBindings = lifecycleBindingManager.getReportBindings( project );
// findForkModifiers( mojoBinding, pluginDescriptor, planElement, lifecycleBindings,
// project, forkingBindings, tasks );
for ( Iterator reportBindingIt = reportBindings.iterator(); reportBindingIt.hasNext(); ) for ( Iterator reportBindingIt = reportBindings.iterator(); reportBindingIt.hasNext(); )
{ {
MojoBinding reportBinding = (MojoBinding) reportBindingIt.next(); MojoBinding reportBinding = (MojoBinding) reportBindingIt.next();
PluginDescriptor pd;
try try
{ {
pd = pluginLoader.loadReportPlugin( mojoBinding, project ); pluginLoader.loadReportPlugin( mojoBinding, project );
} }
catch ( PluginLoaderException e ) catch ( PluginLoaderException e )
{ {
throw new LifecyclePlannerException( "Failed to load report-plugin descriptor for: " throw new LifecyclePlannerException( "Failed to load report-plugin descriptor for: "
+ MojoBindingUtils.toString( reportBinding ) + ". Reason: " + e.getMessage(), e ); + MojoBindingUtils.toString( reportBinding )
} + ". Reason: " + e.getMessage(), e );
// findForkModifiers( reportBinding, planElement, lifecycleBindings, project );
}
Phase phase = LifecycleUtils.findPhaseForMojoBinding( mojoBinding, lifecycleBindings, true );
if ( phase == null )
{
if ( planElement instanceof DirectInvocationOriginElement )
{
DirectInvocationModifier modder = new SimpleDirectInvocationModifier( mojoBinding, reportBindings );
( (DirectInvocationOriginElement) planElement ).addDirectInvocationModifier( modder );
}
else
{
throw new LifecyclePlannerException( "Cannot inject reports for direct invocation: "
+ MojoBindingUtils.toString( mojoBinding )
+ "; current plan element does not accept direct-invocation modifiers." );
} }
} }
else
{
BuildPlanModifier modder = new ReportingPlanModifier( mojoBinding, reportBindings );
planElement.addModifier( modder ); plan.addForkedExecution( mojoBinding, reportBindings );
}
// NOTE: the first sighting of a mojo requiring reports should satisfy this condition. // NOTE: the first sighting of a mojo requiring reports should satisfy this condition.
// therefore, we can break out as soon as we find one. // therefore, we can break out as soon as we find one.
@ -210,159 +226,38 @@ public class DefaultBuildPlanner
} }
/** /**
* Explores a single MojoBinding, and injects any necessary plan modifiers to accommodate any * Explores a single MojoBinding, and injects any necessary plan modifiers to accommodate any of the three types of
* of the three types of forked execution, along with any new mojos/lifecycles that entails. * forked execution, along with any new mojos/lifecycles that entails.
*/ */
private void findForkModifiers( MojoBinding mojoBinding, PluginDescriptor pluginDescriptor, private void findForkModifiers( final MojoBinding mojoBinding, final PluginDescriptor pluginDescriptor,
ModifiablePlanElement planElement, LifecycleBindings mergedBindings, MavenProject project, final BuildPlan plan, final MavenProject project )
LinkedList forkingBindings )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
forkingBindings.addLast( mojoBinding ); String referencingGoal = mojoBinding.getGoal();
try MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( referencingGoal );
if ( mojoDescriptor.getExecuteGoal() != null )
{ {
String referencingGoal = mojoBinding.getGoal(); recurseSingleMojoFork( mojoBinding, pluginDescriptor, plan, project );
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( referencingGoal );
if ( mojoDescriptor.getExecuteGoal() != null )
{
recurseSingleMojoFork( mojoBinding, pluginDescriptor, planElement, mergedBindings, project, forkingBindings );
}
else if ( mojoDescriptor.getExecutePhase() != null )
{
recursePhaseMojoFork( mojoBinding, pluginDescriptor, planElement, mergedBindings, project, forkingBindings );
}
} }
finally else if ( mojoDescriptor.getExecutePhase() != null )
{ {
forkingBindings.removeLast(); recursePhaseMojoFork( mojoBinding, pluginDescriptor, plan, project );
} }
} }
/** /**
* Handles exploration of a single-mojo forked execution for further forkings, and also performs * Constructs the lifecycle bindings used to execute a particular fork, given the forking mojo binding. If the mojo
* the actual build-plan modification for that single-mojo forked execution. * binding specifies a lifecycle overlay, this method will add that into the forked lifecycle, and calculate the
*/ * bindings to inject based on the phase in that new lifecycle which should be executed.
private void modifyBuildPlanForForkedDirectInvocation( MojoBinding invokedBinding, MojoBinding invokedVia,
PluginDescriptor pluginDescriptor, ModifiablePlanElement planElement,
LifecycleBindings mergedBindings, MavenProject project,
LinkedList forkingBindings )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{
if ( planElement instanceof DirectInvocationOriginElement )
{
List noTasks = Collections.EMPTY_LIST;
LifecycleBindings forkedBindings = new LifecycleBindings();
LifecycleBuildPlan forkedPlan = new LifecycleBuildPlan( noTasks, forkedBindings );
forkingBindings.addLast( invokedBinding );
try
{
findForkModifiers( invokedBinding, pluginDescriptor, forkedPlan, forkedBindings, project, forkingBindings );
}
finally
{
forkingBindings.removeLast();
}
List forkedMojos = new ArrayList();
forkedMojos.addAll( lifecycleBindingManager.assembleMojoBindingList( noTasks, forkedBindings, project ) );
forkedMojos.add( invokedBinding );
DirectInvocationModifier modifier = new ForkedDirectInvocationModifier( invokedVia, forkedMojos );
( (DirectInvocationOriginElement) planElement ).addDirectInvocationModifier( modifier );
}
else
{
throw new LifecyclePlannerException( "Mojo: " + MojoBindingUtils.toString( invokedVia )
+ " is not bound to the lifecycle; you cannot attach this mojo to a build-plan modifier." );
}
}
/**
* Handles exploration of a lifecycle-based forked execution for further forkings, and also performs
* the actual build-plan modification for that lifecycle-based forked execution.
*/
private void modifyBuildPlanForForkedLifecycle( MojoBinding mojoBinding, PluginDescriptor pluginDescriptor,
ModifiablePlanElement planElement, LifecycleBindings bindings,
MavenProject project, LinkedList forkingBindings )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() );
String phase = mojoDescriptor.getExecutePhase();
List forkedPhaseBindingList = lifecycleBindingManager.assembleMojoBindingList( Collections.singletonList( phase ),
bindings, project );
ModifiablePlanElement mpe;
// setup the ModifiablePlanElement, into which we'll recurse to find further modifications.
if ( LifecycleUtils.findPhaseForMojoBinding( mojoBinding, bindings, true ) != null )
{
mpe = new ForkPlanModifier( mojoBinding, forkedPhaseBindingList );
}
else if ( planElement instanceof BuildPlan )
{
mpe = new SubLifecycleBuildPlan( phase, bindings );
}
else
{
throw new LifecyclePlannerException( "Mojo: " + MojoBindingUtils.toString( mojoBinding )
+ " is not bound to the lifecycle; you cannot attach this mojo to a build-plan modifier." );
}
// recurse, to find further modifications, using the ModifiablePlanElement from above, along
// with the modified task list (which doesn't contain the direct-invocation task that landed
// us here...
for ( Iterator it = forkedPhaseBindingList.iterator(); it.hasNext(); )
{
MojoBinding forkedBinding = (MojoBinding) it.next();
PluginDescriptor forkedPluginDescriptor;
try
{
forkedPluginDescriptor = pluginLoader.loadPlugin( forkedBinding, project );
}
catch ( PluginLoaderException e )
{
throw new LifecyclePlannerException( e.getMessage(), e );
}
findForkModifiers( forkedBinding, forkedPluginDescriptor, mpe, bindings, project, forkingBindings );
}
// now that we've discovered any deeper modifications, add the current MPE to the parent MPE
// in the appropriate location.
if ( LifecycleUtils.findPhaseForMojoBinding( mojoBinding, bindings, true ) != null )
{
planElement.addModifier( (BuildPlanModifier) mpe );
}
else if ( planElement instanceof DirectInvocationOriginElement )
{
List planMojoBindings = ( (BuildPlan) mpe ).getPlanMojoBindings( project, lifecycleBindingManager );
ForkedDirectInvocationModifier modifier = new ForkedDirectInvocationModifier( mojoBinding, planMojoBindings );
( (DirectInvocationOriginElement) planElement ).addDirectInvocationModifier( modifier );
}
}
/**
* Constructs the lifecycle bindings used to execute a particular fork, given the forking mojo
* binding. If the mojo binding specifies a lifecycle overlay, this method will add that into
* the forked lifecycle, and calculate the bindings to inject based on the phase in that new
* lifecycle which should be executed.
* *
* Hands off to the {@link DefaultBuildPlanner#modifyBuildPlanForForkedLifecycle(MojoBinding, PluginDescriptor, ModifiablePlanElement, LifecycleBindings, MavenProject, LinkedList, List)} * Hands off to the
* {@link DefaultBuildPlanner#modifyBuildPlanForForkedLifecycle(MojoBinding, PluginDescriptor, ModifiablePlanElement, LifecycleBindings, MavenProject, LinkedList, List)}
* method to handle the actual plan modification. * method to handle the actual plan modification.
*/ */
private void recursePhaseMojoFork( MojoBinding mojoBinding, PluginDescriptor pluginDescriptor, private void recursePhaseMojoFork( final MojoBinding mojoBinding, final PluginDescriptor pluginDescriptor,
ModifiablePlanElement planElement, LifecycleBindings mergedBindings, MavenProject project, final BuildPlan plan, final MavenProject project )
LinkedList forkingBindings )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
String referencingGoal = mojoBinding.getGoal(); String referencingGoal = mojoBinding.getGoal();
@ -376,48 +271,44 @@ public class DefaultBuildPlanner
return; return;
} }
if ( LifecycleUtils.findLifecycleBindingForPhase( phase, mergedBindings ) == null ) if ( !LifecycleUtils.isValidPhaseName( phase ) )
{ {
throw new LifecyclePlannerException( "Cannot find lifecycle for phase: " + phase ); throw new LifecyclePlannerException( "Cannot find lifecycle for phase: " + phase );
} }
LifecycleBindings cloned; BuildPlan clonedPlan = plan.copy( Collections.singletonList( phase ) );
if ( mojoDescriptor.getExecuteLifecycle() != null )
{
String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
if ( executeLifecycle != null )
{
LifecycleBindings overlayBindings; LifecycleBindings overlayBindings;
try try
{ {
overlayBindings = lifecycleBindingManager.getPluginLifecycleOverlay( pluginDescriptor, executeLifecycle, project ); overlayBindings =
lifecycleBindingManager.getPluginLifecycleOverlay( pluginDescriptor, executeLifecycle, project );
} }
catch ( LifecycleLoaderException e ) catch ( LifecycleLoaderException e )
{ {
throw new LifecyclePlannerException( "Failed to load overlay lifecycle: " + executeLifecycle + ". Reason: " throw new LifecyclePlannerException( "Failed to load overlay lifecycle: " + executeLifecycle
+ e.getMessage(), e ); + ". Reason: " + e.getMessage(), e );
} }
cloned = LifecycleUtils.cloneBindings( mergedBindings ); clonedPlan.addLifecycleOverlay( overlayBindings );
cloned = LifecycleUtils.mergeBindings( overlayBindings, cloned, null, true, true );
}
else
{
cloned = LifecycleUtils.cloneBindings( mergedBindings );
} }
LifecycleUtils.removeMojoBindings( forkingBindings, cloned, false ); plan.addForkedExecution( mojoBinding, clonedPlan );
modifyBuildPlanForForkedLifecycle( mojoBinding, pluginDescriptor, planElement, cloned, project, forkingBindings ); addForkedLifecycleModifiers( clonedPlan, project );
} }
/** /**
* Retrieves the information necessary to create a new MojoBinding for a single-mojo forked * Retrieves the information necessary to create a new MojoBinding for a single-mojo forked execution, then hands
* execution, then hands off to the {@link DefaultBuildPlanner#modifyBuildPlanForForkedDirectInvocation(MojoBinding, MojoBinding, PluginDescriptor, ModifiablePlanElement, LifecycleBindings, MavenProject, LinkedList, List)} * off to the
* {@link DefaultBuildPlanner#modifyBuildPlanForForkedDirectInvocation(MojoBinding, MojoBinding, PluginDescriptor, ModifiablePlanElement, LifecycleBindings, MavenProject, LinkedList, List)}
* method to actually inject the modification. * method to actually inject the modification.
*/ */
private void recurseSingleMojoFork( MojoBinding mojoBinding, PluginDescriptor pluginDescriptor, private void recurseSingleMojoFork( final MojoBinding mojoBinding, final PluginDescriptor pluginDescriptor,
ModifiablePlanElement planElement, LifecycleBindings mergedBindings, final BuildPlan plan, final MavenProject project )
MavenProject project, LinkedList forkingBindings )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
String referencingGoal = mojoBinding.getGoal(); String referencingGoal = mojoBinding.getGoal();
@ -435,20 +326,16 @@ public class DefaultBuildPlanner
if ( otherDescriptor == null ) if ( otherDescriptor == null )
{ {
throw new LifecyclePlannerException( "Mojo: " + executeGoal + " (referenced by: " + referencingGoal throw new LifecyclePlannerException( "Mojo: " + executeGoal + " (referenced by: " + referencingGoal
+ ") does not exist in plugin: " + pluginDescriptor.getId() + "." ); + ") does not exist in plugin: " + pluginDescriptor.getId() + "." );
} }
MojoBinding binding = mojoBindingFactory.createMojoBinding( pluginDescriptor.getGroupId(), MojoBinding binding =
pluginDescriptor.getArtifactId(), mojoBindingFactory.createMojoBinding( pluginDescriptor.getGroupId(), pluginDescriptor.getArtifactId(),
pluginDescriptor.getVersion(), executeGoal, project ); pluginDescriptor.getVersion(), executeGoal, project );
binding.setOrigin( "Forked from " + referencingGoal ); binding.setOrigin( "Forked from " + referencingGoal );
if ( !LifecycleUtils.isMojoBindingPresent( binding, forkingBindings, false ) ) plan.addForkedExecution( mojoBinding, Collections.singletonList( binding ) );
{
modifyBuildPlanForForkedDirectInvocation( binding, mojoBinding, pluginDescriptor, planElement, mergedBindings,
project, forkingBindings );
}
} }
} }

View File

@ -1,32 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.project.MavenProject;
import java.util.List;
/**
* Modifier that alters a build plan to substitute a set of MojoBindings in place of a single,
* direct-invocation MojoBinding. These bindings are not impacted by {@link BuildPlanModifier}s,
* since they don't exist in a {@link LifecycleBindings} instance.
*
* @author jdcasey
*
*/
public interface DirectInvocationModifier
{
/**
* The MojoBinding which should be modified.
*/
MojoBinding getBindingToModify();
/**
* Return the list of MojoBindings which should replace the modified binding in the master
* build plan.
*/
List getModifiedBindings( MavenProject project, LifecycleBindingManager bindingManager );
}

View File

@ -1,17 +0,0 @@
package org.apache.maven.lifecycle.plan;
/**
* Instantiates MojoBindings for direct invocation, which may be subject to modification.
*
* @author jdcasey
*
*/
public interface DirectInvocationOriginElement
{
/**
* Add a new direct-invocation binding modifier.
*/
void addDirectInvocationModifier( DirectInvocationModifier modifier );
}

View File

@ -1,113 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Inject a list of forked-execution bindings at the point where the modification point is bound to
* the supplied LifecycleBindings, bracketed by special mojo bindings to control the forked-execution
* context.
*
* @author jdcasey
*
*/
public class ForkPlanModifier
implements BuildPlanModifier
{
private final MojoBinding modificationPoint;
private List planModifiers = new ArrayList();
private final List mojoBindings;
public ForkPlanModifier( MojoBinding modificationPoint, List mojoBindings )
{
this.modificationPoint = modificationPoint;
this.mojoBindings = mojoBindings;
}
/**
* Retrieve the MojoBinding which serves as the injection point for the forked bindings.
*/
public MojoBinding getModificationPoint()
{
return modificationPoint;
}
/**
* Modify the LifeycleBindings from a BuildPlan by locating the modification point MojoBinding,
* and prepending the forked-execution bindings in the plan, bracketed by mojos that control the
* forked-execution context.
*/
public LifecycleBindings modifyBindings( LifecycleBindings bindings )
throws LifecyclePlannerException
{
Phase phase = LifecycleUtils.findPhaseForMojoBinding( getModificationPoint(), bindings, true );
String modificationKey = LifecycleUtils.createMojoBindingKey( getModificationPoint(), true );
if ( phase == null )
{
throw new LifecyclePlannerException( "Failed to modify plan. No phase found containing mojoBinding: "
+ modificationKey );
}
int stopIndex = -1;
int insertionIndex = -1;
List phaseBindings = phase.getBindings();
for ( int i = 0; i < phaseBindings.size(); i++ )
{
MojoBinding candidate = (MojoBinding) phaseBindings.get( i );
String key = LifecycleUtils.createMojoBindingKey( candidate, true );
if ( key.equals( modificationKey ) )
{
insertionIndex = i;
stopIndex = i + 1;
break;
}
}
phaseBindings.add( stopIndex, StateManagementUtils.createClearForkedExecutionMojoBinding() );
phaseBindings.add( insertionIndex, StateManagementUtils.createEndForkedExecutionMojoBinding() );
phaseBindings.addAll( insertionIndex, mojoBindings );
phaseBindings.add( insertionIndex, StateManagementUtils.createStartForkedExecutionMojoBinding() );
phase.setBindings( phaseBindings );
for ( Iterator it = planModifiers.iterator(); it.hasNext(); )
{
BuildPlanModifier modifier = (BuildPlanModifier) it.next();
modifier.modifyBindings( bindings );
}
return bindings;
}
/**
* Add a new modifier to further adjust the LifecycleBindings which are modified here.
*/
public void addModifier( BuildPlanModifier planModifier )
{
planModifiers.add( planModifier );
}
/**
* Return true if this modifier itself has modifiers.
*/
public boolean hasModifiers()
{
return !planModifiers.isEmpty();
}
}

View File

@ -1,56 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.List;
/**
* Inject a list of MojoBindings in place of the forking binding, bracketing the forked bindings with
* special mojos to control the forked-execution context.
*
* @author jdcasey
*
*/
public class ForkedDirectInvocationModifier
implements DirectInvocationModifier
{
private final List forkedBindings;
private final MojoBinding forkingBinding;
public ForkedDirectInvocationModifier( MojoBinding forkingBinding, List forkedBindings )
{
this.forkingBinding = forkingBinding;
this.forkedBindings = forkedBindings;
}
/**
* Return a list containing forked-execution context control MojoBindings, the forked-execution
* bindings themselves, and finally the binding that forked off a new execution branch.
*/
public List getModifiedBindings( MavenProject project, LifecycleBindingManager bindingManager )
{
List result = new ArrayList();
result.add( StateManagementUtils.createStartForkedExecutionMojoBinding() );
result.addAll( forkedBindings );
result.add( StateManagementUtils.createEndForkedExecutionMojoBinding() );
result.add( forkingBinding );
result.add( StateManagementUtils.createClearForkedExecutionMojoBinding() );
return result;
}
/**
* Return the MojoBinding that forks execution to include the bindings in this modifier.
*/
public MojoBinding getBindingToModify()
{
return forkingBinding;
}
}

View File

@ -1,91 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Construct a list of MojoBinding instances that accomplish all of the tasks specified. For lifecycle
* phases, construct a list of mojos to execute up to and including the specified phase, and add them
* to the list. For direct invocations, construct a new MojoBinding instance and add it to the list.
*
* All of these bindings are subject to lifecycle modifications due to forking, reporting, or other
* factors, and also to forked-execution modification of direct invocations.
*
* @author jdcasey
*
*/
public class LifecycleBuildPlan
implements BuildPlan, DirectInvocationOriginElement
{
private final List tasks;
private final LifecycleBindings lifecycleBindings;
private List planModifiers = new ArrayList();
private Map directInvocationModifiers = new HashMap();
public LifecycleBuildPlan( List tasks, LifecycleBindings lifecycleBindings )
{
this.tasks = tasks;
this.lifecycleBindings = lifecycleBindings;
}
/**
* Build the master execution list necessary to accomplish the specified tasks, given the
* specified set of mojo bindings to different parts of the lifecycle.
*/
public List getPlanMojoBindings( MavenProject project, LifecycleBindingManager bindingManager )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings cloned = BuildPlanUtils.modifyPlanBindings( lifecycleBindings, planModifiers );
return bindingManager.assembleMojoBindingList( tasks, cloned, directInvocationModifiers, project );
}
/**
* Retrieve the set of tasks that this build plan is responsible for.
*/
public List getTasks()
{
return tasks;
}
/**
* Add a new build-plan modifier to inject reporting, forked-execution, or other altered behavior
* into the "vanilla" lifecycle that was specified at instance construction.
*/
public void addModifier( BuildPlanModifier planModifier )
{
planModifiers.add( planModifier );
}
/**
* Return true if build-plan modifiers exist (these are lifecycle-only modifiers, not direct
* invocation modifiers).
*/
public boolean hasModifiers()
{
return !planModifiers.isEmpty();
}
/**
* Add a new modifier for a direct-invocation MojoBinding in the build plan resulting from this
* instance.
*/
public void addDirectInvocationModifier( DirectInvocationModifier modifier )
{
directInvocationModifiers.put( LifecycleUtils.createMojoBindingKey( modifier.getBindingToModify(), true ), modifier );
}
}

View File

@ -1,23 +0,0 @@
package org.apache.maven.lifecycle.plan;
/**
* Any element of a build plan that contains or handles a LifecycleBindings instance which is subject
* to modification.
*
* @author jdcasey
*
*/
public interface ModifiablePlanElement
{
/**
* Add a new lifecycle modifier to this build-plan element.
*/
void addModifier( BuildPlanModifier planModifier );
/**
* Return true if this element has lifecycle modifiers
*/
boolean hasModifiers();
}

View File

@ -1,94 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Inject the MojoBindings necessary to execute and make available the report instances that another
* mojo in the build plan needs.
*
* @author jdcasey
*
*/
public class ReportingPlanModifier
implements BuildPlanModifier
{
private List planModifiers = new ArrayList();
private final MojoBinding targetMojoBinding;
private final List reportBindings;
public ReportingPlanModifier( MojoBinding mojoBinding, List reportBindings )
{
this.targetMojoBinding = mojoBinding;
this.reportBindings = reportBindings;
}
/**
* Find the mojo that requested reports, and inject the reporting MojoBinding instances just
* ahead of it in the lifecycle bindings.
*/
public LifecycleBindings modifyBindings( LifecycleBindings bindings )
throws LifecyclePlannerException
{
Phase phase = LifecycleUtils.findPhaseForMojoBinding( targetMojoBinding, bindings, true );
String modificationKey = LifecycleUtils.createMojoBindingKey( targetMojoBinding, true );
if ( phase == null )
{
throw new LifecyclePlannerException( "Failed to modify plan. No phase found containing mojoBinding: "
+ modificationKey );
}
int insertionIndex = -1;
List phaseBindings = phase.getBindings();
for ( int i = 0; i < phaseBindings.size(); i++ )
{
MojoBinding candidate = (MojoBinding) phaseBindings.get( i );
String key = LifecycleUtils.createMojoBindingKey( candidate, true );
if ( key.equals( modificationKey ) )
{
insertionIndex = i;
break;
}
}
phaseBindings.addAll( insertionIndex, reportBindings );
phase.setBindings( phaseBindings );
for ( Iterator it = planModifiers.iterator(); it.hasNext(); )
{
BuildPlanModifier modifier = (BuildPlanModifier) it.next();
modifier.modifyBindings( bindings );
}
return bindings;
}
/**
* Add further lifecycle modifications to this report-injecting modifier.
*/
public void addModifier( BuildPlanModifier planModifier )
{
planModifiers.add( planModifier );
}
/**
* Return true if this report-injecting modifier contains further modifications for the lifecycle.
*/
public boolean hasModifiers()
{
return !planModifiers.isEmpty();
}
}

View File

@ -1,52 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.List;
/**
* Inject a list of MojoBindings in place of the forking binding, bracketing the forked bindings with
* special mojos to control the forked-execution context.
*
* @author jdcasey
*
*/
public class SimpleDirectInvocationModifier
implements DirectInvocationModifier
{
private final List reportBindings;
private final MojoBinding targetBinding;
public SimpleDirectInvocationModifier( MojoBinding targetBinding, List reportBindings )
{
this.targetBinding = targetBinding;
this.reportBindings = reportBindings;
}
/**
* Return a list containing forked-execution context control MojoBindings, the forked-execution
* bindings themselves, and finally the binding that forked off a new execution branch.
*/
public List getModifiedBindings( MavenProject project, LifecycleBindingManager bindingManager )
{
List result = new ArrayList();
result.addAll( reportBindings );
result.add( targetBinding );
return result;
}
/**
* Return the MojoBinding that forks execution to include the bindings in this modifier.
*/
public MojoBinding getBindingToModify()
{
return targetBinding;
}
}

View File

@ -1,70 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.project.MavenProject;
import java.util.Collections;
import java.util.List;
/**
* Constructs a build plan using a LifecycleBindings instance, but only allowing one phase for that
* lifecycle, as opposed to the parent class which allows a list of tasks (some of which may not be
* lifecycle phases at all).
*
* This build plan cannot produce direct-invocation MojoBindings.
*
* @author jdcasey
*
*/
public class SubLifecycleBuildPlan
implements BuildPlan
{
private LifecycleBuildPlan delegate;
private final String phase;
public SubLifecycleBuildPlan( String phase, LifecycleBindings bindings )
{
this.phase = phase;
delegate = new LifecycleBuildPlan( Collections.singletonList( phase ), bindings );
}
/**
* Retrieve the build plan binding list from the delegate {@link LifecycleBuildPlan} instance,
* and return them.
*/
public List getPlanMojoBindings(MavenProject project, LifecycleBindingManager bindingManager)
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
return delegate.getPlanMojoBindings(project, bindingManager);
}
/**
* Return a list containing a single item: the lifecycle phase that this plan is concerned with
* accomplishing.
*/
public List getTasks()
{
return Collections.singletonList( phase );
}
/**
* Add a build-plan modifier to the delegate {@link LifecycleBuildPlan} instance.
*/
public void addModifier( BuildPlanModifier planModifier )
{
delegate.addModifier( planModifier );
}
/**
* Return true if the delegate {@link LifecycleBuildPlan} instance contains build-plan modifiers.
*/
public boolean hasModifiers()
{
return delegate.hasModifiers();
}
}

View File

@ -0,0 +1,57 @@
package org.apache.maven.lifecycle.statemgmt;
import org.apache.maven.lifecycle.MojoBindingUtils;
import org.apache.maven.lifecycle.binding.MojoBindingFactory;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.loader.PluginLoader;
import org.apache.maven.plugin.loader.PluginLoaderException;
import org.apache.maven.project.MavenProject;
public class ResolveLateBoundPluginMojo extends AbstractMojo
{
/**
* @component
*/
private PluginLoader pluginLoader;
private String groupId;
private String artifactId;
private String version;
private String goal;
private MavenProject project;
private MojoBindingFactory bindingFactory;
public void execute() throws MojoExecutionException, MojoFailureException
{
MojoBinding binding = bindingFactory.createMojoBinding( groupId, artifactId, version, artifactId, project );
try
{
PluginDescriptor descriptor = pluginLoader.loadPlugin( binding, project );
MojoDescriptor mojoDescriptor = descriptor.getMojo( goal );
if ( mojoDescriptor == null )
{
throw new MojoExecutionException( "Resolved plugin: " + descriptor.getId()
+ " does not contain a mojo called \'" + goal + "\'." );
}
}
catch ( PluginLoaderException e )
{
throw new MojoExecutionException( "Failed to load late-bound plugin: "
+ MojoBindingUtils.createPluginKey( binding ) );
}
}
}

View File

@ -4,11 +4,10 @@ import org.apache.maven.lifecycle.model.MojoBinding;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
/** /**
* Constructs and matches MojoBinding instances that refer to the forked-execution context manager * Constructs and matches MojoBinding instances that refer to the forked-execution context manager mojos.
* mojos.
* *
* @author jdcasey * @author jdcasey
* *
*/ */
public final class StateManagementUtils public final class StateManagementUtils
{ {
@ -27,6 +26,8 @@ public final class StateManagementUtils
public static final String CLEAR_FORKED_EXECUTION_GOAL = "clear-fork-context"; public static final String CLEAR_FORKED_EXECUTION_GOAL = "clear-fork-context";
public static final String RESOLVE_LATE_BOUND_PLUGIN_GOAL = "resolve-late-bound-plugin";
private static int CURRENT_FORK_ID = 0; private static int CURRENT_FORK_ID = 0;
private StateManagementUtils() private StateManagementUtils()
@ -34,9 +35,8 @@ public final class StateManagementUtils
} }
/** /**
* Create a new MojoBinding instance that refers to the internal mojo used to setup a new * Create a new MojoBinding instance that refers to the internal mojo used to setup a new forked-execution context.
* forked-execution context. Also, set the configuration to contain the forkId for this new * Also, set the configuration to contain the forkId for this new context.
* context.
*/ */
public static MojoBinding createStartForkedExecutionMojoBinding() public static MojoBinding createStartForkedExecutionMojoBinding()
{ {
@ -49,22 +49,21 @@ public final class StateManagementUtils
binding.setOrigin( ORIGIN ); binding.setOrigin( ORIGIN );
CURRENT_FORK_ID = (int) System.currentTimeMillis(); CURRENT_FORK_ID = (int) System.currentTimeMillis();
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" ); Xpp3Dom forkId = new Xpp3Dom( "forkId" );
forkId.setValue( "" + CURRENT_FORK_ID ); forkId.setValue( "" + CURRENT_FORK_ID );
config.addChild( forkId ); config.addChild( forkId );
binding.setConfiguration( config ); binding.setConfiguration( config );
return binding; return binding;
} }
/** /**
* Create a new MojoBinding instance that refers to the internal mojo used to end a * Create a new MojoBinding instance that refers to the internal mojo used to end a forked-execution context. Also,
* forked-execution context. Also, set the configuration to contain the forkId for this new * set the configuration to contain the forkId for this new context.
* context.
*/ */
public static MojoBinding createEndForkedExecutionMojoBinding() public static MojoBinding createEndForkedExecutionMojoBinding()
{ {
@ -79,18 +78,17 @@ public final class StateManagementUtils
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" ); Xpp3Dom forkId = new Xpp3Dom( "forkId" );
forkId.setValue( "" + CURRENT_FORK_ID ); forkId.setValue( "" + CURRENT_FORK_ID );
config.addChild( forkId ); config.addChild( forkId );
binding.setConfiguration( config ); binding.setConfiguration( config );
return binding; return binding;
} }
/** /**
* Create a new MojoBinding instance that refers to the internal mojo used to cleanup a completed * Create a new MojoBinding instance that refers to the internal mojo used to cleanup a completed forked-execution
* forked-execution context. Also, set the configuration to contain the forkId for this new * context. Also, set the configuration to contain the forkId for this new context.
* context.
*/ */
public static MojoBinding createClearForkedExecutionMojoBinding() public static MojoBinding createClearForkedExecutionMojoBinding()
{ {
@ -105,45 +103,99 @@ public final class StateManagementUtils
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" ); Xpp3Dom forkId = new Xpp3Dom( "forkId" );
forkId.setValue( "" + CURRENT_FORK_ID ); forkId.setValue( "" + CURRENT_FORK_ID );
config.addChild( forkId ); config.addChild( forkId );
binding.setConfiguration( config ); binding.setConfiguration( config );
return binding; return binding;
} }
/** /**
* Return true if the specified MojoBinding refers to the internal mojo used to setup a new * Return true if the specified MojoBinding refers to the internal mojo used to setup a new forked-execution
* forked-execution context. This is useful for formatting when listing the build plan, when * context. This is useful for formatting when listing the build plan, when expression of these actual mojo names
* expression of these actual mojo names isn't necessarily useful, and can be confusing. * isn't necessarily useful, and can be confusing.
*/ */
public static boolean isForkedExecutionStartMarker( MojoBinding binding ) public static boolean isForkedExecutionStartMarker( final MojoBinding binding )
{ {
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() ) return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& START_FORKED_EXECUTION_GOAL.equals( binding.getGoal() ); && START_FORKED_EXECUTION_GOAL.equals( binding.getGoal() );
} }
/** /**
* Return true if the specified MojoBinding refers to the internal mojo used to end a * Return true if the specified MojoBinding refers to the internal mojo used to end a forked-execution context. This
* forked-execution context. This is useful for formatting when listing the build plan, when * is useful for formatting when listing the build plan, when expression of these actual mojo names isn't
* expression of these actual mojo names isn't necessarily useful, and can be confusing. * necessarily useful, and can be confusing.
*/ */
public static boolean isForkedExecutionEndMarker( MojoBinding binding ) public static boolean isForkedExecutionEndMarker( final MojoBinding binding )
{ {
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() ) return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& END_FORKED_EXECUTION_GOAL.equals( binding.getGoal() ); && END_FORKED_EXECUTION_GOAL.equals( binding.getGoal() );
} }
/** /**
* Return true if the specified MojoBinding refers to the internal mojo used to clean up a completed * Return true if the specified MojoBinding refers to the internal mojo used to clean up a completed
* forked-execution context. This is useful for formatting when listing the build plan, when * forked-execution context. This is useful for formatting when listing the build plan, when expression of these
* expression of these actual mojo names isn't necessarily useful, and can be confusing. * actual mojo names isn't necessarily useful, and can be confusing.
*/ */
public static boolean isForkedExecutionClearMarker( MojoBinding binding ) public static boolean isForkedExecutionClearMarker( final MojoBinding binding )
{ {
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() ) return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& CLEAR_FORKED_EXECUTION_GOAL.equals( binding.getGoal() ); && CLEAR_FORKED_EXECUTION_GOAL.equals( binding.getGoal() );
}
/**
* Create a new MojoBinding instance that refers to the internal mojo used to resolve a late-bound plugin just
* before it is to be used. Also, set the configuration to contain the parameters necessary for this resolution.
*/
public static MojoBinding createResolveLateBoundMojoBinding( final MojoBinding lateBound )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( GROUP_ID );
binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION );
binding.setGoal( RESOLVE_LATE_BOUND_PLUGIN_GOAL );
binding.setOrigin( ORIGIN );
Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom param = new Xpp3Dom( "groupId" );
param.setValue( lateBound.getGroupId() );
config.addChild( param );
param = new Xpp3Dom( "artifactId" );
param.setValue( lateBound.getArtifactId() );
config.addChild( param );
if ( lateBound.getVersion() != null )
{
param = new Xpp3Dom( "version" );
param.setValue( lateBound.getVersion() );
config.addChild( param );
}
param = new Xpp3Dom( "goal" );
param.setValue( lateBound.getGoal() );
config.addChild( param );
binding.setConfiguration( config );
return binding;
}
/**
* Return true if the specified MojoBinding refers to the internal mojo used to resolve a late-bound mojo. This is
* useful for formatting when listing the build plan, when expression of these actual mojo names isn't necessarily
* useful, and can be confusing.
*/
public static boolean isResolveLateBoundMojoBinding( final MojoBinding binding )
{
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& RESOLVE_LATE_BOUND_PLUGIN_GOAL.equals( binding.getGoal() );
} }
} }

View File

@ -113,5 +113,73 @@
<forkId implementation="int" default-value="-1">${forkId}</forkId> <forkId implementation="int" default-value="-1">${forkId}</forkId>
</configuration> </configuration>
</mojo> </mojo>
<mojo>
<goal>resolve-plugin</goal>
<description>Resolve a late-bound plugin during a build, right before it is to be used.</description>
<requiresDirectInvocation>false</requiresDirectInvocation>
<requiresProject>true</requiresProject>
<requiresReports>false</requiresReports>
<aggregator>false</aggregator>
<requiresOnline>false</requiresOnline>
<inheritedByDefault>true</inheritedByDefault>
<implementation>org.apache.maven.lifecycle.statemgmt.ResolveLateBoundPluginMojo</implementation>
<language>java</language>
<instantiationStrategy>per-lookup</instantiationStrategy>
<executionStrategy>once-per-session</executionStrategy>
<parameters>
<parameter>
<name>project</name>
<type>org.apache.maven.project.MavenProject</type>
<required>true</required>
<editable>false</editable>
<description>The current MavenProject instance, for building a new MojoBinding instance.</description>
</parameter>
<parameter>
<name>groupId</name>
<type>java.lang.String</type>
<required>true</required>
<editable>true</editable>
<description>The plugin's groupId.</description>
</parameter>
<parameter>
<name>artifactId</name>
<type>java.lang.String</type>
<required>true</required>
<editable>true</editable>
<description>The plugin's artifactId.</description>
</parameter>
<parameter>
<name>version</name>
<type>java.lang.String</type>
<required>false</required>
<editable>true</editable>
<description>The plugin's version.</description>
</parameter>
<parameter>
<name>gaol</name>
<type>java.lang.String</type>
<required>true</required>
<editable>true</editable>
<description>The mojo's goal that we're looking for, as an extra validation step.</description>
</parameter>
</parameters>
<configuration>
<project implementation="org.apache.maven.project.MavenProject" default-value="${project}"/>
<groupId implementation="java.lang.String">${groupId}</groupId>
<artifactId implementation="java.lang.String">${artifactId}</artifactId>
<version implementation="java.lang.String">${version}</version>
<goal implementation="java.lang.String">${goal}</goal>
</configuration>
<requirements>
<requirement>
<role>org.apache.maven.plugin.loader.PluginLoader</role>
<field-name>pluginLoader</field-name>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.MojoBindingFactory</role>
<field-name>bindingFactory</field-name>
</requirement>
</requirements>
</mojo>
</mojos> </mojos>
</plugin> </plugin>

View File

@ -266,9 +266,6 @@ under the License.
<requirement> <requirement>
<role>org.apache.maven.context.BuildContextManager</role> <role>org.apache.maven.context.BuildContextManager</role>
</requirement> </requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.LifecycleBindingManager</role>
</requirement>
<requirement> <requirement>
<role>org.apache.maven.plugin.loader.PluginLoader</role> <role>org.apache.maven.plugin.loader.PluginLoader</role>
</requirement> </requirement>

View File

@ -4,7 +4,6 @@ import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException; import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.model.LifecycleBindings; import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.plan.LifecyclePlannerException;
import org.apache.maven.model.Build; import org.apache.maven.model.Build;
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
@ -14,24 +13,21 @@ import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusTestCase; import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
public class DefaultLifecycleBindingManagerTest public class DefaultLifecycleBindingManagerTest extends PlexusTestCase
extends PlexusTestCase
{ {
private LifecycleBindingManager mgr; private LifecycleBindingManager mgr;
public void setUp() public void setUp() throws Exception
throws Exception
{ {
super.setUp(); super.setUp();
this.mgr = (LifecycleBindingManager) lookup( LifecycleBindingManager.ROLE, "default" ); mgr = (LifecycleBindingManager) lookup( LifecycleBindingManager.ROLE, "default" );
} }
public void testLookup() public void testLookup()
@ -92,7 +88,7 @@ public class DefaultLifecycleBindingManagerTest
Build build = new Build(); Build build = new Build();
model.setBuild( build ); model.setBuild( build );
PluginManagement plugMgmt = new PluginManagement(); PluginManagement plugMgmt = new PluginManagement();
build.setPluginManagement( plugMgmt ); build.setPluginManagement( plugMgmt );
@ -182,7 +178,7 @@ public class DefaultLifecycleBindingManagerTest
assertEquals( "other-value", config.getChild( "test2" ).getValue() ); assertEquals( "other-value", config.getChild( "test2" ).getValue() );
} }
private Object createConfiguration( Properties configProperties ) private Object createConfiguration( final Properties configProperties )
{ {
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
for ( Iterator it = configProperties.keySet().iterator(); it.hasNext(); ) for ( Iterator it = configProperties.keySet().iterator(); it.hasNext(); )
@ -199,164 +195,4 @@ public class DefaultLifecycleBindingManagerTest
return config; return config;
} }
public void testAssembleMojoBindingList_ReturnBindingsUpToStopPhaseForSinglePhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
bindings.getCleanBinding().getPostClean().addBinding( newMojoBinding( "goal", "artifact", "post-clean" ) );
List result = mgr.assembleMojoBindingList( Collections.singletonList( "clean" ), bindings, new MavenProject( new Model() ) );
assertEquals( 2, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
}
public void testAssembleMojoBindingList_CombinePreviousBindingsWhenSubsetOfNextBindingsForTwoPhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "post-clean" ) );
List tasks = new ArrayList( 2 );
tasks.add( "clean" );
tasks.add( "post-clean" );
List result = mgr.assembleMojoBindingList( tasks, bindings, new MavenProject( new Model() ) );
assertEquals( 3, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
binding = (MojoBinding) result.get( 2 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "post-clean", binding.getGoal() );
}
public void testAssembleMojoBindingList_IgnoreSuccessiveBindingsWhenSameAsPreviousOnesForTwoPhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
List tasks = new ArrayList( 2 );
tasks.add( "clean" );
tasks.add( "post-clean" );
List result = mgr.assembleMojoBindingList( tasks, bindings, new MavenProject( new Model() ) );
assertEquals( 2, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
}
public void testAssembleMojoBindingList_ReturnBindingsUpToStopPhasesForTwoPhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
bindings.getCleanBinding().getPostClean().addBinding( newMojoBinding( "goal", "artifact", "post-clean" ) );
bindings.getBuildBinding().getInitialize().addBinding( newMojoBinding( "goal", "artifact", "initialize" ) );
bindings.getBuildBinding().getCompile().addBinding( newMojoBinding( "goal", "artifact", "compile" ) );
bindings.getBuildBinding().getCreatePackage().addBinding( newMojoBinding( "goal", "artifact", "package" ) );
List tasks = new ArrayList( 2 );
tasks.add( "clean" );
tasks.add( "compile" );
List result = mgr.assembleMojoBindingList( tasks, bindings, new MavenProject( new Model() ) );
assertEquals( 4, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
binding = (MojoBinding) result.get( 2 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "initialize", binding.getGoal() );
binding = (MojoBinding) result.get( 3 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "compile", binding.getGoal() );
}
public void testAssembleMojoBindingList_ThrowErrorForInvalidPhaseNameAsSingletonTaskList()
throws LifecyclePlannerException, LifecycleLoaderException
{
try
{
mgr.assembleMojoBindingList( Collections.singletonList( "dud" ), new LifecycleBindings(),
new MavenProject( new Model() ) );
fail( "Should fail with LifecycleSpecificationException due to invalid phase/direct mojo reference." );
}
catch ( LifecycleSpecificationException e )
{
// expected.
}
}
private MojoBinding newMojoBinding( String groupId, String artifactId, String goal )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( groupId );
binding.setArtifactId( artifactId );
binding.setGoal( goal );
return binding;
}
} }

View File

@ -0,0 +1,98 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.MojoBindingUtils;
import org.apache.maven.lifecycle.model.BuildBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import junit.framework.TestCase;
public class BuildPlanTest
extends TestCase
{
public void testRender_OneDirectInvocationWithForkedPhase_NoLifecycleOverlay()
throws LifecycleSpecificationException, LifecycleLoaderException
{
List check = new ArrayList();
check.add( StateManagementUtils.createStartForkedExecutionMojoBinding() );
MojoBinding mb = new MojoBinding();
mb.setGroupId( "test" );
mb.setArtifactId( "test-plugin" );
mb.setVersion( "1" );
mb.setGoal( "validate" );
check.add( mb );
BuildBinding binding = new BuildBinding();
binding.getValidate().addBinding( mb );
mb = new MojoBinding();
mb.setGroupId( "test" );
mb.setArtifactId( "test-plugin" );
mb.setVersion( "1" );
mb.setGoal( "generate-sources" );
check.add( mb );
check.add( StateManagementUtils.createClearForkedExecutionMojoBinding() );
binding.getGenerateSources().addBinding( mb );
LifecycleBindings bindings = new LifecycleBindings();
bindings.setBuildBinding( binding );
List tasks = Collections.singletonList( "eclipse:eclipse" );
MojoBinding eclipseBinding = new MojoBinding();
eclipseBinding.setGroupId( "org.apache.maven.plugins" );
eclipseBinding.setArtifactId( "maven-eclipse-plugin" );
eclipseBinding.setVersion( "2.3" );
eclipseBinding.setGoal( "eclipse" );
check.add( eclipseBinding );
check.add( StateManagementUtils.createEndForkedExecutionMojoBinding() );
BuildPlan plan = new BuildPlan( new LifecycleBindings(), tasks );
plan.addDirectInvocationBinding( "eclipse:eclipse", eclipseBinding );
plan.addForkedExecution( eclipseBinding, new BuildPlan( bindings,
Collections.singletonList( "generate-sources" ) ) );
List executionPlan = plan.renderExecutionPlan( new Stack() );
assertBindings( check, executionPlan );
}
private void assertBindings( final List check, final List executionPlan )
{
assertNotNull( executionPlan );
System.out.println( "Expected execution plan:\n" + String.valueOf( check ).replace( ',', '\n' ) );
System.out.println( "\nActual execution plan:\n" + String.valueOf( executionPlan ).replace( ',', '\n' ) );
assertEquals( "Execution plan does not contain the expected number of mojo bindings.", check.size(),
executionPlan.size() );
for ( int i = 0; i < check.size(); i++ )
{
MojoBinding checkBinding = (MojoBinding) check.get( i );
MojoBinding realBinding = (MojoBinding) executionPlan.get( i );
assertEquals( "Expected mojo binding does not match execution plan.",
MojoBindingUtils.createMojoBindingKey( checkBinding, true ),
MojoBindingUtils.createMojoBindingKey( realBinding, true ) );
}
}
}

View File

@ -1,197 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
public class ForkPlanModifierTest
extends TestCase
{
public void testModifyBindings_AddTwoMojosAheadOfCompileMojo()
throws LifecyclePlannerException
{
MojoBinding mojo = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile" );
List additions = new ArrayList();
additions.add( newMojo( "group", "artifact", "clean" ) );
additions.add( newMojo( "group", "artifact", "compile" ) );
LifecycleBindings target = new LifecycleBindings();
assertEquals( 0, target.getBuildBinding().getCompile().getBindings().size() );
target.getBuildBinding().getCompile().addBinding( mojo );
assertEquals( 1, target.getBuildBinding().getCompile().getBindings().size() );
target = new ForkPlanModifier( mojo, additions ).modifyBindings( target );
assertEquals( 6, target.getBuildBinding().getCompile().getBindings().size() );
Iterator it = target.getBuildBinding().getCompile().getBindings().iterator();
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.START_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( "group", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( "group", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.END_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( mojo.getGroupId(), mojo.getArtifactId(), mojo.getGoal(),
(MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.CLEAR_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
}
public void testModifyBindings_AddTwoMojosBetweenTwoExistingCompileMojos()
throws LifecyclePlannerException
{
MojoBinding mojo = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile" );
MojoBinding mojo2 = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile2" );
List additions = new ArrayList();
additions.add( newMojo( "group", "artifact", "clean" ) );
additions.add( newMojo( "group", "artifact", "compile" ) );
LifecycleBindings target = new LifecycleBindings();
assertEquals( 0, target.getBuildBinding().getCompile().getBindings().size() );
target.getBuildBinding().getCompile().addBinding( mojo );
target.getBuildBinding().getCompile().addBinding( mojo2 );
assertEquals( 2, target.getBuildBinding().getCompile().getBindings().size() );
target = new ForkPlanModifier( mojo2, additions ).modifyBindings( target );
assertEquals( 7, target.getBuildBinding().getCompile().getBindings().size() );
Iterator it = target.getBuildBinding().getCompile().getBindings().iterator();
assertMojo( mojo.getGroupId(), mojo.getArtifactId(), mojo.getGoal(),
(MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.START_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( "group", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( "group", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.END_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( mojo2.getGroupId(), mojo2.getArtifactId(), mojo2.getGoal(),
(MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.CLEAR_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
}
public void testModifyBindings_AddTwoNormalPlusTwoModifierModifiedMojosWithTwoExistingCompileMojos()
throws LifecyclePlannerException
{
MojoBinding mojo = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile" );
MojoBinding mojo2 = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile2" );
List modAdditions = new ArrayList();
modAdditions.add( newMojo( "group2", "artifact", "clean" ) );
modAdditions.add( newMojo( "group2", "artifact", "compile" ) );
MojoBinding mojo3 = newMojo( "group", "artifact", "clean" );
List additions = new ArrayList();
additions.add( mojo3 );
additions.add( newMojo( "group", "artifact", "compile" ) );
LifecycleBindings target = new LifecycleBindings();
assertEquals( 0, target.getBuildBinding().getCompile().getBindings().size() );
target.getBuildBinding().getCompile().addBinding( mojo );
target.getBuildBinding().getCompile().addBinding( mojo2 );
assertEquals( 2, target.getBuildBinding().getCompile().getBindings().size() );
BuildPlanModifier modder = new ForkPlanModifier( mojo, additions );
modder.addModifier( new ForkPlanModifier( mojo3, modAdditions ) );
target = modder.modifyBindings( target );
assertEquals( 12, target.getBuildBinding().getCompile().getBindings().size() );
Iterator it = target.getBuildBinding().getCompile().getBindings().iterator();
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.START_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.START_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( "group2", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( "group2", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.END_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( mojo3.getGroupId(), mojo3.getArtifactId(), mojo3.getGoal(),
(MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.CLEAR_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
assertMojo( "group", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.END_FORKED_EXECUTION_GOAL,
(MojoBinding) it.next() );
assertMojo( mojo.getGroupId(), mojo.getArtifactId(), mojo.getGoal(),
(MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.CLEAR_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
assertMojo( mojo2.getGroupId(), mojo2.getArtifactId(), mojo2.getGoal(),
(MojoBinding) it.next() );
}
private void assertMojo( String groupId, String artifactId, String goal, MojoBinding binding )
{
assertEquals( groupId, binding.getGroupId() );
assertEquals( artifactId, binding.getArtifactId() );
assertEquals( goal, binding.getGoal() );
}
private MojoBinding newMojo( String groupId, String artifactId, String goal )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( groupId );
binding.setArtifactId( artifactId );
binding.setGoal( goal );
return binding;
}
}

View File

@ -1,122 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.binding.LifecycleBindingManager;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import org.codehaus.plexus.PlexusTestCase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class LifecycleBuildPlanTest
extends PlexusTestCase
{
private LifecycleBindingManager bindingManager;
public void setUp()
throws Exception
{
super.setUp();
bindingManager = (LifecycleBindingManager) lookup( LifecycleBindingManager.ROLE, "default" );
}
public void testSingleTask_TwoMojoBindings()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojo( "group", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojo( "group", "artifact", "clean" ) );
List plan = new LifecycleBuildPlan( Collections.singletonList( "clean" ), bindings ).getPlanMojoBindings( null,
bindingManager );
assertEquals( 2, plan.size() );
assertMojo( "group", "artifact", "pre-clean", (MojoBinding) plan.get( 0 ) );
assertMojo( "group", "artifact", "clean", (MojoBinding) plan.get( 1 ) );
}
public void testTwoAdditiveTasksInOrder_ThreeMojoBindings_NoDupes()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojo( "group", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojo( "group", "artifact", "clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojo( "group", "artifact", "post-clean" ) );
List tasks = new ArrayList();
tasks.add( "clean" );
tasks.add( "post-clean" );
List plan = new LifecycleBuildPlan( tasks, bindings ).getPlanMojoBindings( null, bindingManager );
assertEquals( 3, plan.size() );
assertMojo( "group", "artifact", "pre-clean", (MojoBinding) plan.get( 0 ) );
assertMojo( "group", "artifact", "clean", (MojoBinding) plan.get( 1 ) );
assertMojo( "group", "artifact", "post-clean", (MojoBinding) plan.get( 2 ) );
}
public void testTwoAdditiveTasksInOrder_TwoMojoBindings_OneMojoModifierInsertedBetween_NoDupes()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
MojoBinding clean = newMojo( "group", "artifact", "clean" );
List mods = Collections.singletonList( newMojo( "group", "artifact", "pre-clean" ) );
BuildPlanModifier modder = new ForkPlanModifier( clean, mods );
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( clean );
bindings.getCleanBinding().getClean().addBinding( newMojo( "group", "artifact", "post-clean" ) );
List tasks = new ArrayList();
tasks.add( "clean" );
tasks.add( "post-clean" );
BuildPlan lifecyclePlan = new LifecycleBuildPlan( tasks, bindings );
lifecyclePlan.addModifier( modder );
List plan = lifecyclePlan.getPlanMojoBindings( null, bindingManager );
assertEquals( 6, plan.size() );
Iterator it = plan.iterator();
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.START_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
assertMojo( "group", "artifact", "pre-clean", (MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.END_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
assertMojo( "group", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( StateManagementUtils.GROUP_ID, StateManagementUtils.ARTIFACT_ID,
StateManagementUtils.CLEAR_FORKED_EXECUTION_GOAL, (MojoBinding) it.next() );
assertMojo( "group", "artifact", "post-clean", (MojoBinding) it.next() );
}
private void assertMojo( String groupId, String artifactId, String goal, MojoBinding binding )
{
assertEquals( groupId, binding.getGroupId() );
assertEquals( artifactId, binding.getArtifactId() );
assertEquals( goal, binding.getGoal() );
}
private MojoBinding newMojo( String groupId, String artifactId, String goal )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( groupId );
binding.setArtifactId( artifactId );
binding.setGoal( goal );
return binding;
}
}

View File

@ -1,146 +0,0 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
public class ReportingPlanModifierTest
extends TestCase
{
public void testModifyBindings_AddTwoMojosAheadOfCompileMojo()
throws LifecyclePlannerException
{
MojoBinding mojo = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile" );
List additions = new ArrayList();
additions.add( newMojo( "group", "artifact", "clean" ) );
additions.add( newMojo( "group", "artifact", "compile" ) );
LifecycleBindings target = new LifecycleBindings();
assertEquals( 0, target.getBuildBinding().getCompile().getBindings().size() );
target.getBuildBinding().getCompile().addBinding( mojo );
assertEquals( 1, target.getBuildBinding().getCompile().getBindings().size() );
target = new ReportingPlanModifier( mojo, additions ).modifyBindings( target );
assertEquals( 3, target.getBuildBinding().getCompile().getBindings().size() );
Iterator it = target.getBuildBinding().getCompile().getBindings().iterator();
assertMojo( "group", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( "group", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( mojo.getGroupId(), mojo.getArtifactId(), mojo.getGoal(), (MojoBinding) it.next() );
}
public void testModifyBindings_AddTwoMojosBetweenTwoExistingCompileMojos()
throws LifecyclePlannerException
{
MojoBinding mojo = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile" );
MojoBinding mojo2 = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile2" );
List additions = new ArrayList();
additions.add( newMojo( "group", "artifact", "clean" ) );
additions.add( newMojo( "group", "artifact", "compile" ) );
LifecycleBindings target = new LifecycleBindings();
assertEquals( 0, target.getBuildBinding().getCompile().getBindings().size() );
target.getBuildBinding().getCompile().addBinding( mojo );
target.getBuildBinding().getCompile().addBinding( mojo2 );
assertEquals( 2, target.getBuildBinding().getCompile().getBindings().size() );
target = new ReportingPlanModifier( mojo2, additions ).modifyBindings( target );
assertEquals( 4, target.getBuildBinding().getCompile().getBindings().size() );
Iterator it = target.getBuildBinding().getCompile().getBindings().iterator();
assertMojo( mojo.getGroupId(), mojo.getArtifactId(), mojo.getGoal(), (MojoBinding) it.next() );
assertMojo( "group", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( "group", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( mojo2.getGroupId(), mojo2.getArtifactId(), mojo2.getGoal(), (MojoBinding) it.next() );
}
public void testModifyBindings_AddTwoNormalPlusTwoModifierModifiedMojosWithTwoExistingCompileMojos()
throws LifecyclePlannerException
{
MojoBinding mojo = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile" );
MojoBinding mojo2 = newMojo( "org.apache.maven.plugins", "maven-compiler-plugin", "compile2" );
List modAdditions = new ArrayList();
modAdditions.add( newMojo( "group2", "artifact", "clean" ) );
modAdditions.add( newMojo( "group2", "artifact", "compile" ) );
MojoBinding mojo3 = newMojo( "group", "artifact", "clean" );
List additions = new ArrayList();
additions.add( mojo3 );
additions.add( newMojo( "group", "artifact", "compile" ) );
LifecycleBindings target = new LifecycleBindings();
assertEquals( 0, target.getBuildBinding().getCompile().getBindings().size() );
target.getBuildBinding().getCompile().addBinding( mojo );
target.getBuildBinding().getCompile().addBinding( mojo2 );
assertEquals( 2, target.getBuildBinding().getCompile().getBindings().size() );
BuildPlanModifier modder = new ReportingPlanModifier( mojo, additions );
modder.addModifier( new ReportingPlanModifier( mojo3, modAdditions ) );
target = modder.modifyBindings( target );
assertEquals( 6, target.getBuildBinding().getCompile().getBindings().size() );
Iterator it = target.getBuildBinding().getCompile().getBindings().iterator();
assertMojo( "group2", "artifact", "clean", (MojoBinding) it.next() );
assertMojo( "group2", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( mojo3.getGroupId(), mojo3.getArtifactId(), mojo3.getGoal(), (MojoBinding) it.next() );
assertMojo( "group", "artifact", "compile", (MojoBinding) it.next() );
assertMojo( mojo.getGroupId(), mojo.getArtifactId(), mojo.getGoal(), (MojoBinding) it.next() );
assertMojo( mojo2.getGroupId(), mojo2.getArtifactId(), mojo2.getGoal(), (MojoBinding) it.next() );
}
private void assertMojo( String groupId, String artifactId, String goal, MojoBinding binding )
{
assertEquals( groupId, binding.getGroupId() );
assertEquals( artifactId, binding.getArtifactId() );
assertEquals( goal, binding.getGoal() );
}
private MojoBinding newMojo( String groupId, String artifactId, String goal )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( groupId );
binding.setArtifactId( artifactId );
binding.setGoal( goal );
return binding;
}
}

View File

@ -42,7 +42,7 @@ under the License.
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.1</version> <version>2.2-beta-1</version>
<configuration> <configuration>
<descriptor>src/main/assembly/bin.xml</descriptor> <descriptor>src/main/assembly/bin.xml</descriptor>
<finalName>maven-${version}</finalName> <finalName>maven-${version}</finalName>
@ -51,7 +51,7 @@ under the License.
<execution> <execution>
<phase>install</phase> <phase>install</phase>
<goals> <goals>
<goal>attached</goal> <goal>single</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>

View File

@ -22,7 +22,7 @@ public class LifecycleUtils
{ {
} }
public static void setOrigin( LifecycleBindings bindings, String origin ) public static void setOrigin( final LifecycleBindings bindings, final String origin )
{ {
for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); ) for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); )
{ {
@ -52,7 +52,7 @@ public class LifecycleUtils
} }
} }
public static List getMojoBindingListForLifecycle( String stopPhase, LifecycleBindings bindings ) public static List getMojoBindingListForLifecycle( final String stopPhase, final LifecycleBindings bindings )
throws NoSuchPhaseException throws NoSuchPhaseException
{ {
LifecycleBinding binding = findLifecycleBindingForPhase( stopPhase, bindings ); LifecycleBinding binding = findLifecycleBindingForPhase( stopPhase, bindings );
@ -65,7 +65,7 @@ public class LifecycleUtils
return getMojoBindingListForLifecycle( stopPhase, binding ); return getMojoBindingListForLifecycle( stopPhase, binding );
} }
public static List getMojoBindingListForLifecycle( String stopPhase, LifecycleBinding lifecycle ) public static List getMojoBindingListForLifecycle( final String stopPhase, final LifecycleBinding lifecycle )
throws NoSuchPhaseException throws NoSuchPhaseException
{ {
List phaseNames = lifecycle.getPhaseNamesInOrder(); List phaseNames = lifecycle.getPhaseNamesInOrder();
@ -85,7 +85,7 @@ public class LifecycleUtils
Phase phase = (Phase) phases.get( i ); Phase phase = (Phase) phases.get( i );
List phaseBindings = phase.getBindings(); List phaseBindings = phase.getBindings();
if ( phaseBindings != null && !phaseBindings.isEmpty() ) if ( ( phaseBindings != null ) && !phaseBindings.isEmpty() )
{ {
bindings.addAll( phaseBindings ); bindings.addAll( phaseBindings );
} }
@ -97,7 +97,8 @@ public class LifecycleUtils
/** /**
* @return null if the phase is not contained in any of the lifecycles. * @return null if the phase is not contained in any of the lifecycles.
*/ */
public static LifecycleBinding findLifecycleBindingForPhase( String phaseName, LifecycleBindings lifecycles ) public static LifecycleBinding findLifecycleBindingForPhase( final String phaseName,
final LifecycleBindings lifecycles )
{ {
List lifecyclesAvailable = lifecycles.getBindingList(); List lifecyclesAvailable = lifecycles.getBindingList();
@ -114,8 +115,8 @@ public class LifecycleUtils
return null; return null;
} }
public static void removeMojoBinding( String phaseName, MojoBinding mojoBinding, LifecycleBinding lifecycleBinding, public static void removeMojoBinding( final String phaseName, final MojoBinding mojoBinding,
boolean considerExecutionId ) final LifecycleBinding lifecycleBinding, final boolean considerExecutionId )
throws NoSuchPhaseException throws NoSuchPhaseException
{ {
List phaseNames = lifecycleBinding.getPhaseNamesInOrder(); List phaseNames = lifecycleBinding.getPhaseNamesInOrder();
@ -125,7 +126,7 @@ public class LifecycleUtils
if ( idx < 0 ) if ( idx < 0 )
{ {
throw new NoSuchPhaseException( phaseName, "Phase: " + phaseName + " not found in lifecycle: " throw new NoSuchPhaseException( phaseName, "Phase: " + phaseName + " not found in lifecycle: "
+ lifecycleBinding.getId() ); + lifecycleBinding.getId() );
} }
List phases = lifecycleBinding.getPhasesInOrder(); List phases = lifecycleBinding.getPhasesInOrder();
@ -136,13 +137,13 @@ public class LifecycleUtils
{ {
List mojoBindings = phase.getBindings(); List mojoBindings = phase.getBindings();
String targetKey = createMojoBindingKey( mojoBinding, considerExecutionId ); String targetKey = MojoBindingUtils.createMojoBindingKey( mojoBinding, considerExecutionId );
for ( Iterator it = mojoBindings.iterator(); it.hasNext(); ) for ( Iterator it = mojoBindings.iterator(); it.hasNext(); )
{ {
MojoBinding candidate = (MojoBinding) it.next(); MojoBinding candidate = (MojoBinding) it.next();
String candidateKey = createMojoBindingKey( candidate, considerExecutionId ); String candidateKey = MojoBindingUtils.createMojoBindingKey( candidate, considerExecutionId );
if ( candidateKey.equals( targetKey ) ) if ( candidateKey.equals( targetKey ) )
{ {
it.remove(); it.remove();
@ -153,8 +154,8 @@ public class LifecycleUtils
} }
} }
public static void addMojoBinding( String phaseName, MojoBinding mojoBinding, LifecycleBinding lifecycleBinding ) public static void addMojoBinding( final String phaseName, final MojoBinding mojoBinding,
throws NoSuchPhaseException final LifecycleBinding lifecycleBinding ) throws NoSuchPhaseException
{ {
List phaseNames = lifecycleBinding.getPhaseNamesInOrder(); List phaseNames = lifecycleBinding.getPhaseNamesInOrder();
@ -163,7 +164,7 @@ public class LifecycleUtils
if ( idx < 0 ) if ( idx < 0 )
{ {
throw new NoSuchPhaseException( phaseName, "Phase: " + phaseName + " not found in lifecycle: " throw new NoSuchPhaseException( phaseName, "Phase: " + phaseName + " not found in lifecycle: "
+ lifecycleBinding.getId() ); + lifecycleBinding.getId() );
} }
List phases = lifecycleBinding.getPhasesInOrder(); List phases = lifecycleBinding.getPhasesInOrder();
@ -172,7 +173,7 @@ public class LifecycleUtils
phase.addBinding( mojoBinding ); phase.addBinding( mojoBinding );
} }
public static void addMojoBinding( String phaseName, MojoBinding mojo, LifecycleBindings bindings ) public static void addMojoBinding( final String phaseName, final MojoBinding mojo, final LifecycleBindings bindings )
throws LifecycleSpecificationException throws LifecycleSpecificationException
{ {
LifecycleBinding binding = findLifecycleBindingForPhase( phaseName, bindings ); LifecycleBinding binding = findLifecycleBindingForPhase( phaseName, bindings );
@ -185,21 +186,25 @@ public class LifecycleUtils
addMojoBinding( phaseName, mojo, binding ); addMojoBinding( phaseName, mojo, binding );
} }
public static LifecycleBindings mergeBindings( LifecycleBindings existingBindings, LifecycleBindings newBindings, public static LifecycleBindings mergeBindings( final LifecycleBindings existingBindings,
LifecycleBindings defaultBindings, boolean mergeConfigIfExecutionIdMatches ) final LifecycleBindings newBindings,
final LifecycleBindings defaultBindings,
final boolean mergeConfigIfExecutionIdMatches )
{ {
return mergeBindings( existingBindings, newBindings, defaultBindings, mergeConfigIfExecutionIdMatches, false ); return mergeBindings( existingBindings, newBindings, defaultBindings, mergeConfigIfExecutionIdMatches, false );
} }
public static LifecycleBindings mergeBindings( LifecycleBindings existingBindings, LifecycleBindings newBindings, public static LifecycleBindings mergeBindings( final LifecycleBindings existingBindings,
LifecycleBindings defaultBindings, boolean mergeConfigIfExecutionIdMatches, final LifecycleBindings newBindings,
boolean reverseConfigMergeDirection ) final LifecycleBindings defaultBindings,
final boolean mergeConfigIfExecutionIdMatches,
final boolean reverseConfigMergeDirection )
{ {
LifecycleBindings result = new LifecycleBindings(); LifecycleBindings result = new LifecycleBindings();
result.setPackaging( newBindings.getPackaging() ); result.setPackaging( newBindings.getPackaging() );
CleanBinding cb = (CleanBinding) cloneBinding( existingBindings.getCleanBinding() ); CleanBinding cb = (CleanBinding) cloneBinding( existingBindings.getCleanBinding() );
if ( defaultBindings != null && isNullOrEmpty( cb ) ) if ( ( defaultBindings != null ) && isNullOrEmpty( cb ) )
{ {
cb = (CleanBinding) cloneBinding( defaultBindings.getCleanBinding() ); cb = (CleanBinding) cloneBinding( defaultBindings.getCleanBinding() );
} }
@ -212,7 +217,7 @@ public class LifecycleUtils
result.setCleanBinding( cb ); result.setCleanBinding( cb );
BuildBinding bb = (BuildBinding) cloneBinding( existingBindings.getBuildBinding() ); BuildBinding bb = (BuildBinding) cloneBinding( existingBindings.getBuildBinding() );
if ( defaultBindings != null && isNullOrEmpty( bb ) ) if ( ( defaultBindings != null ) && isNullOrEmpty( bb ) )
{ {
bb = (BuildBinding) cloneBinding( defaultBindings.getBuildBinding() ); bb = (BuildBinding) cloneBinding( defaultBindings.getBuildBinding() );
} }
@ -225,7 +230,7 @@ public class LifecycleUtils
result.setBuildBinding( bb ); result.setBuildBinding( bb );
SiteBinding sb = (SiteBinding) cloneBinding( existingBindings.getSiteBinding() ); SiteBinding sb = (SiteBinding) cloneBinding( existingBindings.getSiteBinding() );
if ( defaultBindings != null && isNullOrEmpty( sb ) ) if ( ( defaultBindings != null ) && isNullOrEmpty( sb ) )
{ {
sb = (SiteBinding) cloneBinding( defaultBindings.getSiteBinding() ); sb = (SiteBinding) cloneBinding( defaultBindings.getSiteBinding() );
} }
@ -251,7 +256,7 @@ public class LifecycleUtils
Phase phase = (Phase) phases.get( i ); Phase phase = (Phase) phases.get( i );
String name = (String) phaseNames.get( i ); String name = (String) phaseNames.get( i );
if ( phase != null && phase.getBindings() != null && !phase.getBindings().isEmpty() ) if ( ( phase != null ) && ( phase.getBindings() != null ) && !phase.getBindings().isEmpty() )
{ {
for ( Iterator phaseIt = phase.getBindings().iterator(); phaseIt.hasNext(); ) for ( Iterator phaseIt = phase.getBindings().iterator(); phaseIt.hasNext(); )
{ {
@ -261,40 +266,46 @@ public class LifecycleUtils
if ( mergeConfigIfExecutionIdMatches ) if ( mergeConfigIfExecutionIdMatches )
{ {
MojoBinding matchingBinding = findMatchingMojoBinding( mojoBinding, existingBindings, true ); MojoBinding matchingBinding =
findMatchingMojoBinding( mojoBinding, existingBindings, true );
if ( matchingBinding != null ) if ( matchingBinding != null )
{ {
Xpp3Dom existingConfig = new Xpp3Dom( (Xpp3Dom) matchingBinding.getConfiguration() ); Xpp3Dom existingConfig = new Xpp3Dom( (Xpp3Dom) matchingBinding.getConfiguration() );
Xpp3Dom configuration; Xpp3Dom configuration;
if ( reverseConfigMergeDirection ) if ( reverseConfigMergeDirection )
{ {
configuration = Xpp3Dom.mergeXpp3Dom( existingConfig, (Xpp3Dom) mojoBinding.getConfiguration() ); configuration =
Xpp3Dom.mergeXpp3Dom( existingConfig,
(Xpp3Dom) mojoBinding.getConfiguration() );
} }
else else
{ {
configuration = Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) mojoBinding.getConfiguration(), existingConfig ); configuration =
Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) mojoBinding.getConfiguration(),
existingConfig );
} }
mojoBinding.setConfiguration( configuration ); mojoBinding.setConfiguration( configuration );
if ( mojoBinding.getOrigin() == null && matchingBinding.getOrigin() != null ) if ( ( mojoBinding.getOrigin() == null ) && ( matchingBinding.getOrigin() != null ) )
{ {
mojoBinding.setOrigin( matchingBinding.getOrigin() ); mojoBinding.setOrigin( matchingBinding.getOrigin() );
} }
LifecycleBinding resultBinding = findLifecycleBindingForPhase( name, result ); LifecycleBinding resultBinding = findLifecycleBindingForPhase( name, result );
try try
{ {
removeMojoBinding( name, matchingBinding, resultBinding, true ); removeMojoBinding( name, matchingBinding, resultBinding, true );
} }
catch ( NoSuchPhaseException e ) catch ( NoSuchPhaseException e )
{ {
IllegalStateException error = new IllegalStateException( IllegalStateException error =
e.getMessage() new IllegalStateException(
+ "\nSomething strange is going on. Merging should not encounter such inconsistencies." ); e.getMessage()
+ "\nSomething strange is going on. Merging should not encounter such inconsistencies." );
error.initCause( e ); error.initCause( e );
@ -311,9 +322,9 @@ public class LifecycleUtils
{ {
// NOTE: this shouldn't happen as long as normal components are used // NOTE: this shouldn't happen as long as normal components are used
// to create/read these LifecycleBindings instances. // to create/read these LifecycleBindings instances.
IllegalArgumentException error = new IllegalArgumentException( IllegalArgumentException error =
"Project bindings are invalid. Reason: " new IllegalArgumentException( "Project bindings are invalid. Reason: "
+ e.getMessage() ); + e.getMessage() );
error.initCause( e ); error.initCause( e );
@ -328,35 +339,36 @@ public class LifecycleUtils
return result; return result;
} }
private static boolean isNullOrEmpty( LifecycleBinding binding ) private static boolean isNullOrEmpty( final LifecycleBinding binding )
{ {
if ( binding == null ) if ( binding == null )
{ {
return true; return true;
} }
for ( Iterator it = binding.getPhasesInOrder().iterator(); it.hasNext(); ) for ( Iterator it = binding.getPhasesInOrder().iterator(); it.hasNext(); )
{ {
Phase phase = (Phase) it.next(); Phase phase = (Phase) it.next();
if ( !phase.getBindings().isEmpty() ) if ( !phase.getBindings().isEmpty() )
{ {
return false; return false;
} }
} }
return true; return true;
} }
public static MojoBinding findMatchingMojoBinding( MojoBinding mojoBinding, LifecycleBindings inBindings, public static MojoBinding findMatchingMojoBinding( final MojoBinding mojoBinding,
boolean considerExecutionId ) final LifecycleBindings inBindings,
final boolean considerExecutionId )
{ {
String key = createMojoBindingKey( mojoBinding, considerExecutionId ); String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, considerExecutionId );
return (MojoBinding) mapMojoBindingsByKey( inBindings, considerExecutionId ).get( key ); return (MojoBinding) mapMojoBindingsByKey( inBindings, considerExecutionId ).get( key );
} }
private static Map mapMojoBindingsByKey( LifecycleBindings bindings, boolean considerExecutionId ) private static Map mapMojoBindingsByKey( final LifecycleBindings bindings, final boolean considerExecutionId )
{ {
Map byKey = new HashMap(); Map byKey = new HashMap();
@ -376,7 +388,8 @@ public class LifecycleUtils
{ {
MojoBinding mojoBinding = (MojoBinding) mojoIt.next(); MojoBinding mojoBinding = (MojoBinding) mojoIt.next();
byKey.put( createMojoBindingKey( mojoBinding, considerExecutionId ), mojoBinding ); byKey.put( MojoBindingUtils.createMojoBindingKey( mojoBinding, considerExecutionId ),
mojoBinding );
} }
} }
} }
@ -386,8 +399,8 @@ public class LifecycleUtils
return byKey; return byKey;
} }
public static void removeMojoBindings( List toRemove, LifecycleBindings bindings, boolean considerExecutionId ) public static void removeMojoBindings( final List toRemove, final LifecycleBindings bindings,
throws NoSuchPhaseException final boolean considerExecutionId ) throws NoSuchPhaseException
{ {
if ( bindings.getCleanBinding() != null ) if ( bindings.getCleanBinding() != null )
{ {
@ -405,8 +418,8 @@ public class LifecycleUtils
} }
} }
public static void removeMojoBindings( List toRemove, LifecycleBinding removeFrom, boolean considerExecutionId ) public static void removeMojoBindings( final List toRemove, final LifecycleBinding removeFrom,
throws NoSuchPhaseException final boolean considerExecutionId ) throws NoSuchPhaseException
{ {
// remove where gid:aid:goal matches. // remove where gid:aid:goal matches.
List targets = new ArrayList(); List targets = new ArrayList();
@ -414,7 +427,7 @@ public class LifecycleUtils
{ {
MojoBinding binding = (MojoBinding) it.next(); MojoBinding binding = (MojoBinding) it.next();
targets.add( createMojoBindingKey( binding, considerExecutionId ) ); targets.add( MojoBindingUtils.createMojoBindingKey( binding, considerExecutionId ) );
} }
List phases = removeFrom.getPhasesInOrder(); List phases = removeFrom.getPhasesInOrder();
@ -427,7 +440,7 @@ public class LifecycleUtils
for ( Iterator mojoIt = phaseBindings.iterator(); mojoIt.hasNext(); ) for ( Iterator mojoIt = phaseBindings.iterator(); mojoIt.hasNext(); )
{ {
MojoBinding binding = (MojoBinding) mojoIt.next(); MojoBinding binding = (MojoBinding) mojoIt.next();
String key = createMojoBindingKey( binding, considerExecutionId ); String key = MojoBindingUtils.createMojoBindingKey( binding, considerExecutionId );
if ( targets.contains( key ) ) if ( targets.contains( key ) )
{ {
mojoIt.remove(); mojoIt.remove();
@ -438,19 +451,7 @@ public class LifecycleUtils
} }
} }
public static String createMojoBindingKey( MojoBinding mojoBinding, boolean considerExecutionId ) public static LifecycleBindings cloneBindings( final LifecycleBindings bindings )
{
String key = mojoBinding.getGroupId() + ":" + mojoBinding.getArtifactId() + ":" + mojoBinding.getGoal();
if ( considerExecutionId )
{
key += ":" + mojoBinding.getExecutionId();
}
return key;
}
public static LifecycleBindings cloneBindings( LifecycleBindings bindings )
{ {
LifecycleBindings result = new LifecycleBindings(); LifecycleBindings result = new LifecycleBindings();
@ -472,7 +473,7 @@ public class LifecycleUtils
return result; return result;
} }
public static LifecycleBinding cloneBinding( LifecycleBinding binding ) public static LifecycleBinding cloneBinding( final LifecycleBinding binding )
{ {
if ( binding == null ) if ( binding == null )
{ {
@ -495,7 +496,7 @@ public class LifecycleUtils
else else
{ {
throw new IllegalArgumentException( "Unrecognized LifecycleBinding type: " + binding.getClass().getName() throw new IllegalArgumentException( "Unrecognized LifecycleBinding type: " + binding.getClass().getName()
+ "; cannot clone." ); + "; cannot clone." );
} }
List phases = binding.getPhasesInOrder(); List phases = binding.getPhasesInOrder();
@ -518,8 +519,10 @@ public class LifecycleUtils
} }
catch ( NoSuchPhaseException e ) catch ( NoSuchPhaseException e )
{ {
IllegalStateException error = new IllegalStateException( e.getMessage() IllegalStateException error =
+ "\nSomething strange is going on. Cloning should not encounter such inconsistencies." ); new IllegalStateException(
e.getMessage()
+ "\nSomething strange is going on. Cloning should not encounter such inconsistencies." );
error.initCause( e ); error.initCause( e );
@ -531,7 +534,7 @@ public class LifecycleUtils
return result; return result;
} }
public static MojoBinding cloneMojoBinding( MojoBinding binding ) public static MojoBinding cloneMojoBinding( final MojoBinding binding )
{ {
MojoBinding result = new MojoBinding(); MojoBinding result = new MojoBinding();
@ -546,10 +549,11 @@ public class LifecycleUtils
return result; return result;
} }
public static Phase findPhaseForMojoBinding( MojoBinding mojoBinding, LifecycleBindings lifecycleBindings, public static Phase findPhaseForMojoBinding( final MojoBinding mojoBinding,
boolean considerExecutionId ) final LifecycleBindings lifecycleBindings,
final boolean considerExecutionId )
{ {
String targetKey = createMojoBindingKey( mojoBinding, considerExecutionId ); String targetKey = MojoBindingUtils.createMojoBindingKey( mojoBinding, considerExecutionId );
for ( Iterator lifecycleIt = lifecycleBindings.getBindingList().iterator(); lifecycleIt.hasNext(); ) for ( Iterator lifecycleIt = lifecycleBindings.getBindingList().iterator(); lifecycleIt.hasNext(); )
{ {
@ -562,7 +566,7 @@ public class LifecycleUtils
for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); ) for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); )
{ {
MojoBinding candidate = (MojoBinding) mojoIt.next(); MojoBinding candidate = (MojoBinding) mojoIt.next();
String key = createMojoBindingKey( candidate, considerExecutionId ); String key = MojoBindingUtils.createMojoBindingKey( candidate, considerExecutionId );
if ( key.equals( targetKey ) ) if ( key.equals( targetKey ) )
{ {
return phase; return phase;
@ -574,15 +578,16 @@ public class LifecycleUtils
return null; return null;
} }
public static boolean isMojoBindingPresent( MojoBinding binding, List candidates, boolean considerExecutionId ) public static boolean isMojoBindingPresent( final MojoBinding binding, final List candidates,
final boolean considerExecutionId )
{ {
String key = createMojoBindingKey( binding, considerExecutionId ); String key = MojoBindingUtils.createMojoBindingKey( binding, considerExecutionId );
for ( Iterator it = candidates.iterator(); it.hasNext(); ) for ( Iterator it = candidates.iterator(); it.hasNext(); )
{ {
MojoBinding candidate = (MojoBinding) it.next(); MojoBinding candidate = (MojoBinding) it.next();
String candidateKey = createMojoBindingKey( candidate, considerExecutionId ); String candidateKey = MojoBindingUtils.createMojoBindingKey( candidate, considerExecutionId );
if ( candidateKey.equals( key ) ) if ( candidateKey.equals( key ) )
{ {
@ -593,79 +598,87 @@ public class LifecycleUtils
return false; return false;
} }
public static boolean isValidPhaseName( String phaseName ) public static boolean isValidPhaseName( final String phaseName )
{ {
LifecycleBindings test = new LifecycleBindings(); LifecycleBindings test = new LifecycleBindings();
for ( Iterator it = test.getBindingList().iterator(); it.hasNext(); ) for ( Iterator it = test.getBindingList().iterator(); it.hasNext(); )
{ {
LifecycleBinding binding = (LifecycleBinding) it.next(); LifecycleBinding binding = (LifecycleBinding) it.next();
if ( binding.getPhaseNamesInOrder().contains( phaseName ) ) if ( binding.getPhaseNamesInOrder().contains( phaseName ) )
{ {
return true; return true;
} }
} }
return false; return false;
} }
public static List getValidPhaseNames() public static List getValidPhaseNames()
{ {
List phaseNames = new ArrayList(); List phaseNames = new ArrayList();
LifecycleBindings bindings = new LifecycleBindings(); LifecycleBindings bindings = new LifecycleBindings();
for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); ) for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); )
{ {
LifecycleBinding binding = (LifecycleBinding) bindingIt.next(); LifecycleBinding binding = (LifecycleBinding) bindingIt.next();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); ) for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{ {
phaseNames.add( phaseNameIt.next() ); phaseNames.add( phaseNameIt.next() );
} }
} }
return phaseNames; return phaseNames;
} }
public static List getValidBuildPhaseNames() public static List getValidBuildPhaseNames()
{ {
List phaseNames = new ArrayList(); List phaseNames = new ArrayList();
LifecycleBinding binding = new BuildBinding(); LifecycleBinding binding = new BuildBinding();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); ) for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{ {
phaseNames.add( phaseNameIt.next() ); phaseNames.add( phaseNameIt.next() );
} }
return phaseNames; return phaseNames;
} }
public static List getValidCleanPhaseNames() public static List getValidCleanPhaseNames()
{ {
List phaseNames = new ArrayList(); List phaseNames = new ArrayList();
LifecycleBinding binding = new CleanBinding(); LifecycleBinding binding = new CleanBinding();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); ) for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{ {
phaseNames.add( phaseNameIt.next() ); phaseNames.add( phaseNameIt.next() );
} }
return phaseNames; return phaseNames;
} }
public static List getValidSitePhaseNames() public static List getValidSitePhaseNames()
{ {
List phaseNames = new ArrayList(); List phaseNames = new ArrayList();
LifecycleBinding binding = new SiteBinding(); LifecycleBinding binding = new SiteBinding();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); ) for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{ {
phaseNames.add( phaseNameIt.next() ); phaseNames.add( phaseNameIt.next() );
} }
return phaseNames; return phaseNames;
} }
/**
* @deprecated Use {@link MojoBindingUtils#createMojoBindingKey(MojoBinding, boolean)} instead.
*/
public static String createMojoBindingKey( final MojoBinding mojoBinding, final boolean considerExecutionId )
{
return MojoBindingUtils.createMojoBindingKey( mojoBinding, considerExecutionId );
}
} }

View File

@ -9,10 +9,35 @@ public final class MojoBindingUtils
{ {
} }
public static String toString( MojoBinding mojoBinding ) public static String toString( final MojoBinding mojoBinding )
{ {
return mojoBinding.getGroupId() + ":" + mojoBinding.getArtifactId() + ":" return mojoBinding.getGroupId() + ":" + mojoBinding.getArtifactId() + ":"
+ ( mojoBinding.getVersion() == null ? "" : mojoBinding.getVersion() + ":" ) + mojoBinding.getGoal(); + ( mojoBinding.getVersion() == null ? "" : mojoBinding.getVersion() + ":" )
+ mojoBinding.getGoal();
}
public static String createMojoBindingKey( final MojoBinding mojoBinding, final boolean considerExecutionId )
{
String key = mojoBinding.getGroupId() + ":" + mojoBinding.getArtifactId() + ":" + mojoBinding.getGoal();
if ( considerExecutionId )
{
key += ":" + mojoBinding.getExecutionId();
}
return key;
}
public static String createPluginKey( final MojoBinding binding )
{
String result = binding.getGroupId() + ":" + binding.getArtifactId();
if ( binding.getVersion() != null )
{
result += ":" + binding.getVersion();
}
return result;
} }
} }

View File

@ -615,6 +615,18 @@
<type>boolean</type> <type>boolean</type>
</field> </field>
</fields> </fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String toString()
{
return getGroupId() + ":" + getArtifactId() + ":" + getVersion() + ":" + getGoal() + ":" + getExecutionId();
}
]]></code>
</codeSegment>
</codeSegments>
</class> </class>
</classes> </classes>
</model> </model>

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -17,10 +16,7 @@ software distributed under the License is distributed on an
KIND, either express or implied. See the License for the KIND, either express or implied. See the License for the
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
--> --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>