Add warnings for deprecation of aggregator-mojos bound to the lifecycle, and add error/error-logging (error when directly in the pom, error-logging when brought in via lifecycle mapping, etc.) when a direct-invocation mojo (@requiresDirectInvocation) is bound to the lifecycle.

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@619711 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2008-02-08 00:46:16 +00:00
parent 621d238877
commit cc6b280343
8 changed files with 272 additions and 61 deletions

View File

@ -25,6 +25,7 @@ import org.apache.maven.NoGoalsSpecifiedException;
import org.apache.maven.ProjectBuildFailureException; import org.apache.maven.ProjectBuildFailureException;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager; import org.apache.maven.execution.ReactorManager;
import org.apache.maven.lifecycle.binding.MojoBindingFactory; import org.apache.maven.lifecycle.binding.MojoBindingFactory;
@ -62,8 +63,15 @@ import java.util.List;
import java.util.Stack; import java.util.Stack;
/** /**
* Responsible for orchestrating the process of building the ordered list of
* steps required to achieve the specified set of tasks passed into Maven, then
* executing these mojos in order. This class also manages the various error messages
* that may occur during this process, and directing the behavior of the build
* according to what's specified in {@link MavenExecutionRequest#getReactorFailureBehavior()}.
*
* @author Jason van Zyl * @author Jason van Zyl
* @author <a href="mailto:brett@apache.org">Brett Porter</a> * @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @author jdcasey
* @version $Id$ * @version $Id$
* @todo because of aggregation, we ended up with cli-ish stuff in here (like line() and the project logging, without * @todo because of aggregation, we ended up with cli-ish stuff in here (like line() and the project logging, without
* much of the event handling) * much of the event handling)
@ -92,12 +100,7 @@ public class DefaultLifecycleExecutor
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** /**
* Execute a task. Each task may be a phase in the lifecycle or the execution of a mojo. * {@inheritDoc}
*
* @param session
* @param reactorManager
* @param dispatcher
* @throws MojoFailureException
*/ */
public void execute( final MavenSession session, public void execute( final MavenSession session,
final ReactorManager reactorManager, final ReactorManager reactorManager,
@ -151,6 +154,16 @@ public class DefaultLifecycleExecutor
dispatcher ); dispatcher );
} }
/**
* After the list of goals from {@link MavenSession#getGoals()} is segmented into
* contiguous sets of aggregated and non-aggregated mojos and lifecycle phases,
* this method is used to execute each task-segment. Its logic has a top-level fork
* for each segment, which basically varies the project used to run the execution
* according to aggregation needs. If the segment is aggregated, the root project
* will be used to construct and execute the mojo bindings. Otherwise, this
* method will iterate through each project, and execute all the goals implied
* by the current task segment.
*/
private void executeTaskSegments( final List taskSegments, private void executeTaskSegments( final List taskSegments,
final ReactorManager reactorManager, final ReactorManager reactorManager,
final MavenSession session, final MavenSession session,
@ -216,7 +229,8 @@ public class DefaultLifecycleExecutor
event, event,
reactorManager, reactorManager,
buildStartTime, buildStartTime,
target ); target,
true );
} }
catch ( MojoFailureException e ) catch ( MojoFailureException e )
{ {
@ -317,7 +331,8 @@ public class DefaultLifecycleExecutor
{ {
executeGoalAndHandleFailures( binding, session, dispatcher, executeGoalAndHandleFailures( binding, session, dispatcher,
event, reactorManager, event, reactorManager,
buildStartTime, target ); buildStartTime, target,
false);
} }
catch ( MojoFailureException e ) catch ( MojoFailureException e )
{ {
@ -367,6 +382,17 @@ public class DefaultLifecycleExecutor
} }
} }
/**
* Since each project can have its own {@link ClassRealm} instance that inherits
* from the core Maven realm, and contains the specific build-extension
* components referenced in that project, the lookup realms must be managed for
* each project that's used to fire off a mojo execution. This helps ensure
* that unsafe {@link PlexusContainer#lookup(String)} and related calls will
* have access to these build-extension components.
* <br />
* This method simply restores the original Maven-core lookup realm when a
* project-specific realm is in use.
*/
private void restoreLookupRealm( ClassRealm oldLookupRealm ) private void restoreLookupRealm( ClassRealm oldLookupRealm )
{ {
if ( oldLookupRealm != null ) if ( oldLookupRealm != null )
@ -375,32 +401,28 @@ public class DefaultLifecycleExecutor
} }
} }
/**
* Since each project can have its own {@link ClassRealm} instance that inherits
* from the core Maven realm, and contains the specific build-extension
* components referenced in that project, the lookup realms must be managed for
* each project that's used to fire off a mojo execution. This helps ensure
* that unsafe {@link PlexusContainer#lookup(String)} and related calls will
* have access to these build-extension components.
* <br />
* This method is meant to find a project-specific realm, if one exists, for
* use as the lookup realm for unsafe component lookups, using {@link PlexusContainer#setLookupRealm(ClassRealm)}.
*/
private ClassRealm setProjectLookupRealm( MavenSession session, private ClassRealm setProjectLookupRealm( MavenSession session,
MavenProject rootProject ) MavenProject rootProject )
throws LifecycleExecutionException throws LifecycleExecutionException
{ {
// MavenProjectSession projectSession; ClassRealm projectRealm = session.getRealmManager().getProjectRealm( rootProject.getGroupId(), rootProject.getArtifactId(), rootProject.getVersion() );
// try
// { if ( projectRealm != null )
// projectSession = session.getProjectSession( rootProject ); {
// } return container.setLookupRealm( projectRealm );
// catch ( PlexusContainerException e ) }
// {
// throw new LifecycleExecutionException(
// "Failed to create project-specific session for: "
// + rootProject.getId(),
// rootProject, e );
// }
// if ( projectSession != null )
// {
// return container.setLookupRealm( projectSession.getProjectRealm() );
// }
// else
// {
// return null;
// }
// TODO: Fix this to use project-level realm!
return container.getLookupRealm(); return container.getLookupRealm();
} }
@ -444,13 +466,22 @@ public class DefaultLifecycleExecutor
return mojoBindings; return mojoBindings;
} }
/**
* Lookup the plugin containing the referenced mojo, validate that it is
* allowed to execute in the current environment (according to whether
* it's a direct-invocation-only or aggregator mojo, and the allowAggregators
* flag), and execute the mojo. If any of these steps fails, this method will
* consult with the {@link ReactorManager} to determine whether the build
* should be stopped.
*/
private void executeGoalAndHandleFailures( final MojoBinding mojoBinding, private void executeGoalAndHandleFailures( final MojoBinding mojoBinding,
final MavenSession session, final MavenSession session,
final EventDispatcher dispatcher, final EventDispatcher dispatcher,
final String event, final String event,
final ReactorManager rm, final ReactorManager rm,
final long buildStartTime, final long buildStartTime,
final String target ) final String target,
boolean allowAggregators )
throws LifecycleExecutionException, MojoFailureException throws LifecycleExecutionException, MojoFailureException
{ {
MavenProject project = session.getCurrentProject(); MavenProject project = session.getCurrentProject();
@ -487,6 +518,9 @@ public class DefaultLifecycleExecutor
} }
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() ); MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoBinding.getGoal() );
validateMojoExecution( mojoBinding, mojoDescriptor, project, allowAggregators );
MojoExecution mojoExecution = new MojoExecution( mojoDescriptor ); MojoExecution mojoExecution = new MojoExecution( mojoDescriptor );
mojoExecution.setConfiguration( (Xpp3Dom) mojoBinding.getConfiguration() ); mojoExecution.setConfiguration( (Xpp3Dom) mojoBinding.getConfiguration() );
@ -546,6 +580,90 @@ public class DefaultLifecycleExecutor
} }
} }
/**
* Verify that the specified {@link MojoBinding} is legal for execution under
* the current circumstances. Currently, this mainly checks that aggregator
* mojos and direct-invocation-only mojos are not bound to lifecycle phases.
* <br/>
* If an invalid mojo is detected, and it is brought in via the user's POM
* (this will be checked using {@link MojoBinding#POM_ORIGIN} and {@link MojoBinding#getOrigin()}),
* then a {@link LifecycleExecutionException} will be thrown. Otherwise, the mojo
* was brought in via a lifecycle mapping or overlay, or as part of a forked execution.
* In these cases, the error will be logged to the console, using the ERROR log-level (since the
* user cannot fix this sort of problem easily).
*/
private void validateMojoExecution( MojoBinding mojoBinding,
MojoDescriptor mojoDescriptor,
MavenProject project,
boolean allowAggregators )
throws LifecycleExecutionException
{
if ( mojoDescriptor.isAggregator() && !allowAggregators )
{
if ( MojoBinding.POM_ORIGIN.equals( mojoBinding.getOrigin() ) )
{
StringBuffer buffer = new StringBuffer();
buffer.append( "\n\nDEPRECATED: Binding aggregator mojos to lifecycle phases in the POM is considered dangerous." );
buffer.append( "\nThis feature has been deprecated. Please adjust your POM files accordingly." );
buffer.append( "\n\nOffending mojo:\n\n" );
buffer.append( MojoBindingUtils.toString( mojoBinding ) );
buffer.append( "\n\nProject: " ).append( project.getId() );
buffer.append( "\nPOM File: " ).append( String.valueOf( project.getFile() ) );
buffer.append( "\n" );
getLogger().warn( buffer.toString() );
}
else
{
StringBuffer buffer = new StringBuffer();
buffer.append( "\n\nDEPRECATED: An aggregator mojo has been bound to your project's build lifecycle." );
buffer.append( "\nThis feature is dangerous, and has been deprecated." );
buffer.append( "\n\nOffending mojo:\n\n" );
buffer.append( MojoBindingUtils.toString( mojoBinding ) );
buffer.append( "\n\nDirect binding of aggregator mojos to the lifecycle is not allowed, but this binding was not configured from within in your POM." );
buffer.append( "\n\nIts origin was: " ).append( mojoBinding.getOrigin() );
if ( mojoBinding.getOriginDescription() != null )
{
buffer.append( " (" ).append( mojoBinding.getOriginDescription() ).append( ")" );
}
buffer.append( "\n" );
getLogger().warn( buffer.toString() );
}
}
else if ( mojoDescriptor.isDirectInvocationOnly() && !MojoBinding.DIRECT_INVOCATION_ORIGIN.equals( mojoBinding.getOrigin() ) )
{
if ( MojoBinding.POM_ORIGIN.equals( mojoBinding.getOrigin() ) )
{
throw new LifecycleExecutionException( "Mojo:\n\n" + MojoBindingUtils.toString( mojoBinding ) + "\n\ncan only be invoked directly by the user. Binding it to lifecycle phases in the POM is not allowed.", project );
}
else
{
StringBuffer buffer = new StringBuffer();
buffer.append( "\n\nSKIPPING execution of mojo:\n\n" ).append( MojoBindingUtils.toString( mojoBinding ) );
buffer.append( "\n\nIt specifies direct-invocation only, but has been bound to the build lifecycle." );
buffer.append( "\n\nDirect-invocation mojos can only be called by the user. This binding was not configured from within in your POM." );
buffer.append( "\n\nIts origin was: " ).append( mojoBinding.getOrigin() );
if ( mojoBinding.getOriginDescription() != null )
{
buffer.append( " (" ).append( mojoBinding.getOriginDescription() ).append( ")" );
}
buffer.append( "\n" );
getLogger().error( buffer.toString() );
}
}
}
/**
* In the event that an error occurs during executeGoalAndHandleFailure(..),
* this method is called to handle logging the error in the {@link ReactorManager},
* then determining (again, from the reactor-manager) whether to stop the build.
*
* @return true if the build should stop, false otherwise.
*/
private boolean handleExecutionFailure( final ReactorManager rm, private boolean handleExecutionFailure( final ReactorManager rm,
final MavenProject project, final MavenProject project,
final Exception e, final Exception e,
@ -571,6 +689,9 @@ public class DefaultLifecycleExecutor
return false; return false;
} }
/**
* {@inheritDoc}
*/
public TaskValidationResult isTaskValid( String task, public TaskValidationResult isTaskValid( String task,
MavenSession session, MavenSession session,
MavenProject rootProject ) MavenProject rootProject )
@ -636,6 +757,15 @@ public class DefaultLifecycleExecutor
return new TaskValidationResult(); return new TaskValidationResult();
} }
/**
* Split up the list of goals from {@link MavenSession#getGoals()} according
* to aggregation needs. Each adjacent goal in the list is included in a single
* task segment. When the next goal references a different type of mojo or
* lifecycle phase (eg. previous goal wasn't an aggregator, but next one is...or the reverse),
* a new task segment is started and the new goal is added to that.
*
* @return the list of task-segments, each flagged according to aggregation needs.
*/
private List segmentTaskListByAggregationNeeds( final List tasks, private List segmentTaskListByAggregationNeeds( final List tasks,
final MavenSession session, final MavenSession session,
final MavenProject rootProject ) final MavenProject rootProject )
@ -735,6 +865,12 @@ public class DefaultLifecycleExecutor
return segments; return segments;
} }
/**
* Retrieve the {@link MojoDescriptor} that corresponds to a given direct mojo
* invocation. This is used during the fail-fast method isTaskValid(..), and also
* during task-segmentation, to allow the lifecycle executor to determine whether
* the mojo is an aggregator.
*/
private MojoDescriptor getMojoDescriptorForDirectInvocation( String task, private MojoDescriptor getMojoDescriptorForDirectInvocation( String task,
MavenSession session, MavenSession session,
MavenProject project ) MavenProject project )

View File

@ -20,21 +20,39 @@ package org.apache.maven.lifecycle;
*/ */
import org.apache.maven.BuildFailureException; import org.apache.maven.BuildFailureException;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager; import org.apache.maven.execution.ReactorManager;
import org.apache.maven.monitor.event.EventDispatcher; import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
/** /**
* Responsible for orchestrating the process of building the ordered list of
* steps required to achieve the specified set of tasks passed into Maven, then
* executing these mojos in order. This class also manages the various error messages
* that may occur during this process, and directing the behavior of the build
* according to what's specified in {@link MavenExecutionRequest#getReactorFailureBehavior()}.
*
* @author <a href="mailto:jason@maven.org">Jason van Zyl</a> * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
* @author jdcasey
* @version $Id$ * @version $Id$
*/ */
public interface LifecycleExecutor public interface LifecycleExecutor
{ {
String ROLE = LifecycleExecutor.class.getName(); String ROLE = LifecycleExecutor.class.getName();
/**
* Provides a fail-fast way to check that all goals specified in {@link MavenExecutionRequest#getGoals()}
* or {@link MavenSession#getGoals()} is valid.
*/
TaskValidationResult isTaskValid( String task, MavenSession session, MavenProject rootProject ); TaskValidationResult isTaskValid( String task, MavenSession session, MavenProject rootProject );
/**
* Order and execute mojos associated with the current set of projects in the
* reactor. Specific lifecycle phases and mojo invocations that determine what
* phases and mojos this method will attempt to execute are provided in {@link MavenSession#getGoals()},
* which is populated from {@link MavenExecutionRequest#getGoals()}.
*/
void execute( MavenSession session, ReactorManager rm, EventDispatcher dispatcher ) void execute( MavenSession session, ReactorManager rm, EventDispatcher dispatcher )
throws LifecycleExecutionException, BuildFailureException; throws LifecycleExecutionException, BuildFailureException;

View File

@ -189,7 +189,7 @@ public class DefaultLifecycleBindingManager
mojoBinding.setGoal( goal ); mojoBinding.setGoal( goal );
mojoBinding.setConfiguration( BindingUtils.mergeConfigurations( plugin, execution ) ); mojoBinding.setConfiguration( BindingUtils.mergeConfigurations( plugin, execution ) );
mojoBinding.setExecutionId( execution.getId() ); mojoBinding.setExecutionId( execution.getId() );
mojoBinding.setOrigin( "POM" ); mojoBinding.setOrigin( MojoBinding.POM_ORIGIN );
logger.debug( "Mojo: " + MojoBindingUtils.toString( mojoBinding ) + ": determining binding phase." ); logger.debug( "Mojo: " + MojoBindingUtils.toString( mojoBinding ) + ": determining binding phase." );
@ -384,7 +384,8 @@ public class DefaultLifecycleBindingManager
} }
binding.setConfiguration( configuration ); binding.setConfiguration( configuration );
binding.setOrigin( lifecycleId ); binding.setOrigin( MojoBinding.LIFECYCLE_MAPPING_ORIGIN );
binding.setOriginDescription( "Lifecycle overlay: " + lifecycleId );
LifecycleUtils.addMojoBinding( phase.getId(), binding, bindings ); LifecycleUtils.addMojoBinding( phase.getId(), binding, bindings );
phaseBindings.add( binding ); phaseBindings.add( binding );
@ -572,7 +573,7 @@ public class DefaultLifecycleBindingManager
binding.setVersion( pluginDescriptor.getVersion() ); binding.setVersion( pluginDescriptor.getVersion() );
binding.setGoal( mojoDescriptor.getGoal() ); binding.setGoal( mojoDescriptor.getGoal() );
binding.setExecutionId( id ); binding.setExecutionId( id );
binding.setOrigin( "POM" ); binding.setOrigin( MojoBinding.POM_ORIGIN );
BindingUtils.injectProjectConfiguration( binding, project ); BindingUtils.injectProjectConfiguration( binding, project );

View File

@ -132,6 +132,7 @@ public final class BuildPlanUtils
if ( extendedInfo ) if ( extendedInfo )
{ {
listing.append( "\nOrigin: " ).append( binding.getOrigin() ); listing.append( "\nOrigin: " ).append( binding.getOrigin() );
listing.append( "\nOrigin Description: " ).append( binding.getOriginDescription() );
listing.append( "\nConfiguration:\n\t" ).append( listing.append( "\nConfiguration:\n\t" ).append(
String.valueOf( binding.getConfiguration() ).replaceAll( String.valueOf( binding.getConfiguration() ).replaceAll(
"\\n", "\\n",

View File

@ -126,6 +126,10 @@ public class DefaultBuildPlanner
project, project,
session, session,
true ); true );
binding.setOrigin( MojoBinding.DIRECT_INVOCATION_ORIGIN );
binding.setOriginDescription( "Original reference from user: " + task );
plan.addDirectInvocationBinding( task, binding ); plan.addDirectInvocationBinding( task, binding );
} }
} }
@ -469,7 +473,8 @@ public class DefaultBuildPlanner
executeGoal, executeGoal,
project ); project );
binding.setOrigin( "Forked from " + referencingGoal ); binding.setOrigin( MojoBinding.FORKED_DIRECT_REFERENCE_ORIGIN );
binding.setOriginDescription( "Forked from: " + MojoBindingUtils.toString( mojoBinding ) );
plan.addForkedExecution( mojoBinding, Collections.singletonList( binding ) ); plan.addForkedExecution( mojoBinding, Collections.singletonList( binding ) );
} }

View File

@ -16,8 +16,6 @@ public final class StateManagementUtils
public static final String ARTIFACT_ID = "maven-state-management"; public static final String ARTIFACT_ID = "maven-state-management";
public static final String ORIGIN = "Maven build-state management";
public static final String END_FORKED_EXECUTION_GOAL = "end-fork"; public static final String END_FORKED_EXECUTION_GOAL = "end-fork";
public static final String START_FORKED_EXECUTION_GOAL = "start-fork"; public static final String START_FORKED_EXECUTION_GOAL = "start-fork";
@ -46,7 +44,7 @@ public final class StateManagementUtils
binding.setArtifactId( ARTIFACT_ID ); binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION ); binding.setVersion( VERSION );
binding.setGoal( START_FORKED_EXECUTION_GOAL ); binding.setGoal( START_FORKED_EXECUTION_GOAL );
binding.setOrigin( ORIGIN ); binding.setOrigin( MojoBinding.INTERNAL_ORIGIN );
CURRENT_FORK_ID = (int) System.currentTimeMillis(); CURRENT_FORK_ID = (int) System.currentTimeMillis();
@ -73,7 +71,7 @@ public final class StateManagementUtils
binding.setArtifactId( ARTIFACT_ID ); binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION ); binding.setVersion( VERSION );
binding.setGoal( END_FORKED_EXECUTION_GOAL ); binding.setGoal( END_FORKED_EXECUTION_GOAL );
binding.setOrigin( ORIGIN ); binding.setOrigin( MojoBinding.INTERNAL_ORIGIN );
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" ); Xpp3Dom forkId = new Xpp3Dom( "forkId" );
@ -98,7 +96,7 @@ public final class StateManagementUtils
binding.setArtifactId( ARTIFACT_ID ); binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION ); binding.setVersion( VERSION );
binding.setGoal( CLEAR_FORKED_EXECUTION_GOAL ); binding.setGoal( CLEAR_FORKED_EXECUTION_GOAL );
binding.setOrigin( ORIGIN ); binding.setOrigin( MojoBinding.INTERNAL_ORIGIN );
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" ); Xpp3Dom forkId = new Xpp3Dom( "forkId" );
@ -156,7 +154,7 @@ public final class StateManagementUtils
binding.setArtifactId( ARTIFACT_ID ); binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION ); binding.setVersion( VERSION );
binding.setGoal( RESOLVE_LATE_BOUND_PLUGIN_GOAL ); binding.setGoal( RESOLVE_LATE_BOUND_PLUGIN_GOAL );
binding.setOrigin( ORIGIN ); binding.setOrigin( MojoBinding.INTERNAL_ORIGIN );
Xpp3Dom config = new Xpp3Dom( "configuration" ); Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom param = new Xpp3Dom( "groupId" ); Xpp3Dom param = new Xpp3Dom( "groupId" );

View File

@ -845,13 +845,25 @@ public class DefaultPluginManager
if ( param.getDeprecated() != null ) if ( param.getDeprecated() != null )
{ {
boolean warnOfDeprecation = false; boolean warnOfDeprecation = false;
if ( extractedMojoConfiguration.getChild( param.getName() ) != null ) PlexusConfiguration child = extractedMojoConfiguration.getChild( param.getName() );
try
{ {
warnOfDeprecation = true; if ( ( child != null ) && ( child.getValue() != null ) )
{
warnOfDeprecation = true;
}
else if ( param.getAlias() != null)
{
child = extractedMojoConfiguration.getChild( param.getAlias() );
if ( ( child != null ) && ( child.getValue() != null ) )
{
warnOfDeprecation = true;
}
}
} }
else if ( ( param.getAlias() != null ) && ( extractedMojoConfiguration.getChild( param.getAlias() ) != null ) ) catch ( PlexusConfigurationException e )
{ {
warnOfDeprecation = true; // forget it, this is just for deprecation checking, after all...
} }
if ( warnOfDeprecation ) if ( warnOfDeprecation )

View File

@ -547,17 +547,8 @@
</field> </field>
</fields> </fields>
</class> </class>
<class>
<name>LifecycleStep</name>
<version>1.0.0</version>
<description><![CDATA[
Some step in the build process. This could be a mojo, or it could be a signal to start/stop
forked-mode of execution, etc.
]]></description>
</class>
<class> <class>
<name>MojoBinding</name> <name>MojoBinding</name>
<superClass>LifecycleStep</superClass>
<version>1.0.0</version> <version>1.0.0</version>
<description>A binding of one mojo to one lifecycle phase, possibly including configuration.</description> <description>A binding of one mojo to one lifecycle phase, possibly including configuration.</description>
<fields> <fields>
@ -600,12 +591,6 @@
<description>A name for this mojo binding, for purposes of merging configurations via inheritance, etc.</description> <description>A name for this mojo binding, for purposes of merging configurations via inheritance, etc.</description>
<type>String</type> <type>String</type>
</field> </field>
<field>
<version>1.0.0</version>
<name>origin</name>
<type>String</type>
<description>Specific location from which this set of mojo binding was loaded.</description>
</field>
<field> <field>
<name>configuration</name> <name>configuration</name>
<version>1.0.0</version> <version>1.0.0</version>
@ -623,8 +608,63 @@
<codeSegment> <codeSegment>
<version>1.0.0</version> <version>1.0.0</version>
<code><![CDATA[ <code><![CDATA[
/** origin marker for mojos referenced directly by the user or embedded-mode consumer. */
public static final String DIRECT_INVOCATION_ORIGIN = "Direct invocation";
/** origin marker for single (non-lifecycle) mojos referenced by a forked-execution annotation in another mojo. */
public static final String FORKED_DIRECT_REFERENCE_ORIGIN = "Direct forking reference";
/** origin marker for mojos bound to the lifecycle through POM configuration (not packaging defaults). */
public static final String POM_ORIGIN = "POM";
/** origin marker for mojos bound to the lifecycle by a standard (or default) lifecycle mapping. */
public static final String LIFECYCLE_MAPPING_ORIGIN = "Lifecycle mapping";
/** origin marker for mojos injected into the lifecycle by Maven, to manage lifecycle state. */
public static final String INTERNAL_ORIGIN = "Maven internal state-management";
private String origin;
/**
* Return the origin marker set for this MojoBinding, or null. This will give a general idea of where this
* binding came from.
*/
public String getOrigin()
{
return origin;
}
public void setOrigin( String origin )
{
this.origin = origin;
}
private String originDescription;
/**
* Return specific information about where exactly this binding came from, if it's available.
* This might be used to record the specific forking mojo or the lifecycle
* overlay name that included this mojo, for instance.
*/
public String getOriginDescription()
{
return originDescription;
}
public void setOriginDescription( String originDescription )
{
this.originDescription = originDescription;
}
private boolean lateBound = false; private boolean lateBound = false;
/**
* Mark this mojo binding as late-bound, meaning the plugin for this mojo
* could not be resolved when it was included in a build plan (the class
* responsible for calculating the ordered list of mojos to execute for a build).
* This flag should result in Maven injecting an internal step into the build
* just ahead of this mojo's execution, to resolve the plugin it refers to.
*/
public boolean isLateBound() public boolean isLateBound()
{ {
return lateBound; return lateBound;