<commit_before>package org.apache.maven.lifecycle;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.execution.MavenExecutionResponse;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.extension.ExtensionManager;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.model.Extension;
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.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
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.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reactor.ReactorException;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id: DefaultLifecycleExecutor.java,v 1.16 2005/03/04 09:04:25
 *          jdcasey Exp $
 * @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)
 */
public class DefaultLifecycleExecutor
    extends AbstractLogEnabled
    implements LifecycleExecutor
{
    // ----------------------------------------------------------------------
    // Components
    // ----------------------------------------------------------------------

    private PluginManager pluginManager;

    private ExtensionManager extensionManager;

    private List lifecycles;

    private ArtifactHandlerManager artifactHandlerManager;

    private List defaultReports;

    private Map phaseToLifecycleMap;

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    /**
     * 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 MavenExecutionResponse execute( MavenSession session, ReactorManager rm, EventDispatcher dispatcher )
        throws LifecycleExecutionException
    {
        MavenProject rootProject = rm.getTopLevelProject();

        List goals = session.getGoals();

        if ( goals.isEmpty() && rootProject != null )
        {
            String goal = rootProject.getDefaultGoal();
            if ( goal != null )
            {
                goals = Collections.singletonList( goal );
            }
        }

        MavenExecutionResponse response = new MavenExecutionResponse();

        response.setStart( new Date() );

        try
        {
            if ( goals.isEmpty() )
            {
                throw new NoGoalsSpecifiedException( "You must specify at least one goal. Try 'install'" );
            }

            List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject );

            // TODO: probably don't want to do all this up front
            for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
            {
                MavenProject project = (MavenProject) i.next();

                for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
                {
                    Extension extension = (Extension) j.next();
                    extensionManager.addExtension( extension, project, session.getLocalRepository() );
                }

                Map handlers = findArtifactTypeHandlers( project, session.getSettings(), session.getLocalRepository() );
                artifactHandlerManager.addHandlers( handlers );
            }

            executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher, response );

            if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) && rm.hasBuildFailures() )
            {
                response.setException( new ReactorException( "One or more projects failed to build." ) );
            }
        }
        catch ( MojoExecutionException e )
        {
            response.setException( e );
        }
        catch ( ArtifactNotFoundException e )
        {
            response.setException( e );
        }
        catch ( ArtifactResolutionException e )
        {
            response.setException( e );
        }
        catch ( PlexusContainerException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( PluginManagerException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( PluginVersionResolutionException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( NoGoalsSpecifiedException e )
        {
            response.setException( e );
        }
        catch ( MojoFailureException e )
        {
            response.setException( e );
        }
        finally
        {
            response.setFinish( new Date() );
        }

        return response;
    }

    private void executeTaskSegments( List taskSegments, ReactorManager rm, MavenSession session,
                                      MavenProject rootProject, EventDispatcher dispatcher,
                                      MavenExecutionResponse response )
        throws ArtifactNotFoundException, MojoExecutionException, LifecycleExecutionException, MojoFailureException
    {
        for ( Iterator it = taskSegments.iterator(); it.hasNext(); )
        {
            TaskSegment segment = (TaskSegment) it.next();

            if ( segment.aggregate() )
            {
                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;

                    dispatcher.dispatchStart( event, rootProject.getId() + " ( " + segment + " )" );

                    try
                    {
                        // 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();

                            try
                            {
                                executeGoal( task, session, rootProject, response );
                            }
                            catch ( MojoExecutionException e )
                            {
                                // TODO: should this be removed?
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                            catch ( ArtifactResolutionException e )
                            {
                                // TODO: should this be removed?
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                            catch ( MojoFailureException e )
                            {
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                            catch ( ArtifactNotFoundException e )
                            {
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                        }

                        rm.registerBuildSuccess( rootProject );

                        dispatcher.dispatchEnd( event, rootProject.getId() + " ( " + segment + " )" );
                    }
                    catch ( LifecycleExecutionException e )
                    {
                        dispatcher.dispatchError( event, rootProject.getId() + " ( " + segment + " )", e );

                        throw e;
                    }
                }
                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
            {
                List sortedProjects = session.getSortedProjects();

                response.setExecutedMultipleProjects( true );

                // iterate over projects, and execute on each...
                for ( Iterator projectIterator = sortedProjects.iterator(); projectIterator.hasNext(); )
                {
                    MavenProject currentProject = (MavenProject) projectIterator.next();

                    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;

                        dispatcher.dispatchStart( event, currentProject.getId() + " ( " + segment + " )" );

                        try
                        {
                            for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
                            {
                                String task = (String) goalIterator.next();

                                try
                                {
                                    executeGoal( task, session, currentProject, response );
                                }
                                catch ( MojoExecutionException e )
                                {
                                    // TODO: should this be removed?
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                                catch ( ArtifactResolutionException e )
                                {
                                    // TODO: should this be removed?
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                                catch ( MojoFailureException e )
                                {
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                                catch ( ArtifactNotFoundException e )
                                {
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                            }

                            rm.registerBuildSuccess( currentProject );

                            dispatcher.dispatchEnd( event, currentProject.getId() + " ( " + segment + " )" );
                        }
                        catch ( LifecycleExecutionException e )
                        {
                            dispatcher.dispatchError( event, currentProject.getId() + " ( " + segment + " )", e );

                            throw e;
                        }
                    }
                    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 handleExecutionFailure( ReactorManager rm, MavenProject project, Exception e, String task )
        throws MojoExecutionException, MojoFailureException, ArtifactNotFoundException
    {
        if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
        {
            rm.registerBuildFailure( project, e, task );

            if ( e instanceof MojoExecutionException )
            {
                throw (MojoExecutionException) e;
            }
            if ( e instanceof MojoFailureException )
            {
                throw (MojoFailureException) e;
            }
            else if ( e instanceof ArtifactNotFoundException )
            {
                throw (ArtifactNotFoundException) e;
            }
            else
            {
                getLogger().error( "Attempt to register inappropriate build-failure Exception.", e );

                throw new IllegalArgumentException( "Inappropriate build-failure Exception: " + e );
            }
        }
        else if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) )
        {
            rm.registerBuildFailure( project, e, task );

            rm.blackList( project );
        }
        // FIXME: how about the other cases?
    }

    private List segmentTaskListByAggregationNeeds( List tasks, MavenSession session, MavenProject project )
        throws LifecycleExecutionException
    {
        List segments = new ArrayList();

        if ( project != null )
        {

            TaskSegment currentSegment = null;
            for ( Iterator it = tasks.iterator(); it.hasNext(); )
            {
                String task = (String) it.next();

                // 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 ) )
                {
                    if ( currentSegment != null && currentSegment.aggregate() )
                    {
                        segments.add( currentSegment );
                        currentSegment = null;
                    }

                    if ( currentSegment == null )
                    {
                        currentSegment = new TaskSegment();
                    }

                    currentSegment.add( task );
                }
                else
                {
                    MojoDescriptor mojo = null;
                    try
                    {
                        // definitely a CLI goal, can use prefix
                        mojo = getMojoDescriptor( task, session, project, task, true );
                    }
                    catch ( ArtifactResolutionException e )
                    {
                        getLogger().info(
                            "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." );
                        getLogger().debug( "", e );
                    }
                    catch ( ArtifactNotFoundException e )
                    {
                        getLogger().info(
                            "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." );
                        getLogger().debug( "", e );
                    }

                    // 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;
                        }

                        if ( currentSegment == null )
                        {
                            currentSegment = new TaskSegment( true );
                        }

                        currentSegment.add( task );
                    }
                    else
                    {
                        if ( currentSegment != null && currentSegment.aggregate() )
                        {
                            segments.add( currentSegment );
                            currentSegment = null;
                        }

                        if ( currentSegment == null )
                        {
                            currentSegment = new TaskSegment();
                        }

                        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, MavenExecutionResponse response )
        throws LifecycleExecutionException, ArtifactNotFoundException, MojoExecutionException,
        ArtifactResolutionException, MojoFailureException
    {
        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, session, lifecycleMappings, project, response, lifecycle );
        }
        else
        {
            executeStandaloneGoal( task, session, project, response );
        }
    }

    private void executeGoalWithLifecycle( String task, MavenSession session, Map lifecycleMappings,
                                           MavenProject project, MavenExecutionResponse response, Lifecycle lifecycle )
        throws ArtifactResolutionException, LifecycleExecutionException, MojoExecutionException, MojoFailureException,
        ArtifactNotFoundException
    {
        List goals = processGoalChain( task, lifecycleMappings, lifecycle );

        executeGoals( goals, session, project, response );
    }

    private void executeStandaloneGoal( String task, MavenSession session, MavenProject project,
                                        MavenExecutionResponse response )
        throws ArtifactResolutionException, LifecycleExecutionException, MojoExecutionException, MojoFailureException,
        ArtifactNotFoundException
    {
        // guaranteed to come from the CLI and not be part of a phase<commit_msg>PR: MNG-512 skip project if no goals are bound<commit_after>package org.apache.maven.lifecycle;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.execution.MavenExecutionResponse;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.extension.ExtensionManager;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.model.Extension;
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.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
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.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reactor.ReactorException;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id: DefaultLifecycleExecutor.java,v 1.16 2005/03/04 09:04:25
 *          jdcasey Exp $
 * @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)
 */
public class DefaultLifecycleExecutor
    extends AbstractLogEnabled
    implements LifecycleExecutor
{
    // ----------------------------------------------------------------------
    // Components
    // ----------------------------------------------------------------------

    private PluginManager pluginManager;

    private ExtensionManager extensionManager;

    private List lifecycles;

    private ArtifactHandlerManager artifactHandlerManager;

    private List defaultReports;

    private Map phaseToLifecycleMap;

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    /**
     * 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 MavenExecutionResponse execute( MavenSession session, ReactorManager rm, EventDispatcher dispatcher )
        throws LifecycleExecutionException
    {
        MavenProject rootProject = rm.getTopLevelProject();

        List goals = session.getGoals();

        if ( goals.isEmpty() && rootProject != null )
        {
            String goal = rootProject.getDefaultGoal();
            if ( goal != null )
            {
                goals = Collections.singletonList( goal );
            }
        }

        MavenExecutionResponse response = new MavenExecutionResponse();

        response.setStart( new Date() );

        try
        {
            if ( goals.isEmpty() )
            {
                throw new NoGoalsSpecifiedException( "You must specify at least one goal. Try 'install'" );
            }

            List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject );

            // TODO: probably don't want to do all this up front
            for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); )
            {
                MavenProject project = (MavenProject) i.next();

                for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
                {
                    Extension extension = (Extension) j.next();
                    extensionManager.addExtension( extension, project, session.getLocalRepository() );
                }

                Map handlers = findArtifactTypeHandlers( project, session.getSettings(), session.getLocalRepository() );
                artifactHandlerManager.addHandlers( handlers );
            }

            executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher, response );

            if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) && rm.hasBuildFailures() )
            {
                response.setException( new ReactorException( "One or more projects failed to build." ) );
            }
        }
        catch ( MojoExecutionException e )
        {
            response.setException( e );
        }
        catch ( ArtifactNotFoundException e )
        {
            response.setException( e );
        }
        catch ( ArtifactResolutionException e )
        {
            response.setException( e );
        }
        catch ( PlexusContainerException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( PluginManagerException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( PluginVersionResolutionException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw new LifecycleExecutionException( "Unable to initialise extensions", e );
        }
        catch ( NoGoalsSpecifiedException e )
        {
            response.setException( e );
        }
        catch ( MojoFailureException e )
        {
            response.setException( e );
        }
        finally
        {
            response.setFinish( new Date() );
        }

        return response;
    }

    private void executeTaskSegments( List taskSegments, ReactorManager rm, MavenSession session,
                                      MavenProject rootProject, EventDispatcher dispatcher,
                                      MavenExecutionResponse response )
        throws ArtifactNotFoundException, MojoExecutionException, LifecycleExecutionException, MojoFailureException
    {
        for ( Iterator it = taskSegments.iterator(); it.hasNext(); )
        {
            TaskSegment segment = (TaskSegment) it.next();

            if ( segment.aggregate() )
            {
                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;

                    dispatcher.dispatchStart( event, rootProject.getId() + " ( " + segment + " )" );

                    try
                    {
                        // 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();

                            try
                            {
                                executeGoal( task, session, rootProject, response );
                            }
                            catch ( MojoExecutionException e )
                            {
                                // TODO: should this be removed?
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                            catch ( ArtifactResolutionException e )
                            {
                                // TODO: should this be removed?
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                            catch ( MojoFailureException e )
                            {
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                            catch ( ArtifactNotFoundException e )
                            {
                                handleExecutionFailure( rm, rootProject, e, task );
                            }
                        }

                        rm.registerBuildSuccess( rootProject );

                        dispatcher.dispatchEnd( event, rootProject.getId() + " ( " + segment + " )" );
                    }
                    catch ( LifecycleExecutionException e )
                    {
                        dispatcher.dispatchError( event, rootProject.getId() + " ( " + segment + " )", e );

                        throw e;
                    }
                }
                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
            {
                List sortedProjects = session.getSortedProjects();

                response.setExecutedMultipleProjects( true );

                // iterate over projects, and execute on each...
                for ( Iterator projectIterator = sortedProjects.iterator(); projectIterator.hasNext(); )
                {
                    MavenProject currentProject = (MavenProject) projectIterator.next();

                    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;

                        dispatcher.dispatchStart( event, currentProject.getId() + " ( " + segment + " )" );

                        try
                        {
                            for ( Iterator goalIterator = segment.getTasks().iterator(); goalIterator.hasNext(); )
                            {
                                String task = (String) goalIterator.next();

                                try
                                {
                                    executeGoal( task, session, currentProject, response );
                                }
                                catch ( MojoExecutionException e )
                                {
                                    // TODO: should this be removed?
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                                catch ( ArtifactResolutionException e )
                                {
                                    // TODO: should this be removed?
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                                catch ( MojoFailureException e )
                                {
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                                catch ( ArtifactNotFoundException e )
                                {
                                    handleExecutionFailure( rm, currentProject, e, task );
                                }
                            }

                            rm.registerBuildSuccess( currentProject );

                            dispatcher.dispatchEnd( event, currentProject.getId() + " ( " + segment + " )" );
                        }
                        catch ( LifecycleExecutionException e )
                        {
                            dispatcher.dispatchError( event, currentProject.getId() + " ( " + segment + " )", e );

                            throw e;
                        }
                    }
                    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 handleExecutionFailure( ReactorManager rm, MavenProject project, Exception e, String task )
        throws MojoExecutionException, MojoFailureException, ArtifactNotFoundException
    {
        if ( ReactorManager.FAIL_FAST.equals( rm.getFailureBehavior() ) )
        {
            rm.registerBuildFailure( project, e, task );

            if ( e instanceof MojoExecutionException )
            {
                throw (MojoExecutionException) e;
            }
            if ( e instanceof MojoFailureException )
            {
                throw (MojoFailureException) e;
            }
            else if ( e instanceof ArtifactNotFoundException )
            {
                throw (ArtifactNotFoundException) e;
            }
            else
            {
                getLogger().error( "Attempt to register inappropriate build-failure Exception.", e );

                throw new IllegalArgumentException( "Inappropriate build-failure Exception: " + e );
            }
        }
        else if ( ReactorManager.FAIL_AT_END.equals( rm.getFailureBehavior() ) )
        {
            rm.registerBuildFailure( project, e, task );

            rm.blackList( project );
        }
        // FIXME: how about the other cases?
    }

    private List segmentTaskListByAggregationNeeds( List tasks, MavenSession session, MavenProject project )
        throws LifecycleExecutionException
    {
        List segments = new ArrayList();

        if ( project != null )
        {

            TaskSegment currentSegment = null;
            for ( Iterator it = tasks.iterator(); it.hasNext(); )
            {
                String task = (String) it.next();

                // 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 ) )
                {
                    if ( currentSegment != null && currentSegment.aggregate() )
                    {
                        segments.add( currentSegment );
                        currentSegment = null;
                    }

                    if ( currentSegment == null )
                    {
                        currentSegment = new TaskSegment();
                    }

                    currentSegment.add( task );
                }
                else
                {
                    MojoDescriptor mojo = null;
                    try
                    {
                        // definitely a CLI goal, can use prefix
                        mojo = getMojoDescriptor( task, session, project, task, true );
                    }
                    catch ( ArtifactResolutionException e )
                    {
                        getLogger().info(
                            "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." );
                        getLogger().debug( "", e );
                    }
                    catch ( ArtifactNotFoundException e )
                    {
                        getLogger().info(
                            "Cannot find mojo descriptor for: \'" + task + "\' - Treating as non-aggregator." );
                        getLogger().debug( "", e );
                    }

                    // 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;
                        }

                        if ( currentSegment == null )
                        {
                            currentSegment = new TaskSegment( true );
                        }

                        currentSegment.add( task );
                    }
                    else
                    {
                        if ( currentSegment != null && currentSegment.aggregate() )
                        {
                            segments.add( currentSegment );
                            currentSegment = null;
                        }

                        if ( currentSegment == null )
                        {
                            currentSegment = new TaskSegment();
                        }

                        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, MavenExecutionResponse response )
        throws LifecycleExecutionException, ArtifactNotFoundException, MojoExecutionException,
        ArtifactResolutionException, MojoFailureException
    {
        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, session, lifecycleMappings, project, response, lifecycle );
        }
        else
        {
            executeStandaloneGoal( task, session, project, response );
        }
    }

    private void executeGoalWithLifecycle( String task, MavenSession session, Map lifecycleMappings,
                                           MavenProject project, MavenExecutionResponse response, Lifecycle lifecycle )
        throws ArtifactResolutionException, LifecycleExecutionException, MojoExecutionException, MojoFailureException,
        ArtifactNotFoundException
    {
        List goals = processGoalChain( task, lifecycleMappings, lifecycle );

        if ( !goals.isEmpty() )
        {
            executeGoals( goals, session, project, response );
        }
        else
        {
            getLogger().info( "No goals needed for project - skipping" );
        }
    }

    private void executeStandaloneGoal( String task, MavenSession session, MavenProject project,
                                        MavenExecutionResponse response )
        throws ArtifactResolutionException, LifecycleExecutionException, MojoExecutionException, MojoFailureException,
        ArtifactNotFoundException
    {
        // guaranteed to come from the CLI and not be part of a phase
{'fraction_non_alphanumeric': 0.09091120193200818, 'fraction_numerical': 0.00155582389002415, 'mean_word_length': 1.377574118036769, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4673459', 'n_tokens_mistral': 9915, 'n_tokens_neox': 9205, 'n_words': 2375}