maven-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jvan...@apache.org
Subject svn commit: r751454 [2/3] - in /maven/components/branches/MNG-2766: ./ maven-core/src/main/java/org/apache/maven/ maven-core/src/main/java/org/apache/maven/execution/ maven-core/src/main/java/org/apache/maven/lifecycle/ maven-core/src/main/java/org/apa...
Date Sun, 08 Mar 2009 16:14:26 GMT
Modified: maven/components/branches/MNG-2766/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
URL: http://svn.apache.org/viewvc/maven/components/branches/MNG-2766/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java?rev=751454&r1=751453&r2=751454&view=diff
==============================================================================
--- maven/components/branches/MNG-2766/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java (original)
+++ maven/components/branches/MNG-2766/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java Sun Mar  8 16:14:26 2009
@@ -1,45 +1,42 @@
 package org.apache.maven.lifecycle;
 
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
  */
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Stack;
+import java.util.StringTokenizer;
 
-import org.apache.maven.AggregatedBuildFailureException;
 import org.apache.maven.BuildFailureException;
-import org.apache.maven.NoGoalsSpecifiedException;
-import org.apache.maven.ProjectBuildFailureException;
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
-import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.execution.MavenSession;
 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.model.MojoBinding;
-import org.apache.maven.lifecycle.plan.BuildPlan;
-import org.apache.maven.lifecycle.plan.BuildPlanUtils;
-import org.apache.maven.lifecycle.plan.BuildPlanner;
+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.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.model.ReportPlugin;
+import org.apache.maven.model.ReportSet;
 import org.apache.maven.monitor.event.EventDispatcher;
 import org.apache.maven.monitor.event.MavenEvents;
 import org.apache.maven.plugin.InvalidPluginException;
@@ -49,68 +46,163 @@
 import org.apache.maven.plugin.PluginLoaderException;
 import org.apache.maven.plugin.PluginManager;
 import org.apache.maven.plugin.PluginManagerException;
+import org.apache.maven.plugin.PluginNotFoundException;
+import org.apache.maven.plugin.PluginVersionNotFoundException;
+import org.apache.maven.plugin.PluginVersionResolutionException;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.lifecycle.Execution;
+import org.apache.maven.plugin.lifecycle.Phase;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.apache.maven.reporting.MavenReport;
+import org.apache.maven.settings.Settings;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 /**
- * Responsible for orchestrating the process of building the ordered list of
- * steps required to achieve the specified set of tasks passed into Maven, then
- * executing these mojos in order. This class also manages the various error messages
- * that may occur during this process, and directing the behavior of the build
- * according to what's specified in {@link MavenExecutionRequest#getReactorFailureBehavior()}.
- *
- * @author Jason van Zyl
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
- * @author jdcasey
- * @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)
+ * @version $Id$
+ * @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)
  */
-
 @Component(role = LifecycleExecutor.class)
 public class DefaultLifecycleExecutor
     extends AbstractLogEnabled
     implements LifecycleExecutor
-{
+{    
+    the plugin configuration from the pom is not taken at all, just grab it and then optimize it 
+    
     @Requirement
     private PluginManager pluginManager;
 
-    @Requirement
-    private BuildPlanner buildPlanner;
+    private List<Lifecycle> lifecycles;
 
-    @Requirement
-    private MojoBindingFactory mojoBindingFactory;
-    
-    @Requirement
-    private LifecycleBindingManager lifecycleBindingManager;
-    
-    @Requirement
-    private PlexusContainer container;
+    private List defaultReports;
+
+    private Map phaseToLifecycleMap;
 
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
 
+    public static boolean isValidPhaseName( final String phaseName )
+    {
+        LifecycleBindings test = new LifecycleBindings();
+        for ( Iterator it = test.getBindingList().iterator(); it.hasNext(); )
+        {
+            LifecycleBinding binding = (LifecycleBinding) it.next();
+
+            if ( binding.getPhaseNamesInOrder().contains( phaseName ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * {@inheritDoc}
      */
-    public void execute( MavenSession session, ReactorManager reactorManager, EventDispatcher dispatcher )
+    public TaskValidationResult isTaskValid( String task, MavenSession session, MavenProject rootProject )
+    {
+        //jvz: have to investigate plugins that are run without a root project or using Maven in reactor mode. Looks like we
+        // were never validating these anyway if you look in the execution code.
+
+        if ( rootProject != null )
+        {
+            if ( !isValidPhaseName( task ) )
+            {
+                // definitely a CLI goal, can use prefix
+                try
+                {
+                    getMojoDescriptorForDirectInvocation( task, session, rootProject );
+
+                    return new TaskValidationResult();
+                }
+                catch ( PluginLoaderException e )
+                {
+                    // TODO: shouldn't hit this, investigate using the same resolution logic as
+                    // others for plugins in the reactor
+
+                    return new TaskValidationResult( task, "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator.", e );
+                }
+                catch ( LifecycleSpecificationException e )
+                {
+                    String message = "Invalid task '" + task + "': you must specify a valid lifecycle phase, or"
+                        + " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
+
+                    return new TaskValidationResult( task, message, e );
+                }
+                catch ( LifecycleLoaderException e )
+                {
+                    String message = "Failed to load one or more lifecycle definitions which may contain task: '" + task + "'.";
+
+                    return new TaskValidationResult( task, message, e );
+                }
+                catch ( InvalidPluginException e )
+                {
+                    return new TaskValidationResult( task, e.getMessage(), e );
+                }
+            }
+        }
+
+        return new TaskValidationResult();
+    }
+
+    /**
+     * Retrieve the {@link MojoDescriptor} that corresponds to a given direct mojo invocation. This
+     * is used during the fail-fast method isTaskValid(..), and also during task-segmentation, to
+     * allow the lifecycle executor to determine whether the mojo is an aggregator.
+     * 
+     * @throws PluginLoaderException
+     */
+    private MojoDescriptor getMojoDescriptorForDirectInvocation( String task, MavenSession session, MavenProject project )
+        throws InvalidPluginException, LifecycleSpecificationException, LifecycleLoaderException, PluginLoaderException
+    {        
+        MojoDescriptor descriptor;
+        
+        try
+        {
+            descriptor = getMojoDescriptor( task, session, project, task, true, false );
+        }
+        catch ( LifecycleExecutionException e )
+        {
+            throw new LifecycleSpecificationException( "Cannot find the specified goal.", e );
+        }
+                
+        if ( descriptor == null )
+        {
+            throw new InvalidPluginException( "Plugin: " + descriptor.getId() + " does not contain referenced mojo: " + descriptor.getGoal() );
+        }
+
+        return descriptor;
+    }
+
+    /**
+     * Execute a task. Each task may be a phase in the lifecycle or the execution of a mojo.
+     * 
+     * @param session
+     * @param rm
+     * @param dispatcher
+     */
+    public void execute( MavenSession session, ReactorManager rm, EventDispatcher dispatcher )
         throws BuildFailureException, LifecycleExecutionException
     {
         // TODO: This is dangerous, particularly when it's just a collection of loose-leaf projects being built
         // within the same reactor (using an inclusion pattern to gather them up)...
-        MavenProject rootProject = reactorManager.getTopLevelProject();
+        MavenProject rootProject = rm.getTopLevelProject();
 
         List goals = session.getGoals();
 
-        if ( ( ( goals == null ) || goals.isEmpty() ) && ( rootProject != null ) )
+        if ( goals.isEmpty() && rootProject != null )
         {
             String goal = rootProject.getDefaultGoal();
 
@@ -120,47 +212,17 @@
             }
         }
 
-        if ( ( goals == null ) || goals.isEmpty() )
+        if ( goals.isEmpty() )
         {
-            StringBuffer buffer = new StringBuffer( 1024 );
-
-            buffer.append( "\n\n" );
-            buffer.append( "You must specify at least one goal or lifecycle phase to perform build steps.\n" );
-            buffer.append( "The following list illustrates some commonly used build commands:\n\n" );
-            buffer.append( "  mvn clean\n" );
-            buffer.append( "    Deletes any build output (e.g. class files or JARs).\n" );
-            buffer.append( "  mvn test\n" );
-            buffer.append( "    Runs the unit tests for the project.\n" );
-            buffer.append( "  mvn install\n" );
-            buffer.append( "    Copies the project artifacts into your local repository.\n" );
-            buffer.append( "  mvn deploy\n" );
-            buffer.append( "    Copies the project artifacts into the remote repository.\n" );
-            buffer.append( "  mvn site\n" );
-            buffer.append( "    Creates project documentation (e.g. reports or Javadoc).\n\n" );
-            buffer.append( "Please see\n" );
-            buffer.append( "http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html\n" );
-            buffer.append( "for a complete description of available lifecycle phases.\n\n" );
-            buffer.append( "Use \"mvn --help\" to show general usage information about Maven's command line.\n\n" );
-
-            throw new NoGoalsSpecifiedException( buffer.toString() );
+            throw new BuildFailureException( "\n\nYou must specify at least one goal. Try 'mvn install' to build or 'mvn --help' for options \nSee http://maven.apache.org for more information.\n\n" );
         }
 
         List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject );
 
-        executeTaskSegments( taskSegments, reactorManager, session, rootProject, dispatcher );
+        executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher );
     }
 
-    /**
-     * After the list of goals from {@link MavenSession#getGoals()} is segmented into
-     * contiguous sets of aggregated and non-aggregated mojos and lifecycle phases,
-     * this method is used to execute each task-segment. Its logic has a top-level fork
-     * for each segment, which basically varies the project used to run the execution
-     * according to aggregation needs. If the segment is aggregated, the root project
-     * will be used to construct and execute the mojo bindings. Otherwise, this
-     * method will iterate through each project, and execute all the goals implied
-     * by the current task segment.
-     */
-    private void executeTaskSegments( List taskSegments, ReactorManager reactorManager, MavenSession session, MavenProject rootProject, EventDispatcher dispatcher )
+    private void executeTaskSegments( List taskSegments, ReactorManager rm, MavenSession session, MavenProject rootProject, EventDispatcher dispatcher )
         throws LifecycleExecutionException, BuildFailureException
     {
         for ( Iterator it = taskSegments.iterator(); it.hasNext(); )
@@ -169,7 +231,60 @@
 
             if ( segment.aggregate() )
             {
-                executeTaskSegmentForProject( segment, rootProject, reactorManager, dispatcher, session );
+                if ( !rm.isBlackListed( rootProject ) )
+                {
+                    line();
+
+                    getLogger().info( "Building " + rootProject.getName() );
+
+                    getLogger().info( "  " + segment );
+
+                    line();
+
+                    // !! This is ripe for refactoring to an aspect.
+                    // Event monitoring.
+                    String event = MavenEvents.PROJECT_EXECUTION;
+
+                    long buildStartTime = System.currentTimeMillis();
+
+                    String target = rootProject.getId() + " ( " + segment + " )";
+
+                    dispatcher.dispatchStart( event, target );
+
+                    try
+                    {
+                        session.setCurrentProject( rootProject );
+
+                        // only call once, with the top-level project (assumed to be provided as a parameter)...
+                        for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
+                        {
+                            String task = (String) goalIterator.next();
+
+                            executeGoalAndHandleFailures( task, session, rootProject, dispatcher, event, rm, buildStartTime, target );
+                        }
+
+                        rm.registerBuildSuccess( rootProject, System.currentTimeMillis() - buildStartTime );
+
+                    }
+                    finally
+                    {
+                        session.setCurrentProject( null );
+                    }
+
+                    dispatcher.dispatchEnd( event, target );
+                }
+                else
+                {
+                    line();
+
+                    getLogger().info( "SKIPPING " + rootProject.getName() );
+
+                    getLogger().info( "  " + segment );
+
+                    getLogger().info( "This project has been banned from further executions due to previous failures." );
+
+                    line();
+                }
             }
             else
             {
@@ -179,653 +294,1072 @@
                 for ( Iterator projectIterator = sortedProjects.iterator(); projectIterator.hasNext(); )
                 {
                     MavenProject currentProject = (MavenProject) projectIterator.next();
-                    
-                    executeTaskSegmentForProject( segment, currentProject, reactorManager, dispatcher, session );
+
+                    if ( !rm.isBlackListed( currentProject ) )
+                    {
+                        line();
+
+                        getLogger().info( "Building " + currentProject.getName() );
+
+                        getLogger().info( "  " + segment );
+
+                        line();
+
+                        // !! This is ripe for refactoring to an aspect.
+                        // Event monitoring.
+                        String event = MavenEvents.PROJECT_EXECUTION;
+
+                        long buildStartTime = System.currentTimeMillis();
+
+                        String target = currentProject.getId() + " ( " + segment + " )";
+                        dispatcher.dispatchStart( event, target );
+
+                        try
+                        {
+                            session.setCurrentProject( currentProject );
+
+                            for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
+                            {
+                                String task = (String) goalIterator.next();
+
+                                executeGoalAndHandleFailures( task, session, currentProject, dispatcher, event, rm, buildStartTime, target );
+                            }
+
+                        }
+                        finally
+                        {
+                            session.setCurrentProject( null );
+                        }
+
+                        rm.registerBuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
+
+                        dispatcher.dispatchEnd( event, target );
+                    }
+                    else
+                    {
+                        line();
+
+                        getLogger().info( "SKIPPING " + currentProject.getName() );
+
+                        getLogger().info( "  " + segment );
+
+                        getLogger().info( "This project has been banned from further executions due to previous failures." );
+
+                        line();
+                    }
                 }
             }
         }
     }
 
-    private void executeTaskSegmentForProject( TaskSegment segment,
-                                    MavenProject project,
-                                    ReactorManager reactorManager,
-                                    EventDispatcher dispatcher,
-                                    MavenSession session )
-        throws LifecycleExecutionException, BuildFailureException
+    private void executeGoalAndHandleFailures( String task, MavenSession session, MavenProject project, EventDispatcher dispatcher, String event, ReactorManager rm, long buildStartTime, String target )
+        throws BuildFailureException, LifecycleExecutionException
     {
-        if ( !reactorManager.isBlackListed( project ) )
+        try
         {
-            String target = project.getName() + "\nId: " + project.getId() + "\n" + segment;
-
-            getLogger().debug( "Constructing build plan for " + target );
+            executeGoal( task, session, project );
+        }
+        catch ( LifecycleExecutionException e )
+        {
+            dispatcher.dispatchError( event, target, e );
 
-            String event = MavenEvents.PROJECT_EXECUTION;
+            if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
+            {
+                throw e;
+            }
+        }
+        catch ( BuildFailureException e )
+        {
+            dispatcher.dispatchError( event, target, e );
 
-            long buildStartTime = System.currentTimeMillis();
+            if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
+            {
+                throw e;
+            }
+        }
+    }
 
-            dispatcher.dispatchStart( event, target );
+    private boolean handleExecutionFailure( ReactorManager rm, MavenProject project, Exception e, String task, long buildStartTime )
+    {
+        rm.registerBuildFailure( project, e, task, System.currentTimeMillis() - buildStartTime );
 
-            ClassRealm oldLookupRealm = setProjectLookupRealm( session, project );
+        if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
+        {
+            return true;
+        }
+        else if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) )
+        {
+            rm.blackList( project );
+        }
+        // if NEVER, don't blacklist
+        return false;
+    }
 
-            try
-            {
-                session.setCurrentProject( project );
+    private List segmentTaskListByAggregationNeeds( List tasks, MavenSession session, MavenProject project )
+        throws LifecycleExecutionException, BuildFailureException
+    {
+        List segments = new ArrayList();
 
-                // NEW: Build up the execution plan, including configuration.
-                List mojoBindings = getLifecycleBindings( segment.getTasks(), project, session, target );
+        if ( project != null )
+        {
 
-                String currentPhase = null;
+            TaskSegment currentSegment = null;
+            for ( Iterator it = tasks.iterator(); it.hasNext(); )
+            {
+                String task = (String) it.next();
 
-                // 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)...
-                for ( Iterator mojoIterator = mojoBindings.iterator(); mojoIterator.hasNext(); )
+                // if it's a phase, then we don't need to check whether it's an aggregator.
+                // simply add it to the current task partition.
+                if ( getPhaseToLifecycleMap().containsKey( task ) )
                 {
-                    MojoBinding binding = (MojoBinding) mojoIterator.next();
-
-                    String phase = binding.getPhase() == null ? null : binding.getPhase().getName();
-
-                    if ( ( currentPhase != null ) && !currentPhase.equals( phase ) )
+                    if ( currentSegment != null && currentSegment.aggregate() )
                     {
-                        dispatcher.dispatchEnd( MavenEvents.PHASE_EXECUTION, currentPhase );
-                        currentPhase = null;
+                        segments.add( currentSegment );
+                        currentSegment = null;
                     }
 
-                    if ( ( currentPhase == null ) && ( phase != null ) )
+                    if ( currentSegment == null )
                     {
-                        currentPhase = phase;
-                        dispatcher.dispatchStart( MavenEvents.PHASE_EXECUTION, currentPhase );
+                        currentSegment = new TaskSegment();
                     }
 
-                    try
+                    currentSegment.add( task );
+                }
+                else
+                {
+                    MojoDescriptor mojo = getMojoDescriptor( task, session, project, task, true, false );
+
+                    // if the mojo descriptor was found, determine aggregator status according to:
+                    // 1. whether the mojo declares itself an aggregator
+                    // 2. whether the mojo DOES NOT require a project to function (implicitly avoid reactor)
+                    if ( mojo != null && ( mojo.isAggregator() || !mojo.isProjectRequired() ) )
                     {
-                        executeGoalAndHandleFailures(
-                            binding,
-                            session,
-                            dispatcher,
-                            event,
-                            reactorManager,
-                            buildStartTime,
-                            target,
-                            segment.aggregate() );
+                        if ( currentSegment != null && !currentSegment.aggregate() )
+                        {
+                            segments.add( currentSegment );
+                            currentSegment = null;
+                        }
+
+                        if ( currentSegment == null )
+                        {
+                            currentSegment = new TaskSegment( true );
+                        }
+
+                        currentSegment.add( task );
                     }
-                    catch ( MojoFailureException e )
+                    else
                     {
-                        if ( segment.aggregate() )
+                        if ( currentSegment != null && currentSegment.aggregate() )
+                        {
+                            segments.add( currentSegment );
+                            currentSegment = null;
+                        }
+
+                        if ( currentSegment == null )
                         {
-                            AggregatedBuildFailureException error = new AggregatedBuildFailureException(
-                                                                                                        session.getExecutionRootDirectory(),
-                                                                                                        binding,
-                                                                                                        e );
-
-                           dispatcher.dispatchError( event, target, error );
-
-                           if ( handleExecutionFailure( reactorManager, project, error, binding, buildStartTime ) )
-                           {
-                               throw error;
-                           }
+                            currentSegment = new TaskSegment();
                         }
-                        else
+
+                        currentSegment.add( task );
+                    }
+                }
+            }
+
+            segments.add( currentSegment );
+        }
+        else
+        {
+            TaskSegment segment = new TaskSegment( false );
+            for ( Iterator i = tasks.iterator(); i.hasNext(); )
+            {
+                segment.add( (String) i.next() );
+            }
+            segments.add( segment );
+        }
+
+        return segments;
+    }
+
+    private void executeGoal( String task, MavenSession session, MavenProject project )
+        throws LifecycleExecutionException, BuildFailureException
+    {
+        try
+        {
+            Stack forkEntryPoints = new Stack();
+            if ( getPhaseToLifecycleMap().containsKey( task ) )
+            {
+                Lifecycle lifecycle = getLifecycleForPhase( task );
+
+                // we have a lifecycle phase, so lets bind all the necessary goals
+
+                Map lifecycleMappings = constructLifecycleMappings( session, task, project, lifecycle );
+
+                executeGoalWithLifecycle( task, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
+            }
+            else
+            {
+                executeStandaloneGoal( task, forkEntryPoints, session, project );
+            }
+        }
+        catch ( PluginNotFoundException e )
+        {
+            throw new BuildFailureException( "A required plugin was not found: " + e.getMessage(), e );
+        }
+    }
+
+    private void executeGoalWithLifecycle( String task, Stack forkEntryPoints, MavenSession session, Map lifecycleMappings, MavenProject project, Lifecycle lifecycle )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        List goals = processGoalChain( task, lifecycleMappings, lifecycle );
+
+        if ( !goals.isEmpty() )
+        {
+            executeGoals( goals, forkEntryPoints, session, project );
+        }
+        else
+        {
+            getLogger().info( "No goals needed for project - skipping" );
+        }
+    }
+
+    private void executeStandaloneGoal( String task, Stack forkEntryPoints, MavenSession session, MavenProject project )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        // guaranteed to come from the CLI and not be part of a phase
+        MojoDescriptor mojoDescriptor = getMojoDescriptor( task, session, project, task, true, false );
+        executeGoals( Collections.singletonList( new MojoExecution( mojoDescriptor ) ), forkEntryPoints, session, project );
+    }
+
+    private void executeGoals( List goals, Stack forkEntryPoints, MavenSession session, MavenProject project )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        for ( Iterator i = goals.iterator(); i.hasNext(); )
+        {
+            MojoExecution mojoExecution = (MojoExecution) i.next();
+
+            System.out.println( ">> " + mojoExecution );
+            
+            MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+
+            if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
+            {
+                forkEntryPoints.push( mojoDescriptor );
+
+                forkLifecycle( mojoDescriptor, forkEntryPoints, session, project );
+
+                forkEntryPoints.pop();
+            }
+
+            if ( mojoDescriptor.isRequiresReports() )
+            {
+                List reports = getReports( project, forkEntryPoints, mojoExecution, session );
+
+                mojoExecution.setReports( reports );
+
+                for ( Iterator j = mojoExecution.getForkedExecutions().iterator(); j.hasNext(); )
+                {
+                    MojoExecution forkedExecution = (MojoExecution) j.next();
+                    MojoDescriptor descriptor = forkedExecution.getMojoDescriptor();
+
+                    if ( descriptor.getExecutePhase() != null )
+                    {
+                        forkEntryPoints.push( descriptor );
+
+                        forkLifecycle( descriptor, forkEntryPoints, session, project );
+
+                        forkEntryPoints.pop();
+                    }
+                }
+            }
+
+            try
+            {
+                pluginManager.executeMojo( project, mojoExecution, session );
+            }
+            catch ( PluginManagerException e )
+            {
+                throw new LifecycleExecutionException( "Internal error in the plugin manager executing goal '" + mojoDescriptor.getId() + "': " + e.getMessage(), e );
+            }
+            catch ( ArtifactNotFoundException e )
+            {
+                throw new LifecycleExecutionException( e.getMessage(), e );
+            }
+            catch ( InvalidDependencyVersionException e )
+            {
+                throw new LifecycleExecutionException( e.getMessage(), e );
+            }
+            catch ( ArtifactResolutionException e )
+            {
+                throw new LifecycleExecutionException( e.getMessage(), e );
+            }
+            catch ( MojoFailureException e )
+            {
+                throw new BuildFailureException( e.getMessage(), e );
+            }
+            catch ( PluginConfigurationException e )
+            {
+                throw new LifecycleExecutionException( e.getMessage(), e );
+            }
+        }
+    }
+
+    private List getReports( MavenProject project, Stack forkEntryPoints, MojoExecution mojoExecution, MavenSession session )
+        throws LifecycleExecutionException, PluginNotFoundException
+    {
+        List reportPlugins = project.getReportPlugins();
+
+        if ( project.getModel().getReports() != null )
+        {
+            getLogger().error( "Plugin contains a <reports/> section: this is IGNORED - please use <reporting/> instead." );
+        }
+
+        if ( project.getReporting() == null || !project.getReporting().isExcludeDefaults() )
+        {
+            if ( reportPlugins == null )
+            {
+                reportPlugins = new ArrayList();
+            }
+            else
+            {
+                reportPlugins = new ArrayList( reportPlugins );
+            }
+
+            for ( Iterator i = defaultReports.iterator(); i.hasNext(); )
+            {
+                String report = (String) i.next();
+
+                StringTokenizer tok = new StringTokenizer( report, ":" );
+                int count = tok.countTokens();
+                if ( count != 2 && count != 3 )
+                {
+                    getLogger().warn( "Invalid default report ignored: '" + report + "' (must be groupId:artifactId[:version])" );
+                }
+                else
+                {
+                    String groupId = tok.nextToken();
+                    String artifactId = tok.nextToken();
+                    String version = tok.hasMoreTokens() ? tok.nextToken() : null;
+
+                    boolean found = false;
+                    for ( Iterator j = reportPlugins.iterator(); j.hasNext() && !found; )
+                    {
+                        ReportPlugin reportPlugin = (ReportPlugin) j.next();
+                        if ( reportPlugin.getGroupId().equals( groupId ) && reportPlugin.getArtifactId().equals( artifactId ) )
                         {
-                            ProjectBuildFailureException error = new ProjectBuildFailureException(
-                                                                                                  project.getId(),
-                                                                                                  binding,
-                                                                                                  e );
-
-                           dispatcher.dispatchError( event, target, error );
-
-                           if ( handleExecutionFailure( reactorManager, project, error, binding, buildStartTime ) )
-                           {
-                               throw error;
-                           }
+                            found = true;
                         }
                     }
+
+                    if ( !found )
+                    {
+                        ReportPlugin reportPlugin = new ReportPlugin();
+                        reportPlugin.setGroupId( groupId );
+                        reportPlugin.setArtifactId( artifactId );
+                        reportPlugin.setVersion( version );
+                        reportPlugins.add( reportPlugin );
+                    }
                 }
+            }
+        }
+
+        List reports = new ArrayList();
+        if ( reportPlugins != null )
+        {
+            for ( Iterator it = reportPlugins.iterator(); it.hasNext(); )
+            {
+                ReportPlugin reportPlugin = (ReportPlugin) it.next();
 
-                if ( currentPhase != null )
+                List reportSets = reportPlugin.getReportSets();
+
+                if ( reportSets == null || reportSets.isEmpty() )
+                {
+                    reports.addAll( getReports( reportPlugin, forkEntryPoints, null, project, session, mojoExecution ) );
+                }
+                else
                 {
-                    dispatcher.dispatchEnd( MavenEvents.PHASE_EXECUTION, currentPhase );
+                    for ( Iterator j = reportSets.iterator(); j.hasNext(); )
+                    {
+                        ReportSet reportSet = (ReportSet) j.next();
+
+                        reports.addAll( getReports( reportPlugin, forkEntryPoints, reportSet, project, session, mojoExecution ) );
+                    }
                 }
             }
-            finally
+        }
+        return reports;
+    }
+
+    private List getReports( ReportPlugin reportPlugin, Stack forkEntryPoints, ReportSet reportSet, MavenProject project, MavenSession session, MojoExecution mojoExecution )
+        throws LifecycleExecutionException, PluginNotFoundException
+    {
+        PluginDescriptor pluginDescriptor = loadReport( reportPlugin, project, session );
+
+        List reports = new ArrayList();
+
+        for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); )
+        {
+            MojoDescriptor mojoDescriptor = (MojoDescriptor) i.next();
+
+            if ( forkEntryPoints.contains( mojoDescriptor ) )
+            {
+                getLogger().debug( "Omitting report: " + mojoDescriptor.getFullGoalName() + " from reports list. It initiated part of the fork currently executing." );
+                continue;
+            }
+
+            // TODO: check ID is correct for reports
+            // if the POM configured no reports, give all from plugin
+            if ( reportSet == null || reportSet.getReports().contains( mojoDescriptor.getGoal() ) )
             {
-                session.setCurrentProject( null );
-                restoreLookupRealm( oldLookupRealm );
+                String id = null;
+                if ( reportSet != null )
+                {
+                    id = reportSet.getId();
+                }
+
+                MojoExecution reportExecution = new MojoExecution( mojoDescriptor, id );
+
+                try
+                {
+                    MavenReport reportMojo = pluginManager.getReport( project, reportExecution, session );
+
+                    // Comes back null if it was a plugin, not a report - these are mojos in the reporting plugins that are not reports
+                    if ( reportMojo != null )
+                    {
+                        reports.add( reportMojo );
+
+                        mojoExecution.addMojoExecution( reportExecution );
+                    }
+                }
+                catch ( PluginManagerException e )
+                {
+                    throw new LifecycleExecutionException( "Error getting reports from the plugin '" + reportPlugin.getKey() + "': " + e.getMessage(), e );
+                }
+                catch ( PluginConfigurationException e )
+                {
+                    throw new LifecycleExecutionException( "Error getting reports from the plugin '" + reportPlugin.getKey() + "'", e );
+                }
+                catch ( ArtifactNotFoundException e )
+                {
+                    throw new LifecycleExecutionException( e.getMessage(), e );
+                }
+                catch ( ArtifactResolutionException e )
+                {
+                    throw new LifecycleExecutionException( e.getMessage(), e );
+                }
             }
+        }
+        return reports;
+    }
 
+    private void forkLifecycle( MojoDescriptor mojoDescriptor, Stack ancestorLifecycleForkers, MavenSession session, MavenProject project )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
+        getLogger().info( "Preparing " + pluginDescriptor.getGoalPrefix() + ":" + mojoDescriptor.getGoal() );
+
+        if ( mojoDescriptor.isAggregator() )
+        {
+            for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
+            {
+                MavenProject reactorProject = (MavenProject) i.next();
 
-            reactorManager.registerBuildSuccess(
-                project,
-                System.currentTimeMillis() - buildStartTime );
+                line();
 
-            dispatcher.dispatchEnd(
-                event,
-                target );
+                getLogger().info( "Building " + reactorProject.getName() );
+
+                line();
+
+                forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, reactorProject );
+            }
         }
         else
         {
-            line();
+            forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, project );
+        }
+    }
+
+    private void forkProjectLifecycle( MojoDescriptor mojoDescriptor, Stack forkEntryPoints, MavenSession session, MavenProject project )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        forkEntryPoints.push( mojoDescriptor );
+
+        PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
+
+        String targetPhase = mojoDescriptor.getExecutePhase();
+
+        Map lifecycleMappings = null;
+        if ( targetPhase != null )
+        {
+            Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
+
+            // Create new lifecycle
+            lifecycleMappings = constructLifecycleMappings( session, targetPhase, project, lifecycle );
 
-            getLogger().info( "SKIPPING " + project.getName() );
+            String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
+            if ( executeLifecycle != null )
+            {
+                org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
+                try
+                {
+                    lifecycleOverlay = pluginDescriptor.getLifecycleMapping( executeLifecycle );
+                }
+                catch ( IOException e )
+                {
+                    throw new LifecycleExecutionException( "Unable to read lifecycle mapping file: " + e.getMessage(), e );
+                }
+                catch ( XmlPullParserException e )
+                {
+                    throw new LifecycleExecutionException( "Unable to parse lifecycle mapping file: " + e.getMessage(), e );
+                }
 
-            getLogger().info( "  " + segment );
+                if ( lifecycleOverlay == null )
+                {
+                    throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
+                }
 
-            getLogger().info( "This project has been banned from further executions due to previous failures." );
+                for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
+                {
+                    Phase phase = (Phase) i.next();
+                    for ( Iterator j = phase.getExecutions().iterator(); j.hasNext(); )
+                    {
+                        Execution exec = (Execution) j.next();
 
-            line();
+                        for ( Iterator k = exec.getGoals().iterator(); k.hasNext(); )
+                        {
+                            String goal = (String) k.next();
+
+                            PluginDescriptor lifecyclePluginDescriptor;
+                            String lifecycleGoal;
+
+                            // Here we are looking to see if we have a mojo from an external plugin.
+                            // If we do then we need to lookup the plugin descriptor for the externally
+                            // referenced plugin so that we can overly the execution into the lifecycle.
+                            // An example of this is the corbertura plugin that needs to call the surefire
+                            // plugin in forking mode.
+                            //
+                            //<phase>
+                            //  <id>test</id>
+                            //  <executions>
+                            //    <execution>
+                            //      <goals>
+                            //        <goal>org.apache.maven.plugins:maven-surefire-plugin:test</goal>
+                            //      </goals>
+                            //      <configuration>
+                            //        <classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory>
+                            //        <ignoreFailures>true</ignoreFailures>
+                            //        <forkMode>once</forkMode>
+                            //      </configuration>
+                            //    </execution>
+                            //  </executions>
+                            //</phase>
+
+                            // ----------------------------------------------------------------------
+                            //
+                            // ----------------------------------------------------------------------
+
+                            if ( goal.indexOf( ":" ) > 0 )
+                            {
+                                String[] s = StringUtils.split( goal, ":" );
+
+                                String groupId = s[0];
+                                String artifactId = s[1];
+                                lifecycleGoal = s[2];
+
+                                Plugin plugin = new Plugin();
+                                plugin.setGroupId( groupId );
+                                plugin.setArtifactId( artifactId );
+
+                                lifecyclePluginDescriptor = loadPlugin( plugin, project, session );
+                            }
+                            else
+                            {
+                                lifecyclePluginDescriptor = pluginDescriptor;
+                                lifecycleGoal = goal;
+                            }
+
+                            Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
+                            if ( phase.getConfiguration() != null )
+                            {
+                                configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), configuration );
+                            }
+
+                            MojoDescriptor desc = getMojoDescriptor( lifecyclePluginDescriptor, lifecycleGoal );
+                            MojoExecution mojoExecution = new MojoExecution( desc, configuration );
+                            addToLifecycleMappings( lifecycleMappings, phase.getId(), mojoExecution, session.getSettings() );
+                        }
+                    }
+
+                    if ( phase.getConfiguration() != null )
+                    {
+                        // 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.
+                        //   We should create a new lifecycle executor for modelVersion >5.0.0
+                        for ( Iterator j = lifecycleMappings.values().iterator(); j.hasNext(); )
+                        {
+                            List tasks = (List) j.next();
+
+                            for ( Iterator k = tasks.iterator(); k.hasNext(); )
+                            {
+                                MojoExecution exec = (MojoExecution) k.next();
+
+                                Xpp3Dom configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), exec.getConfiguration() );
+
+                                exec.setConfiguration( configuration );
+                            }
+                        }
+                    }
+
+                }
+            }
+
+            removeFromLifecycle( forkEntryPoints, lifecycleMappings );
+        }
+
+        MavenProject executionProject = new MavenProject( project );
+        if ( targetPhase != null )
+        {
+            Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
+
+            executeGoalWithLifecycle( targetPhase, forkEntryPoints, session, lifecycleMappings, executionProject, lifecycle );
         }
+        else
+        {
+            String goal = mojoDescriptor.getExecuteGoal();
+            MojoDescriptor desc = getMojoDescriptor( pluginDescriptor, goal );
+            executeGoals( Collections.singletonList( new MojoExecution( desc ) ), forkEntryPoints, session, executionProject );
+        }
+        project.setExecutionProject( executionProject );
     }
 
-    /**
-     * Since each project can have its own {@link ClassRealm} instance that inherits
-     * from the core Maven realm, and contains the specific build-extension
-     * components referenced in that project, the lookup realms must be managed for
-     * each project that's used to fire off a mojo execution. This helps ensure
-     * that unsafe {@link PlexusContainer#lookup} and related calls will
-     * have access to these build-extension components.
-     * <br />
-     * This method simply restores the original Maven-core lookup realm when a
-     * project-specific realm is in use.
-     */
-    private void restoreLookupRealm( ClassRealm oldLookupRealm )
+    private Lifecycle getLifecycleForPhase( String phase )
+        throws BuildFailureException, LifecycleExecutionException
     {
-        if ( oldLookupRealm != null )
+        Lifecycle lifecycle = (Lifecycle) getPhaseToLifecycleMap().get( phase );
+
+        if ( lifecycle == null )
         {
-            container.setLookupRealm( oldLookupRealm );
+            throw new BuildFailureException( "Unable to find lifecycle for phase '" + phase + "'" );
         }
+        return lifecycle;
     }
 
-    /**
-     * Since each project can have its own {@link ClassRealm} instance that inherits
-     * from the core Maven realm, and contains the specific build-extension
-     * components referenced in that project, the lookup realms must be managed for
-     * each project that's used to fire off a mojo execution. This helps ensure
-     * that unsafe {@link PlexusContainer#lookup} and related calls will
-     * have access to these build-extension components.
-     * <br />
-     * This method is meant to find a project-specific realm, if one exists, for
-     * use as the lookup realm for unsafe component lookups, using {@link PlexusContainer#setLookupRealm(ClassRealm)}.
-     */
-    private ClassRealm setProjectLookupRealm( MavenSession session,
-                                              MavenProject rootProject )
+    private MojoDescriptor getMojoDescriptor( PluginDescriptor pluginDescriptor, String goal )
         throws LifecycleExecutionException
     {
-        ClassRealm projectRealm = session.getRealmManager().getProjectRealm( rootProject.getGroupId(), rootProject.getArtifactId(), rootProject.getVersion() );
+        MojoDescriptor desc = pluginDescriptor.getMojo( goal );
 
-        if ( projectRealm != null )
+        if ( desc == null )
         {
-            return container.setLookupRealm( projectRealm );
+            String message = "Required goal '" + goal + "' not found in plugin '" + pluginDescriptor.getGoalPrefix() + "'";
+            int index = goal.indexOf( ':' );
+            if ( index >= 0 )
+            {
+                String prefix = goal.substring( index + 1 );
+                if ( prefix.equals( pluginDescriptor.getGoalPrefix() ) )
+                {
+                    message = message + " (goals should not be prefixed - try '" + prefix + "')";
+                }
+            }
+            throw new LifecycleExecutionException( message );
         }
-
-        return container.getLookupRealm();
+        return desc;
     }
 
-    /**
-     * Retrieves the build plan for the current project, given the specified list of tasks. This build plan will consist
-     * of MojoBindings, each fully configured to execute, which enables us to enumerate the full build plan to the debug
-     * log-level, complete with the configuration each mojo will use.
-     */
-    private List getLifecycleBindings( List tasks, MavenProject project, MavenSession session, String targetDescription )
-        throws LifecycleExecutionException
+    private void removeFromLifecycle( Stack lifecycleForkers, Map lifecycleMappings )
     {
-        List mojoBindings;
-        try
+        for ( Iterator lifecycleIterator = lifecycleMappings.values().iterator(); lifecycleIterator.hasNext(); )
         {
-            BuildPlan plan = buildPlanner.constructBuildPlan( tasks, project, session, false );
+            List tasks = (List) lifecycleIterator.next();
 
-            if ( getLogger().isDebugEnabled() )
+            for ( Iterator taskIterator = tasks.iterator(); taskIterator.hasNext(); )
             {
-                getLogger().debug(
-                    "\n\nOur build plan is:\n" + BuildPlanUtils.listBuildPlan(
-                        plan,
-                        false ) + "\n\nfor task-segment: " + targetDescription );
+                MojoExecution execution = (MojoExecution) taskIterator.next();
+
+                if ( lifecycleForkers.contains( execution.getMojoDescriptor() ) )
+                {
+                    taskIterator.remove();
+                    getLogger().warn( "Removing: " + execution.getMojoDescriptor().getGoal() + " from forked lifecycle, to prevent recursive invocation." );
+                }
             }
+        }
+    }
+
+    private Map constructLifecycleMappings( MavenSession session, String selectedPhase, MavenProject project, Lifecycle lifecycle )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        // first, bind those associated with the packaging
+        Map lifecycleMappings = bindLifecycleForPackaging( session, selectedPhase, project, lifecycle );
+
+        // next, loop over plugins and for any that have a phase, bind it
+        for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
+        {
+            Plugin plugin = (Plugin) i.next();
+
+            bindPluginToLifecycle( plugin, session, lifecycleMappings, project );
+        }
+
+        return lifecycleMappings;
+    }
+
+    private Map bindLifecycleForPackaging( MavenSession session, String selectedPhase, MavenProject project, Lifecycle lifecycle )
+        throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
+    {
+        Map mappings = findMappingsForLifecycle( session, project, lifecycle );
+
+        List optionalMojos = findOptionalMojosForLifecycle( session, project, lifecycle );
+
+        Map lifecycleMappings = new HashMap();
 
-            mojoBindings = plan.renderExecutionPlan( new Stack() );
-        }
-        catch ( LifecycleException e )
+        for ( Iterator i = lifecycle.getPhases().iterator(); i.hasNext(); )
         {
-            throw new LifecycleExecutionException(
-                "Failed to construct build plan for: " + targetDescription
-                    + ". Reason: " + e.getMessage(), project,
-                e );
-        }
+            String phase = (String) i.next();
 
-        return mojoBindings;
-    }
+            String phaseTasks = (String) mappings.get( phase );
 
-    /**
-     * Lookup the plugin containing the referenced mojo, validate that it is
-     * allowed to execute in the current environment (according to whether
-     * it's a direct-invocation-only or aggregator mojo, and the allowAggregators
-     * flag), and execute the mojo. If any of these steps fails, this method will
-     * consult with the {@link ReactorManager} to determine whether the build
-     * should be stopped.
-     * <br />
-     * <b>NOTE:</b> If the binding is an aggregator mojo, and the specified project
-     * is not the root project of the reactor (using {@link ReactorManager#getTopLevelProject()},
-     * then print a DEBUG message and skip that execution.
-     */
-    private void executeGoalAndHandleFailures( MojoBinding mojoBinding, MavenSession session, EventDispatcher dispatcher, String event, ReactorManager rm,
-                                               long buildStartTime,
-                                               String target,
-                                               boolean allowAggregators )
-        throws LifecycleExecutionException, MojoFailureException
-    {
-        MavenProject project = session.getCurrentProject();
-
-        // 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
-        // instance, and call PluginManager.executeMojo( execution ). The MojoExecutor is constructed
-        // using both the PluginDescriptor and the MojoBinding.
-        try
-        {
-            PluginDescriptor pluginDescriptor;
-            try
+            if ( phaseTasks != null )
             {
-                pluginDescriptor = pluginManager.loadPlugin( mojoBinding, project, session );
-            }
-            catch ( PluginLoaderException e )
-            {
-                if ( mojoBinding.isOptional() )
-                {
-                    getLogger().debug( "Skipping optional mojo execution: " + MojoBindingUtils.toString( mojoBinding ), e );
-                    return;
-                }
-                else
+                for ( StringTokenizer tok = new StringTokenizer( phaseTasks, "," ); tok.hasMoreTokens(); )
                 {
-                    throw new LifecycleExecutionException(
-                        "Failed to load plugin for: "
-                            + MojoBindingUtils.toString( mojoBinding ) + ". Reason: " + e.getMessage(),
-                            project,
-                        e );
+                    String goal = tok.nextToken().trim();
+
+                    // Not from the CLI, don't use prefix
+                    MojoDescriptor mojoDescriptor = getMojoDescriptor( goal, session, project, selectedPhase, false, optionalMojos.contains( goal ) );
+
+                    if ( mojoDescriptor == null )
+                    {
+                        continue;
+                    }
+
+                    if ( mojoDescriptor.isDirectInvocationOnly() )
+                    {
+                        throw new LifecycleExecutionException( "Mojo: \'" + goal + "\' requires direct invocation. It cannot be used as part of lifecycle: \'" + project.getPackaging() + "\'." );
+                    }
+
+                    addToLifecycleMappings( lifecycleMappings, phase, new MojoExecution( mojoDescriptor ), session.getSettings() );
                 }
             }
 
-            MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() );
+            if ( phase.equals( selectedPhase ) )
+            {
+                break;
+            }
+        }
 
-            // TODO: Figure out how to make this logic produce the same result when the binding is in a module.
-            // At times, the module will build in isolation, in which case this logic would allow the aggregator to run.
-            // In other cases, the module will be part of a reactor build, and the aggregator won't run, because it's not
-            // bound to the root project.
-//            if ( mojoDescriptor.isAggregator() && ( project != rm.getTopLevelProject() ) )
-//            {
-//                getLogger().debug( "Skipping mojo execution: " + MojoBindingUtils.toString( mojoBinding ) + "\nfor project: " + project.getId() + "\n\nIt is an aggregator mojo, and the current project is not the root project for the reactor." );
-//                return;
-//            }
+        return lifecycleMappings;
+    }
 
-            validateMojoExecution( mojoBinding, mojoDescriptor, project, allowAggregators );
+    private Map findMappingsForLifecycle( MavenSession session, MavenProject project, Lifecycle lifecycle )
+        throws LifecycleExecutionException, PluginNotFoundException
+    {
+        String packaging = project.getPackaging();
+        Map mappings = null;
 
-            MojoExecution mojoExecution = new MojoExecution( mojoDescriptor );
+        LifecycleMapping m;
 
-            mojoExecution.setConfiguration( (Xpp3Dom) mojoBinding.getConfiguration() );
+        Map defaultMappings = lifecycle.getDefaultPhases();
 
+        if ( mappings == null )
+        {
             try
             {
-                pluginManager.executeMojo(
-                    project,
-                    mojoExecution,
-                    session );
+                m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
+                mappings = m.getPhases( lifecycle.getId() );
             }
-            catch ( PluginManagerException e )
+            catch ( ComponentLookupException e )
             {
-                throw new LifecycleExecutionException(
-                    "Internal error in the plugin manager executing goal '"
-                        + mojoDescriptor.getId() + "': " + e.getMessage(),
-                        project,
-                    e );
+                if ( defaultMappings == null )
+                {
+                    throw new LifecycleExecutionException( "Cannot find lifecycle mapping for packaging: \'" + packaging + "\'.", e );
+                }
             }
-            catch ( ArtifactNotFoundException e )
+        }
+
+        if ( mappings == null )
+        {
+            if ( defaultMappings == null )
             {
-                throw new LifecycleExecutionException(
-                    e.getMessage(),
-                    project,
-                    e );
+                throw new LifecycleExecutionException( "Cannot find lifecycle mapping for packaging: \'" + packaging + "\', and there is no default" );
             }
-            catch ( InvalidDependencyVersionException e )
+            else
             {
-                throw new LifecycleExecutionException(
-                    e.getMessage(),
-                    project,
-                    e );
+                mappings = defaultMappings;
             }
-            catch ( ArtifactResolutionException e )
+        }
+
+        return mappings;
+    }
+
+    private List findOptionalMojosForLifecycle( MavenSession session, MavenProject project, Lifecycle lifecycle )
+        throws LifecycleExecutionException, PluginNotFoundException
+    {
+        String packaging = project.getPackaging();
+        List optionalMojos = null;
+
+        LifecycleMapping m;
+
+        if ( optionalMojos == null )
+        {
+            try
             {
-                throw new LifecycleExecutionException(
-                    e.getMessage(),
-                    project,
-                    e );
+                m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
+                optionalMojos = m.getOptionalMojos( lifecycle.getId() );
             }
-            catch ( PluginConfigurationException e )
+            catch ( ComponentLookupException e )
             {
-                throw new LifecycleExecutionException(
-                    e.getMessage(),
-                    project,
-                    e );
+                getLogger().debug( "Error looking up lifecycle mapping to retrieve optional mojos. Lifecycle ID: " + lifecycle.getId() + ". Error: " + e.getMessage(), e );
             }
         }
-        catch ( LifecycleExecutionException e )
-        {
-            dispatcher.dispatchError( event, target, e );
 
-            if ( handleExecutionFailure( rm, project, e, mojoBinding, buildStartTime ) )
-            {
-                throw e;
-            }
+        if ( optionalMojos == null )
+        {
+            optionalMojos = Collections.EMPTY_LIST;
         }
+
+        return optionalMojos;
     }
 
     /**
-     * Verify that the specified {@link MojoBinding} is legal for execution under
-     * the current circumstances. Currently, this mainly checks that aggregator
-     * mojos and direct-invocation-only mojos are not bound to lifecycle phases.
-     * <br/>
-     * If an invalid mojo is detected, and it is brought in via the user's POM
-     * (this will be checked using {@link MojoBinding#POM_ORIGIN} and {@link MojoBinding#getOrigin()}),
-     * then a {@link LifecycleExecutionException} will be thrown. Otherwise, the mojo
-     * was brought in via a lifecycle mapping or overlay, or as part of a forked execution.
-     * In these cases, the error will be logged to the console, using the ERROR log-level (since the
-     * user cannot fix this sort of problem easily).
+     * Take each mojo contained with a plugin, look to see whether it contributes to a phase in the
+     * lifecycle and if it does place it at the end of the list of goals to execute for that given
+     * phase.
+     * 
+     * @param project
+     * @param session
+     * @throws PluginVersionNotFoundException
+     * @throws PluginManagerException
+     * @throws InvalidPluginException
+     * @throws PluginVersionResolutionException
+     * @throws ArtifactNotFoundException
+     * @throws ArtifactResolutionException
      */
-    private void validateMojoExecution( MojoBinding mojoBinding,
-                                        MojoDescriptor mojoDescriptor,
-                                        MavenProject project,
-                                        boolean allowAggregators )
+    private void bindPluginToLifecycle( Plugin plugin, MavenSession session, Map phaseMap, MavenProject project )
         throws LifecycleExecutionException
     {
-        if ( mojoDescriptor.isAggregator() && !allowAggregators )
-        {
-            if ( MojoBinding.POM_ORIGIN.equals( mojoBinding.getOrigin() ) )
-            {
-                StringBuffer buffer = new StringBuffer();
-                buffer.append( "\n\nDEPRECATED: Binding aggregator mojos to lifecycle phases in the POM is considered dangerous." );
-                buffer.append( "\nThis feature has been deprecated. Please adjust your POM files accordingly." );
-                buffer.append( "\n\nOffending mojo:\n\n" );
-                buffer.append( MojoBindingUtils.toString( mojoBinding ) );
-                buffer.append( "\n\nProject: " ).append( project.getId() );
-                buffer.append( "\nPOM File: " ).append( String.valueOf( project.getFile() ) );
-                buffer.append( "\n" );
+        Settings settings = session.getSettings();
 
-                getLogger().warn( buffer.toString() );
-            }
-            else
+        PluginDescriptor pluginDescriptor = loadPlugin( plugin, project, session );
+
+        if ( pluginDescriptor.getMojos() != null && !pluginDescriptor.getMojos().isEmpty() )
+        {
+            // use the plugin if inherit was true in a base class, or it is in the current POM, otherwise use the default inheritence setting
+            if ( plugin.isInheritanceApplied() || pluginDescriptor.isInheritedByDefault() )
             {
-                StringBuffer buffer = new StringBuffer();
-                buffer.append( "\n\nDEPRECATED: An aggregator mojo has been bound to your project's build lifecycle." );
-                buffer.append( "\nThis feature is dangerous, and has been deprecated." );
-                buffer.append( "\n\nOffending mojo:\n\n" );
-                buffer.append( MojoBindingUtils.toString( mojoBinding ) );
-                buffer.append( "\n\nDirect binding of aggregator mojos to the lifecycle is not allowed, but this binding was not configured from within in your POM." );
-                buffer.append( "\n\nIts origin was: " ).append( mojoBinding.getOrigin() );
-                if ( mojoBinding.getOriginDescription() != null )
+                if ( plugin.getGoals() != null )
                 {
-                    buffer.append( " (" ).append( mojoBinding.getOriginDescription() ).append( ")" );
+                    getLogger().error( "Plugin contains a <goals/> section: this is IGNORED - please use <executions/> instead." );
                 }
 
-                buffer.append( "\n" );
+                List executions = plugin.getExecutions();
+
+                if ( executions != null )
+                {
+                    for ( Iterator it = executions.iterator(); it.hasNext(); )
+                    {
+                        PluginExecution execution = (PluginExecution) it.next();
 
-                getLogger().warn( buffer.toString() );
+                        bindExecutionToLifecycle( pluginDescriptor, phaseMap, execution, settings );
+                    }
+                }
             }
         }
-        else if ( mojoDescriptor.isDirectInvocationOnly() && !MojoBinding.DIRECT_INVOCATION_ORIGIN.equals( mojoBinding.getOrigin() ) )
+    }
+
+    private void bindExecutionToLifecycle( PluginDescriptor pluginDescriptor, Map phaseMap, PluginExecution execution, Settings settings )
+        throws LifecycleExecutionException
+    {
+        for ( Iterator i = execution.getGoals().iterator(); i.hasNext(); )
         {
-            if ( MojoBinding.POM_ORIGIN.equals( mojoBinding.getOrigin() ) )
+            String goal = (String) i.next();
+
+            MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
+            if ( mojoDescriptor == null )
             {
-                throw new LifecycleExecutionException( "Mojo:\n\n" + MojoBindingUtils.toString( mojoBinding ) + "\n\ncan only be invoked directly by the user. Binding it to lifecycle phases in the POM is not allowed.", project );
+                throw new LifecycleExecutionException( "'" + goal + "' was specified in an execution, but not found in the plugin" );
             }
-            else
+
+            // We have to check to see that the inheritance rules have been applied before binding this mojo.
+            if ( execution.isInheritanceApplied() || mojoDescriptor.isInheritedByDefault() )
             {
-                StringBuffer buffer = new StringBuffer();
-                buffer.append( "\n\nSKIPPING execution of mojo:\n\n" ).append( MojoBindingUtils.toString( mojoBinding ) );
-                buffer.append( "\n\nIt specifies direct-invocation only, but has been bound to the build lifecycle." );
-                buffer.append( "\n\nDirect-invocation mojos can only be called by the user. This binding was not configured from within in your POM." );
-                buffer.append( "\n\nIts origin was: " ).append( mojoBinding.getOrigin() );
-                if ( mojoBinding.getOriginDescription() != null )
+                MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
+
+                String phase = execution.getPhase();
+
+                if ( phase == null )
                 {
-                    buffer.append( " (" ).append( mojoBinding.getOriginDescription() ).append( ")" );
+                    // if the phase was not in the configuration, use the phase in the descriptor
+                    phase = mojoDescriptor.getPhase();
                 }
 
-                buffer.append( "\n" );
+                if ( phase != null )
+                {
+                    if ( mojoDescriptor.isDirectInvocationOnly() )
+                    {
+                        throw new LifecycleExecutionException( "Mojo: \'" + goal + "\' requires direct invocation. It cannot be used as part of the lifecycle (it was included via the POM)." );
+                    }
 
-                getLogger().error( buffer.toString() );
+                    addToLifecycleMappings( phaseMap, phase, mojoExecution, settings );
+                }
             }
         }
     }
 
-    /**
-     * In the event that an error occurs during executeGoalAndHandleFailure(..),
-     * this method is called to handle logging the error in the {@link ReactorManager},
-     * then determining (again, from the reactor-manager) whether to stop the build.
-     *
-     * @return true if the build should stop, false otherwise.
-     */
-    private boolean handleExecutionFailure( final ReactorManager rm,
-                                            final MavenProject project,
-                                            final Exception e,
-                                            final MojoBinding mojoBinding,
-                                            final long buildStartTime )
-    {
-        rm.registerBuildFailure(
-            project,
-            e,
-            MojoBindingUtils.toString( mojoBinding ),
-            System.currentTimeMillis()
-                - buildStartTime );
+    private void addToLifecycleMappings( Map lifecycleMappings, String phase, MojoExecution mojoExecution, Settings settings )
+    {
+        List goals = (List) lifecycleMappings.get( phase );
 
-        if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
+        if ( goals == null )
         {
-            return true;
+            goals = new ArrayList();
+            lifecycleMappings.put( phase, goals );
         }
-        else if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) )
+
+        MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
+        if ( settings.isOffline() && mojoDescriptor.isOnlineRequired() )
         {
-            rm.blackList( project );
+            String goal = mojoDescriptor.getGoal();
+            getLogger().warn( goal + " requires online mode, but maven is currently offline. Disabling " + goal + "." );
+        }
+        else
+        {
+            goals.add( mojoExecution );
         }
-        // if NEVER, don't blacklist
-        return false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public TaskValidationResult isTaskValid( String task,
-                                             MavenSession session,
-                                             MavenProject rootProject )
+    private List processGoalChain( String task, Map phaseMap, Lifecycle lifecycle )
     {
-        //jvz: have to investigate plugins that are run without a root project or using Maven in reactor mode. Looks like we
-        // were never validating these anyway if you look in the execution code.
-
-        if ( rootProject != null )
-        {
-
-            if ( !LifecycleUtils.isValidPhaseName( task ) )
-            {
-                // definitely a CLI goal, can use prefix
-                try
-                {
-                    getMojoDescriptorForDirectInvocation(
-                        task,
-                        session,
-                        rootProject );
+        List goals = new ArrayList();
 
-                    return new TaskValidationResult();
-                }
-                catch ( PluginLoaderException e )
-                {
-                    // TODO: shouldn't hit this, investigate using the same resolution logic as
-                    // others for plugins in the reactor
+        // only execute up to the given phase
+        int index = lifecycle.getPhases().indexOf( task );
 
-                    return new TaskValidationResult(
-                        task,
-                        "Cannot find mojo descriptor for: \'" + task
-                            + "\' - Treating as non-aggregator.", e );
-                }
-                catch ( LifecycleSpecificationException e )
-                {
-                    String message =
-                        "Invalid task '"
-                            + task
-                            + "': you must specify a valid lifecycle phase, or"
-                            + " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
-
-                    return new TaskValidationResult(
-                        task,
-                        message, e );
+        for ( int i = 0; i <= index; i++ )
+        {
+            String p = (String) lifecycle.getPhases().get( i );
 
-                }
-                catch ( LifecycleLoaderException e )
-                {
-                    String message = "Failed to load one or more lifecycle definitions which may contain task: '" + task + "'.";
+            List phaseGoals = (List) phaseMap.get( p );
 
-                    return new TaskValidationResult(
-                        task,
-                        message, e );
-                }
-                catch ( InvalidPluginException e )
-                {
-                    return new TaskValidationResult(
-                        task,
-                        e.getMessage(), e );
-                }
+            if ( phaseGoals != null )
+            {
+                goals.addAll( phaseGoals );
             }
         }
-
-        return new TaskValidationResult();
+        return goals;
     }
 
-    /**
-     * Split up the list of goals from {@link MavenSession#getGoals()} according
-     * to aggregation needs. Each adjacent goal in the list is included in a single
-     * task segment. When the next goal references a different type of mojo or
-     * lifecycle phase (eg. previous goal wasn't an aggregator, but next one is...or the reverse),
-     * a new task segment is started and the new goal is added to that.
-     *
-     * @return the list of task-segments, each flagged according to aggregation needs.
-     */
-    private List segmentTaskListByAggregationNeeds( final List tasks,
-                                                    final MavenSession session,
-                                                    final MavenProject rootProject )
+    private MojoDescriptor getMojoDescriptor( String task, MavenSession session, MavenProject project, String invokedVia, boolean canUsePrefix, boolean isOptionalMojo )
+        throws LifecycleExecutionException
     {
-        List segments = new ArrayList();
+        String goal;
+        Plugin plugin;
 
-        if ( rootProject != null )
-        {
-            TaskSegment currentSegment = null;
+        PluginDescriptor pluginDescriptor = null;
 
-            for ( Iterator it = tasks.iterator(); it.hasNext(); )
-            {
-                String task = (String) it.next();
+        StringTokenizer tok = new StringTokenizer( task, ":" );
+        int numTokens = tok.countTokens();
 
-                // if it's a phase, then we don't need to check whether it's an aggregator.
-                // simply add it to the current task partition.
-                if ( LifecycleUtils.isValidPhaseName( task ) )
-                {
-                    if ( ( currentSegment != null ) && currentSegment.aggregate() )
-                    {
-                        segments.add( currentSegment );
-                        currentSegment = null;
-                    }
+        if ( numTokens == 2 )
+        {
+            if ( !canUsePrefix )
+            {
+                String msg = "Mapped-prefix lookup of mojos are only supported from direct invocation. " + "Please use specification of the form groupId:artifactId[:version]:goal instead. "
+                    + "(Offending mojo: \'" + task + "\', invoked via: \'" + invokedVia + "\')";
+                throw new LifecycleExecutionException( msg );
+            }
 
-                    if ( currentSegment == null )
-                    {
-                        currentSegment = new TaskSegment();
-                    }
+            String prefix = tok.nextToken();
+            goal = tok.nextToken();
 
-                    currentSegment.add( task );
-                }
-                else
-                {
-                    MojoDescriptor mojo = null;
+            plugin = pluginManager.getPluginDefinitionForPrefix( prefix, session, project );
+            
+            if ( plugin == null )
+            {
+                plugin = new Plugin();
 
-                    try
-                    {
-                        mojo = getMojoDescriptorForDirectInvocation(
-                            task,
-                            session,
-                            rootProject );
-                    }
-                    catch ( Exception e )
-                    {
-                        // Won't happen as we've validated. So we need to change the code so that
-                        // we don't have to do this.
-                    }
+                plugin.setGroupId( pluginDescriptor.getGroupId() );
+                plugin.setArtifactId( pluginDescriptor.getArtifactId() );
+                plugin.setVersion( pluginDescriptor.getVersion() );
+            }
 
-                    // if the mojo descriptor was found, determine aggregator status according to:
-                    // 1. whether the mojo declares itself an aggregator
-                    // 2. whether the mojo DOES NOT require a project to function (implicitly avoid reactor)
-                    if ( ( mojo != null ) && ( mojo.isAggregator() || !mojo.isProjectRequired() ) )
-                    {
-                        if ( ( currentSegment != null ) && !currentSegment.aggregate() )
-                        {
-                            segments.add( currentSegment );
-                            currentSegment = null;
-                        }
+            // 3. search plugins in the current POM
+            if ( plugin == null )
+            {
+                for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
+                {
+                    Plugin buildPlugin = (Plugin) i.next();
 
-                        if ( currentSegment == null )
-                        {
-                            currentSegment = new TaskSegment( true );
-                        }
+                    PluginDescriptor desc = loadPlugin( buildPlugin, project, session );
 
-                        currentSegment.add( task );
-                    }
-                    else
+                    if ( prefix.equals( desc.getGoalPrefix() ) )
                     {
-                        if ( ( currentSegment != null ) && currentSegment.aggregate() )
-                        {
-                            segments.add( currentSegment );
-                            currentSegment = null;
-                        }
-
-                        if ( currentSegment == null )
-                        {
-                            currentSegment = new TaskSegment();
-                        }
-
-                        currentSegment.add( task );
+                        plugin = buildPlugin;
                     }
                 }
             }
 
-            segments.add( currentSegment );
+            // 4. default to o.a.m.plugins and maven-<prefix>-plugin
+            if ( plugin == null )
+            {
+                plugin = new Plugin();
+                plugin.setGroupId( PluginDescriptor.getDefaultPluginGroupId() );
+                plugin.setArtifactId( PluginDescriptor.getDefaultPluginArtifactId( prefix ) );
+            }
         }
-        else
+        else if ( numTokens == 3 || numTokens == 4 )
         {
-            TaskSegment segment = new TaskSegment( false );
-            for ( Iterator i = tasks.iterator(); i.hasNext(); )
+            plugin = new Plugin();
+
+            plugin.setGroupId( tok.nextToken() );
+            plugin.setArtifactId( tok.nextToken() );
+
+            if ( numTokens == 4 )
             {
-                segment.add( (String) i.next() );
+                plugin.setVersion( tok.nextToken() );
             }
-            segments.add( segment );
+
+            goal = tok.nextToken();
+        }
+        else
+        {
+            String message = "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 LifecycleExecutionException( message );
         }
 
-        return segments;
-    }
+        if ( plugin.getVersion() == null )
+        {
+            for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
+            {
+                Plugin buildPlugin = (Plugin) i.next();
 
-    /**
-     * Retrieve the {@link MojoDescriptor} that corresponds to a given direct mojo
-     * invocation. This is used during the fail-fast method isTaskValid(..), and also
-     * during task-segmentation, to allow the lifecycle executor to determine whether
-     * the mojo is an aggregator.
-     */
-    private MojoDescriptor getMojoDescriptorForDirectInvocation( String task,
-                                                                 MavenSession session,
-                                                                 MavenProject project )
-        throws LifecycleSpecificationException, PluginLoaderException, LifecycleLoaderException,
-        InvalidPluginException
-    {
-        // we don't need to include report configuration here, since we're just looking for
-        // an @aggregator flag...
-        MojoBinding binding = mojoBindingFactory.parseMojoBinding(
-            task,
-            project,
-            session,
-            true );
+                if ( buildPlugin.getKey().equals( plugin.getKey() ) )
+                {
+                    plugin = buildPlugin;
+                    break;
+                }
+            }
 
-        PluginDescriptor descriptor = pluginManager.loadPlugin( binding, project, session );
+            project.injectPluginManagementInfo( plugin );
+        }
+
+        if ( pluginDescriptor == null )
+        {
+            pluginDescriptor = loadPlugin( plugin, project, session );
+        }
 
-        MojoDescriptor mojoDescriptor = descriptor.getMojo( binding.getGoal() );
+        // this has been simplified from the old code that injected the plugin management stuff, since
+        // pluginManagement injection is now handled by the project method.
+        project.addPlugin( plugin );
 
+        MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
         if ( mojoDescriptor == null )
         {
-            throw new InvalidPluginException( "Plugin: " + descriptor.getId() + " does not contain referenced mojo: " + binding.getGoal() );
+            if ( isOptionalMojo )
+            {
+                getLogger().info( "Skipping missing optional mojo: " + task );
+            }
+            else
+            {
+                throw new LifecycleExecutionException( "Required goal not found: " + task + " in " + pluginDescriptor.getId() );
+            }
         }
 
         return mojoDescriptor;
@@ -836,28 +1370,57 @@
         getLogger().info( "------------------------------------------------------------------------" );
     }
 
+    public Map getPhaseToLifecycleMap()
+        throws LifecycleExecutionException
+    {
+        if ( phaseToLifecycleMap == null )
+        {
+            phaseToLifecycleMap = new HashMap();
+
+            for ( Iterator i = lifecycles.iterator(); i.hasNext(); )
+            {
+                Lifecycle lifecycle = (Lifecycle) i.next();
+
+                for ( Iterator p = lifecycle.getPhases().iterator(); p.hasNext(); )
+                {
+                    String phase = (String) p.next();
+
+                    if ( phaseToLifecycleMap.containsKey( phase ) )
+                    {
+                        Lifecycle prevLifecycle = (Lifecycle) phaseToLifecycleMap.get( phase );
+                        throw new LifecycleExecutionException( "Phase '" + phase + "' is defined in more than one lifecycle: '" + lifecycle.getId() + "' and '" + prevLifecycle.getId() + "'" );
+                    }
+                    else
+                    {
+                        phaseToLifecycleMap.put( phase, lifecycle );
+                    }
+                }
+            }
+        }
+        return phaseToLifecycleMap;
+    }
+
     private static class TaskSegment
     {
         private boolean aggregate;
 
-        private final List tasks = new ArrayList();
+        private List tasks = new ArrayList();
 
         TaskSegment()
         {
 
         }
 
-        TaskSegment( final boolean aggregate )
+        TaskSegment( boolean aggregate )
         {
             this.aggregate = aggregate;
         }
 
-        @Override
         public String toString()
         {
             StringBuffer message = new StringBuffer();
 
-            message.append( "task-segment: [" );
+            message.append( " task-segment: [" );
 
             for ( Iterator it = tasks.iterator(); it.hasNext(); )
             {
@@ -886,7 +1449,7 @@
             return aggregate;
         }
 
-        void add( final String task )
+        void add( String task )
         {
             tasks.add( task );
         }
@@ -896,9 +1459,30 @@
             return tasks;
         }
     }
-    
-    public List getLifecycles()
+
+    private PluginDescriptor loadPlugin( Plugin plugin, MavenProject project, MavenSession session )
+        throws LifecycleExecutionException
+    {
+        try

[... 24 lines stripped ...]


Mime
View raw message