blob: d9b13ebc48e792c5acba5304fb0c413ae4766c60 [file] [log] [blame]
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.
*/
import org.apache.maven.BuildFailureException;
import org.apache.maven.ConfigurationInterpolationException;
import org.apache.maven.ConfigurationInterpolator;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
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.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.InvalidPluginException;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.PluginConfigurationException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
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.PluginVersionNotFoundException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.project.interpolation.ModelInterpolationException;
import org.apache.maven.project.interpolation.ModelInterpolator;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.StringUtils;
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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.StringTokenizer;
/**
* @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @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)
*/
public class DefaultLifecycleExecutor
extends AbstractLogEnabled
implements LifecycleExecutor, Initializable, Contextualizable
{
// ----------------------------------------------------------------------
// Components
// ----------------------------------------------------------------------
private PluginManager pluginManager;
private ExtensionManager extensionManager;
private List lifecycles;
private ArtifactHandlerManager artifactHandlerManager;
private List defaultReports;
private Map phaseToLifecycleMap;
private MavenProjectBuilder mavenProjectBuilder;
private ModelInterpolator modelInterpolator;
private ConfigurationInterpolator configInterpolator;
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
/**
* 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( final MavenSession session, final ReactorManager rm, final 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 = rm.getTopLevelProject();
List goals = session.getGoals();
if ( goals.isEmpty() && rootProject != null )
{
String goal = rootProject.getDefaultGoal();
if ( goal != null )
{
goals = Collections.singletonList( goal );
}
}
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 BuildFailureException( buffer.toString() );
}
List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject );
// TODO: probably don't want to do all this up front
findExtensions( session );
executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher );
}
private void findExtensions( final MavenSession session )
throws LifecycleExecutionException
{
// TODO: MNG-4081. What about extensions within the current reactor??
Map<String, ArtifactHandler> handlers = new HashMap<String, ArtifactHandler>();
for ( MavenProject project : session.getSortedProjects() )
{
for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
{
Extension extension = (Extension) j.next();
try
{
getLogger().debug( "Adding extension: " + extension );
extensionManager.addExtension( extension, project, session.getProjectBuilderConfiguration() );
}
catch ( PlexusContainerException e )
{
throw new LifecycleExecutionException( "Unable to initialise extensions", e );
}
catch ( ArtifactResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
}
}
extensionManager.registerWagons();
handlers.putAll( extensionManager.getArtifactTypeHandlers() );
for ( MavenProject project : session.getSortedProjects() )
{
try
{
handlers.putAll( findArtifactTypeHandlersInPlugins( project, session ) );
// shudder...
for ( ArtifactHandler handler : handlers.values() )
{
if ( project.getPackaging().equals( handler.getPackaging() ) )
{
project.getArtifact().setArtifactHandler( handler );
// NOTE: Adding this (maven 2.2.1) to short-circuit things. This means first match is used, NOT LAST.
break;
}
}
}
catch ( PluginNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
}
artifactHandlerManager.addHandlers( handlers );
}
private void executeTaskSegments( final List taskSegments, final ReactorManager rm, final MavenSession session,
final MavenProject rootProject, final EventDispatcher dispatcher )
throws LifecycleExecutionException, BuildFailureException
{
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;
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
{
List sortedProjects = session.getSortedProjects();
// 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;
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 executeGoalAndHandleFailures( final String task, final MavenSession session, final MavenProject project,
final EventDispatcher dispatcher, final String event, final ReactorManager rm,
final long buildStartTime, final String target )
throws BuildFailureException, LifecycleExecutionException
{
try
{
executeGoal( task, session, project );
}
catch ( LifecycleExecutionException e )
{
dispatcher.dispatchError( event, target, e );
if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
{
throw e;
}
}
catch ( BuildFailureException e )
{
dispatcher.dispatchError( event, target, e );
if ( handleExecutionFailure( rm, project, e, task, buildStartTime ) )
{
throw e;
}
}
}
private boolean handleExecutionFailure( final ReactorManager rm, final MavenProject project, final Exception e, final String task,
final long buildStartTime )
{
rm.registerBuildFailure( project, e, task, System.currentTimeMillis() - buildStartTime );
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;
}
private List segmentTaskListByAggregationNeeds( final List tasks, final MavenSession session, final MavenProject project )
throws LifecycleExecutionException, BuildFailureException
{
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, false );
}
catch ( PluginNotFoundException e )
{
// TODO: shouldn't hit this, investigate using the same resolution logic as otheres for plugins in the reactor
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( final String task, final MavenSession session, final 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( final String task, final Stack forkEntryPoints, final MavenSession session,
final Map lifecycleMappings, final MavenProject project, final 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( final String task, final Stack forkEntryPoints, final MavenSession session, final 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, MojoExecution.CLI_EXECUTION_ID ) ),
forkEntryPoints, session, project );
}
private void executeGoals( final List goals, final Stack forkEntryPoints, final MavenSession session, final MavenProject project )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
{
for ( Iterator i = goals.iterator(); i.hasNext(); )
{
MojoExecution mojoExecution = (MojoExecution) i.next();
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
PlexusConfiguration configuration = mojoDescriptor.getMojoConfiguration();
boolean usesReactorProjects = mojoDescriptor.isAggregator() || usesSessionOrReactorProjects( configuration );
if ( usesReactorProjects )
{
calculateAllConcreteStates( session );
}
else
{
calculateConcreteState( project, session, true );
}
calculateConcreteConfiguration( mojoExecution, project, session );
List reportExecutions = null;
if ( mojoDescriptor.isRequiresReports() )
{
reportExecutions = getReportExecutions( project, forkEntryPoints, mojoExecution, session );
}
boolean hasFork = false;
if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
{
hasFork = true;
}
else if ( reportExecutions != null )
{
for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
{
MojoExecution reportExecution = (MojoExecution) it.next();
MojoDescriptor reportDescriptor = reportExecution.getMojoDescriptor();
if ( reportDescriptor.getExecutePhase() != null || reportDescriptor.getExecuteGoal() != null )
{
hasFork = true;
}
}
}
if ( hasFork )
{
// NOTE: This must always happen, regardless of treatment of reactorProjects below, because
// if we're in a forked execution right now, the current project will itself be an execution project of
// something in the reactorProjects list, and won't have a next-stage executionProject created
// for it otherwise, which leaves the project == null for the upcoming forked execution.
createExecutionProject( project, session, true );
if ( usesReactorProjects )
{
List reactorProjects = session.getSortedProjects();
for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
{
MavenProject reactorProject = (MavenProject) it.next();
createExecutionProject( reactorProject, session, false );
}
}
}
if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
{
forkEntryPoints.push( mojoDescriptor );
forkLifecycle( mojoDescriptor, forkEntryPoints, session, project, mojoExecution.getExecutionId() );
forkEntryPoints.pop();
}
if ( mojoDescriptor.isRequiresReports() )
{
List reports = getReports( reportExecutions, project, 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, forkedExecution.getExecutionId() );
forkEntryPoints.pop();
}
}
}
if ( hasFork )
{
// NOTE: This must always happen, regardless of treatment of reactorProjects below, because
// if we're in a forked execution right now, the current project will itself be an execution project of
// something in the reactorProjects list, and may not have had its own executionProject instance reset to
// a concrete state again after the previous forked executions.
calculateConcreteState( project.getExecutionProject(), session, true );
// FIXME: Would be nice to find a way to cause the execution project to stay in a concrete state...
// TODO: Test this! It should be fixed, but I don't want to destabilize until I have the issue I'm working on fixed.
if ( usesReactorProjects )
{
calculateAllConcreteStates( session );
List reactorProjects = session.getSortedProjects();
for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
{
MavenProject reactorProject = (MavenProject) it.next();
calculateConcreteState( reactorProject.getExecutionProject(), session, false );
}
}
}
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 ( MojoExecutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( PluginConfigurationException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
}
}
private void createExecutionProject( final MavenProject project, final MavenSession session, final boolean processProjectReferences )
throws LifecycleExecutionException
{
MavenProject executionProject = new MavenProject( project );
calculateConcreteState( executionProject, session, processProjectReferences );
project.setExecutionProject( executionProject );
}
private boolean usesSessionOrReactorProjects( final PlexusConfiguration configuration )
{
String value = configuration != null ? String.valueOf( configuration ) : null;
if ( value != null )
{
if ( value.indexOf( "${session" ) > -1 || value.indexOf( "${reactorProjects}" ) > -1 )
{
return true;
}
}
return false;
}
private void calculateConcreteConfiguration( final MojoExecution mojoExecution, final MavenProject project, final MavenSession session )
throws LifecycleExecutionException
{
if ( mojoExecution.getConfiguration() == null )
{
return;
}
try
{
mojoExecution.setConfiguration( (Xpp3Dom) configInterpolator.interpolate(
mojoExecution.getConfiguration(),
project,
session.getProjectBuilderConfiguration() ) );
}
catch ( ConfigurationInterpolationException e )
{
throw new LifecycleExecutionException( "Error interpolating configuration for: '" + mojoExecution.getMojoDescriptor().getRoleHint() +
"' (execution: '" + mojoExecution.getExecutionId() + "')", e );
}
}
private void calculateAllConcreteStates( final MavenSession session )
throws LifecycleExecutionException
{
List projects = session.getSortedProjects();
if ( projects != null )
{
for ( Iterator it = projects.iterator(); it.hasNext(); )
{
calculateConcreteState( (MavenProject) it.next(), session, false );
}
}
}
private void calculateConcreteState( final MavenProject project, final MavenSession session, final boolean processReferences )
throws LifecycleExecutionException
{
if ( mavenProjectBuilder != null && project != null )
{
try
{
mavenProjectBuilder.calculateConcreteState( project, session.getProjectBuilderConfiguration(), processReferences );
}
catch ( ModelInterpolationException e )
{
throw new LifecycleExecutionException( "Failed to calculate concrete state for project: " + project,
e );
}
}
}
// private void restoreAllDynamicStates( MavenSession session )
// throws LifecycleExecutionException
// {
// List reactorProjects = session.getSortedProjects();
// if ( reactorProjects != null )
// {
// for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
// {
// MavenProject project = (MavenProject) it.next();
// restoreDynamicState( project, session, false );
// }
// }
// }
//
// private void restoreDynamicState( MavenProject project, MavenSession session, boolean processReferences )
// throws LifecycleExecutionException
// {
// try
// {
// mavenProjectBuilder.restoreDynamicState( project, session.getProjectBuilderConfiguration(), processReferences );
// }
// catch ( ModelInterpolationException e )
// {
// throw new LifecycleExecutionException( "Failed to restore dynamic state for project: " + project, e );
// }
// }
private List getReportExecutions( final MavenProject project, final Stack forkEntryPoints, final MojoExecution mojoExecution, final 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 ) )
{
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();
List reportSets = reportPlugin.getReportSets();
if ( reportSets == null || reportSets.isEmpty() )
{
reports.addAll( getReportExecutions( reportPlugin, forkEntryPoints, null, project, session, mojoExecution ) );
}
else
{
for ( Iterator j = reportSets.iterator(); j.hasNext(); )
{
ReportSet reportSet = (ReportSet) j.next();
reports.addAll( getReportExecutions( reportPlugin, forkEntryPoints, reportSet, project, session, mojoExecution ) );
}
}
}
}
return reports;
}
private List getReportExecutions( final ReportPlugin reportPlugin,
final Stack forkEntryPoints,
final ReportSet reportSet,
final MavenProject project,
final MavenSession session,
final MojoExecution mojoExecution )
throws LifecycleExecutionException, PluginNotFoundException
{
PluginDescriptor pluginDescriptor = verifyReportPlugin( 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() ) )
{
String id = null;
if ( reportSet != null )
{
id = reportSet.getId();
}
else
{
id = mojoExecution.getExecutionId();
}
MojoExecution reportExecution;
if ( id.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
{
reportExecution = new MojoExecution( mojoDescriptor );
}
else
{
reportExecution = new MojoExecution( mojoDescriptor, id );
}
reports.add( reportExecution );
}
}
return reports;
}
private List getReports( final List reportExecutions, final MavenProject project, final MojoExecution mojoExecution, final MavenSession session )
throws LifecycleExecutionException
{
List reports = new ArrayList();
for ( Iterator it = reportExecutions.iterator(); it.hasNext(); )
{
MojoExecution reportExecution = (MojoExecution) it.next();
PluginDescriptor pluginDescriptor = reportExecution.getMojoDescriptor().getPluginDescriptor();
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 '" + pluginDescriptor.getId() + "': " + e.getMessage(), e );
}
catch ( PluginConfigurationException e )
{
throw new LifecycleExecutionException(
"Error getting reports from the plugin '" + pluginDescriptor.getId() + "'", e );
}
catch ( ArtifactNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
}
return reports;
}
private void forkLifecycle( final MojoDescriptor mojoDescriptor, final Stack ancestorLifecycleForkers, final MavenSession session,
final MavenProject project, final String executionId )
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();
line();
getLogger().info( "Building " + reactorProject.getName() );
line();
forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, reactorProject, executionId );
}
}
else
{
forkProjectLifecycle( mojoDescriptor, ancestorLifecycleForkers, session, project, executionId );
}
}
private void forkProjectLifecycle( final MojoDescriptor mojoDescriptor, final Stack forkEntryPoints, final MavenSession session,
MavenProject project, final String executionId )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
{
project = project.getExecutionProject();
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 );
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 );
}
if ( lifecycleOverlay == null )
{
throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
}
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();
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 = verifyPlugin( plugin, project, session );
if ( lifecyclePluginDescriptor == null )
{
throw new LifecycleExecutionException(
"Unable to find plugin " + groupId + ":" + artifactId );
}
}
else
{
lifecyclePluginDescriptor = pluginDescriptor;
lifecycleGoal = goal;
}
Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
// NOTE: This seems to be duplicated below. Why??
if ( phase.getConfiguration() != null )
{
configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ),
configuration );
}
MojoDescriptor desc = getMojoDescriptor( lifecyclePluginDescriptor, lifecycleGoal );
MojoExecution mojoExecution;
if ( executionId.startsWith( MojoExecution.DEFAULT_EXEC_ID_PREFIX ) )
{
mojoExecution = new MojoExecution( desc, configuration );
}
else
{
mojoExecution = new MojoExecution( desc, configuration, executionId );
}
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 );
}
if ( targetPhase != null )
{
Lifecycle lifecycle = getLifecycleForPhase( targetPhase );
executeGoalWithLifecycle( targetPhase, forkEntryPoints, session, lifecycleMappings, project, lifecycle );
}
else
{
String goal = mojoDescriptor.getExecuteGoal();
MojoDescriptor desc = getMojoDescriptor( pluginDescriptor, goal );
executeGoals( Collections.singletonList( new MojoExecution( desc, goal ) ), forkEntryPoints, session, project );
}
}
private Lifecycle getLifecycleForPhase( final String phase )
throws BuildFailureException, LifecycleExecutionException
{
Lifecycle lifecycle = (Lifecycle) getPhaseToLifecycleMap().get( phase );
if ( lifecycle == null )
{
throw new BuildFailureException( "Unable to find lifecycle for phase '" + phase + "'" );
}
return lifecycle;
}
private MojoDescriptor getMojoDescriptor( final PluginDescriptor pluginDescriptor, final String goal )
throws LifecycleExecutionException
{
MojoDescriptor desc = pluginDescriptor.getMojo( goal );
if ( desc == null )
{
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 desc;
}
private void removeFromLifecycle( final Stack lifecycleForkers, final Map lifecycleMappings )
{
for ( Iterator lifecycleIterator = lifecycleMappings.values().iterator(); lifecycleIterator.hasNext(); )
{
List tasks = (List) lifecycleIterator.next();
for ( Iterator taskIterator = tasks.iterator(); taskIterator.hasNext(); )
{
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( final MavenSession session, final String selectedPhase, final MavenProject project,
final 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( final MavenSession session, final String selectedPhase, final MavenProject project,
final Lifecycle lifecycle )
throws LifecycleExecutionException, BuildFailureException, PluginNotFoundException
{
Map mappings = findMappingsForLifecycle( session, project, lifecycle );
List optionalMojos = findOptionalMojosForLifecycle( session, project, lifecycle );
Map lifecycleMappings = new HashMap();
for ( Iterator i = lifecycle.getPhases().iterator(); i.hasNext(); )
{
String phase = (String) i.next();
String phaseTasks = (String) mappings.get( phase );
if ( phaseTasks != null )
{
for ( StringTokenizer tok = new StringTokenizer( phaseTasks, "," ); tok.hasMoreTokens(); )
{
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() );
}
}
if ( phase.equals( selectedPhase ) )
{
break;
}
}
return lifecycleMappings;
}
private Map findMappingsForLifecycle( final MavenSession session, final MavenProject project, final Lifecycle lifecycle )
throws LifecycleExecutionException, PluginNotFoundException
{
String packaging = project.getPackaging();
Map mappings = null;
LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session );
if ( m != null )
{
mappings = m.getPhases( lifecycle.getId() );
}
Map defaultMappings = lifecycle.getDefaultPhases();
if ( mappings == null )
{
try
{
m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
mappings = m.getPhases( lifecycle.getId() );
}
catch ( ComponentLookupException e )
{
if ( defaultMappings == null )
{
throw new LifecycleExecutionException(
"Cannot find lifecycle mapping for packaging: \'" + packaging + "\'.", e );
}
}
}
if ( mappings == null )
{
if ( defaultMappings == null )
{
throw new LifecycleExecutionException(
"Cannot find lifecycle mapping for packaging: \'" + packaging + "\', and there is no default" );
}
else
{
mappings = defaultMappings;
}
}
return mappings;
}
private List findOptionalMojosForLifecycle( final MavenSession session, final MavenProject project, final Lifecycle lifecycle )
throws LifecycleExecutionException, PluginNotFoundException
{
String packaging = project.getPackaging();
List optionalMojos = null;
LifecycleMapping m = (LifecycleMapping) findExtension( project, LifecycleMapping.ROLE, packaging, session );
if ( m != null )
{
optionalMojos = m.getOptionalMojos( lifecycle.getId() );
}
if ( optionalMojos == null )
{
try
{
m = (LifecycleMapping) session.lookup( LifecycleMapping.ROLE, packaging );
optionalMojos = m.getOptionalMojos( lifecycle.getId() );
}
catch ( ComponentLookupException e )
{
getLogger().debug( "Error looking up lifecycle mapping to retrieve optional mojos. Lifecycle ID: " +
lifecycle.getId() + ". Error: " + e.getMessage(), e );
}
}
if ( optionalMojos == null )
{
optionalMojos = Collections.EMPTY_LIST;
}
return optionalMojos;
}
private Object findExtension( final MavenProject project, final String role, final String roleHint, final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException
{
Object pluginComponent = null;
for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext() && pluginComponent == null; )
{
Plugin plugin = (Plugin) i.next();
if ( plugin.isExtensions() )
{
loadPluginFully( plugin, project, session );
// TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly
try
{
pluginComponent = pluginManager.getPluginComponent( plugin, role, roleHint );
}
catch ( ComponentLookupException e )
{
getLogger().debug( "Unable to find the lifecycle component in the extension", e );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException(
"Error getting extensions from the plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
}
}
}
return pluginComponent;
}
/**
* @todo Not particularly happy about this. Would like WagonManager and ArtifactTypeHandlerManager to be able to
* lookup directly, or have them passed in
*/
private Map<String, ArtifactHandler> findArtifactTypeHandlersInPlugins( final MavenProject project, final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException
{
Map<String, ArtifactHandler> map = new HashMap<String, ArtifactHandler>();
for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
{
Plugin plugin = (Plugin) i.next();
if ( plugin.isExtensions() )
{
loadPluginFully( plugin, project, session );
// TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly
try
{
Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE );
map.putAll( components );
}
catch ( ComponentLookupException e )
{
getLogger().debug( "Unable to find the lifecycle component in the extension", e );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException( "Error looking up available components from plugin '" +
plugin.getKey() + "': " + e.getMessage(), e );
}
}
}
return map;
}
/**
* 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
*/
private void bindPluginToLifecycle( final Plugin plugin, final MavenSession session, final Map phaseMap, final MavenProject project )
throws LifecycleExecutionException, PluginNotFoundException
{
Settings settings = session.getSettings();
PluginDescriptor pluginDescriptor =
verifyPlugin( 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() )
{
if ( plugin.getGoals() != null )
{
getLogger().error(
"Plugin contains a <goals/> section: this is IGNORED - please use <executions/> instead." );
}
List executions = plugin.getExecutions();
if ( executions != null )
{
for ( Iterator it = executions.iterator(); it.hasNext(); )
{
PluginExecution execution = (PluginExecution) it.next();
bindExecutionToLifecycle( pluginDescriptor, phaseMap, execution, settings );
}
}
}
}
}
private PluginDescriptor verifyPlugin( final Plugin plugin, final MavenProject project, final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException
{
PluginDescriptor pluginDescriptor;
try
{
// TODO: MNG-4081...need to flush this plugin once we look at it, to avoid using an external
// version of a plugin when a newer version will be created in the current reactor...
pluginDescriptor = pluginManager.loadPluginDescriptor( plugin, project, session );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException(
"Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
}
catch ( PluginVersionResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( InvalidPluginException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( PluginVersionNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
return pluginDescriptor;
}
private PluginDescriptor loadPluginFully( final Plugin plugin, final MavenProject project, final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException
{
PluginDescriptor pluginDescriptor;
try
{
// TODO: MNG-4081...need to flush this plugin once we look at it, to avoid using an external
// version of a plugin when a newer version will be created in the current reactor...
pluginDescriptor = pluginManager.loadPluginFully( plugin, project, session );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException(
"Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), e );
}
catch ( PluginVersionResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( InvalidPluginException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( PluginVersionNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
return pluginDescriptor;
}
private PluginDescriptor verifyReportPlugin( final ReportPlugin plugin, final MavenProject project, final MavenSession session )
throws LifecycleExecutionException, PluginNotFoundException
{
PluginDescriptor pluginDescriptor;
try
{
pluginDescriptor = pluginManager.verifyReportPlugin( plugin, project, session );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException(
"Internal error in the plugin manager getting report '" + plugin.getKey() + "': " + e.getMessage(), e );
}
catch ( PluginVersionResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( InvalidPluginException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( ArtifactResolutionException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
catch ( PluginVersionNotFoundException e )
{
throw new LifecycleExecutionException( e.getMessage(), e );
}
return pluginDescriptor;
}
private void bindExecutionToLifecycle( final PluginDescriptor pluginDescriptor, final Map phaseMap, final PluginExecution execution,
final Settings settings )
throws LifecycleExecutionException
{
for ( Iterator i = execution.getGoals().iterator(); i.hasNext(); )
{
String goal = (String) i.next();
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
if ( mojoDescriptor == null )
{
throw new LifecycleExecutionException(
"'" + goal + "' was specified in an execution, but not found in the plugin" );
}
// We have to check to see that the inheritance rules have been applied before binding this mojo.
if ( execution.isInheritanceApplied() || mojoDescriptor.isInheritedByDefault() )
{
MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
String phase = execution.getPhase();
if ( phase == null )
{
// if the phase was not in the configuration, use the phase in the descriptor
phase = mojoDescriptor.getPhase();
}
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)." );
}
addToLifecycleMappings( phaseMap, phase, mojoExecution, settings );
}
}
}
}
private void addToLifecycleMappings( final Map lifecycleMappings, final String phase, final MojoExecution mojoExecution,
final Settings settings )
{
List goals = (List) lifecycleMappings.get( phase );
if ( goals == null )
{
goals = new ArrayList();
lifecycleMappings.put( phase, goals );
}
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( settings.isOffline() && mojoDescriptor.isOnlineRequired() )
{
String goal = mojoDescriptor.getGoal();
getLogger().warn( goal + " requires online mode, but maven is currently offline. Disabling " + goal + "." );
}
else
{
goals.add( mojoExecution );
}
}
private List processGoalChain( final String task, final Map phaseMap, final Lifecycle lifecycle )
{
List goals = new ArrayList();
// only execute up to the given phase
int index = lifecycle.getPhases().indexOf( task );
for ( int i = 0; i <= index; i++ )
{
String p = (String) lifecycle.getPhases().get( i );
List phaseGoals = (List) phaseMap.get( p );
if ( phaseGoals != null )
{
goals.addAll( phaseGoals );
}
}
return goals;
}
private MojoDescriptor getMojoDescriptor( final String task, final MavenSession session, final MavenProject project,
final String invokedVia, final boolean canUsePrefix, final boolean isOptionalMojo )
throws BuildFailureException, LifecycleExecutionException, PluginNotFoundException
{
String goal;
Plugin plugin = null;
PluginDescriptor pluginDescriptor = null;
try
{
StringTokenizer tok = new StringTokenizer( task, ":" );
int numTokens = tok.countTokens();
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 );
}
String prefix = tok.nextToken();
goal = tok.nextToken();
// Steps for retrieving the plugin model instance:
// 1. request directly from the plugin collector by prefix
pluginDescriptor = pluginManager.getPluginDescriptorForPrefix( prefix );
if ( pluginDescriptor != null )
{
plugin = new Plugin();
plugin.setGroupId( pluginDescriptor.getGroupId() );
plugin.setArtifactId( pluginDescriptor.getArtifactId() );
plugin.setVersion( pluginDescriptor.getVersion() );
}
// 2. search plugins in the current POM
if ( plugin == null )
{
for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
{
Plugin buildPlugin = (Plugin) i.next();
PluginDescriptor desc =
verifyPlugin( buildPlugin, project, session );
if ( prefix.equals( desc.getGoalPrefix() ) )
{
plugin = buildPlugin;
pluginDescriptor = desc;
break;
}
}
}
// 3. look in the repository via search groups
if ( plugin == null )
{
plugin = pluginManager.getPluginDefinitionForPrefix( prefix, session, project );
}
// 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 if ( numTokens == 3 || numTokens == 4 )
{
plugin = new Plugin();
plugin.setGroupId( tok.nextToken() );
plugin.setArtifactId( tok.nextToken() );
if ( numTokens == 4 )
{
plugin.setVersion( tok.nextToken() );
}
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 BuildFailureException( message );
}
if ( plugin.getVersion() == null )
{
for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); )
{
Plugin buildPlugin = (Plugin) i.next();
if ( buildPlugin.getKey().equals( plugin.getKey() ) )
{
plugin = buildPlugin;
break;
}
}
project.injectPluginManagementInfo( plugin );
}
if ( pluginDescriptor == null )
{
pluginDescriptor = verifyPlugin( plugin, project, session );
}
// 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 )
{
if ( isOptionalMojo )
{
getLogger().info( "Skipping missing optional mojo: " + task );
}
else
{
throw new BuildFailureException( "Required goal not found: " + task + " in "
+ pluginDescriptor.getId() );
}
}
return mojoDescriptor;
}
catch ( PluginNotFoundException e )
{
if ( isOptionalMojo )
{
getLogger().info( "Skipping missing optional mojo: " + task );
getLogger().debug( "Mojo: " + task + " could not be found. Reason: " + e.getMessage(), e );
}
else
{
throw e;
}
}
return null;
}
protected void line()
{
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();
TaskSegment()
{
}
TaskSegment( final boolean aggregate )
{
this.aggregate = aggregate;
}
public String toString()
{
StringBuffer message = new StringBuffer();
message.append( " task-segment: [" );
for ( Iterator it = tasks.iterator(); it.hasNext(); )
{
String task = (String) it.next();
message.append( task );
if ( it.hasNext() )
{
message.append( ", " );
}
}
message.append( "]" );
if ( aggregate )
{
message.append( " (aggregator-style)" );
}
return message.toString();
}
boolean aggregate()
{
return aggregate;
}
void add( final String task )
{
tasks.add( task );
}
List getTasks()
{
return tasks;
}
}
public List getLifecycles()
{
return lifecycles;
}
// -------------------------------------------------------------------------
// TODO: The methods and fields below are only needed for products like Hudson,
// that provide their own LifecycleExecutor and component configuration that extend
// default implementation, and which may become out-of-date as component requirements
// are updated within Maven itself.
public void initialize()
throws InitializationException
{
if ( mavenProjectBuilder == null )
{
warnOfIncompleteComponentConfiguration( MavenProjectBuilder.ROLE );
try
{
mavenProjectBuilder = (MavenProjectBuilder) container.lookup( MavenProjectBuilder.ROLE );
}
catch ( ComponentLookupException e )
{
throw new InitializationException( "Failed to lookup project builder after it was NOT injected via component requirement." );
}
}
if ( modelInterpolator == null )
{
warnOfIncompleteComponentConfiguration( ModelInterpolator.ROLE );
try
{
modelInterpolator = (ModelInterpolator) container.lookup( ModelInterpolator.ROLE );
}
catch ( ComponentLookupException e )
{
throw new InitializationException( "Failed to lookup model interpolator after it was NOT injected via component requirement." );
}
}
if ( configInterpolator == null )
{
warnOfIncompleteComponentConfiguration( ConfigurationInterpolator.ROLE );
try
{
configInterpolator = (ConfigurationInterpolator) container.lookup( ConfigurationInterpolator.ROLE );
}
catch ( ComponentLookupException e )
{
throw new InitializationException( "Failed to lookup plugin-configuration interpolator after it was NOT injected via component requirement." );
}
}
}
private void warnOfIncompleteComponentConfiguration( final String role )
{
StringBuffer buffer = new StringBuffer();
buffer.append( "\n************ WARNING ************" );
buffer.append( "\n\nThis Maven runtime contains a LifecycleExecutor component with an incomplete configuration." );
buffer.append( "\n\nLifecycleExecutor class: " ).append( getClass().getName() );
buffer.append( "\nMissing component requirement: " ).append( role );
buffer.append( "\n" );
buffer.append( "\nNOTE: This seems to be a third-party Maven derivative you are using. If so, please" );
buffer.append( "\nnotify the developers for this derivative project of the problem. The Apache Maven team is not" );
buffer.append( "\nresponsible for maintaining the integrity of third-party component overrides." );
buffer.append( "\n\n" );
getLogger().warn( buffer.toString() );
}
private PlexusContainer container;
public void contextualize( final Context context )
throws ContextException
{
container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
}
}