Merging revIds: 515814:520600 from 2.1-lifecycle-refactor branch to trunk.

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@520609 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2007-03-20 21:40:59 +00:00
parent 7d17a9c108
commit 34bf67ecf1
80 changed files with 12792 additions and 1286 deletions

View File

@ -16,6 +16,7 @@
# under the License.
classworlds.version=1.2-alpha-7
plexus-active-collections.version=1.0-SNAPSHOT
plexus.version=1.0-alpha-20
plexus-archiver.version=1.0-alpha-8
plexus-utils.version=1.4.1

View File

@ -116,6 +116,7 @@ under the License.
</sequential>
</macrodef>
<pull orgpath="commons-cli/commons-cli" version="${commons-cli.version}" name="commons-cli"/>
<pull orgpath="org/codehaus/plexus/plexus-active-collections" version="${plexus-active-collections.version}" name="plexus-active-collections" repository="codehaus"/>
<pull orgpath="org/codehaus/plexus/plexus-utils" version="${plexus-utils.version}" name="plexus-utils" repository="codehaus"/>
<pull orgpath="org/codehaus/plexus/plexus-container-default" version="${plexus.version}" name="plexus-container-default" repository="codehaus"/>
<pull orgpath="org/codehaus/plexus/plexus-component-api" version="${plexus.version}" name="plexus-component-api" repository="codehaus"/>
@ -153,6 +154,7 @@ under the License.
<path id="pre.classpath">
<pathelement location="${maven.repo.local}/commons-cli/commons-cli/${commons-cli.version}/commons-cli-${commons-cli.version}.jar"/>
<pathelement location="${maven.repo.local}/commons-lang/commons-lang/${commons-lang.version}/commons-lang-${commons-lang.version}.jar"/>
<pathelement location="${maven.repo.local}/org/codehaus/plexus/plexus-active-collections/${plexus-active-collections.version}/plexus-active-collections-${plexus-active-collections.version}.jar"/>
<pathelement location="${maven.repo.local}/org/codehaus/plexus/plexus-utils/${plexus-utils.version}/plexus-utils-${plexus-utils.version}.jar"/>
<pathelement location="${maven.repo.local}/org/codehaus/plexus/plexus-container-default/${plexus.version}/plexus-container-default-${plexus.version}.jar"/>
<pathelement location="${maven.repo.local}/org/codehaus/plexus/plexus-component-api/${plexus.version}/plexus-component-api-${plexus.version}.jar"/>
@ -226,6 +228,7 @@ under the License.
<modello file="maven-model/src/main/mdo/maven.mdo" version="4.0.0"/>
<!-- DGF TODO turn this into a big <apply> task? write a custom task? -->
<modello file="maven-lifecycle/src/main/mdo/maven-lifecycle.mdo"/>
<modello file="maven-plugin-descriptor/src/main/mdo/lifecycle.mdo"/>
<modello file="maven-plugin-parameter-documenter/src/main/mdo/paramdoc.mdo"/>
<modello file="maven-plugin-registry/plugin-registry.mdo"/>
@ -339,6 +342,9 @@ load ${bootstrapDir}/target/classes
</classpath>
<sysproperty key="classworlds.conf" value="${bootstrapDir}/m2.conf"/>
<sysproperty key="bootstrapDir" value="${bootstrapDir}"/>
<!--
<arg value="-X"/>
-->
<arg value="-e"/>
<arg line="${maven.goals}"/>
</java>

View File

@ -0,0 +1,109 @@
package org.apache.maven.context;
import java.util.HashMap;
import java.util.Map;
public class ScopedBuildContext
implements BuildContext, ManagedBuildData
{
private final BuildContext parentBuildContext;
private final String scopeKey;
private Map localContext;
public ScopedBuildContext( String scopeKey, BuildContext parentBuildContext )
{
this.scopeKey = scopeKey;
this.parentBuildContext = parentBuildContext;
this.localContext = (Map) parentBuildContext.get( scopeKey );
if ( localContext == null )
{
this.localContext = new HashMap();
parentBuildContext.store( this );
}
}
public Object delete( Object key )
{
return localContext.remove( key );
}
public Object get( Object key )
{
return localContext.get( key );
}
public void put( Object key, Object value )
{
localContext.put( key, value );
}
/**
* @deprecated Use {@link BuildContext#store(ManagedBuildData)} instead.
*/
public void put( ManagedBuildData managedData )
{
localContext.put( managedData.getStorageKey(), managedData.getData() );
}
public boolean retrieve( ManagedBuildData managedData )
{
Map data = (Map) localContext.get( managedData.getStorageKey() );
if ( data != null )
{
managedData.setData( data );
return true;
}
else
{
return false;
}
}
public void store( ManagedBuildData managedData )
{
localContext.put( managedData.getStorageKey(), managedData.getData() );
}
public Map getData()
{
return localContext;
}
public String getStorageKey()
{
return scopeKey;
}
public void setData( Map data )
{
this.localContext = data;
}
public void storeContext( BuildContextManager buildContextManager )
{
if ( parentBuildContext instanceof ScopedBuildContext )
{
((ScopedBuildContext) parentBuildContext).storeContext( buildContextManager );
}
else
{
buildContextManager.storeBuildContext( parentBuildContext );
}
}
public BuildContext getParentBuildContext()
{
return parentBuildContext;
}
public void delete( BuildContextManager buildContextManager )
{
parentBuildContext.delete( scopeKey );
storeContext( buildContextManager );
}
}

View File

@ -30,6 +30,11 @@ under the License.
<artifactId>maven-core</artifactId>
<name>Maven Core</name>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-lifecycle</artifactId>
<version>2.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-build-context</artifactId>
@ -65,6 +70,10 @@ under the License.
<artifactId>maven-artifact</artifactId>
<version>2.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
@ -148,5 +157,10 @@ under the License.
<artifactId>plexus-classworlds</artifactId>
<version>1.2-alpha-5</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-active-collections</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -48,6 +48,7 @@ public class DefaultArtifactFilterManager implements ArtifactFilterManager
artifacts.add( "maven-build-context" );
artifacts.add( "maven-core" );
artifacts.add( "maven-error-diagnoser" );
artifacts.add( "maven-lifecycle" );
artifacts.add( "maven-model" );
artifacts.add( "maven-monitor" );
artifacts.add( "maven-plugin-api" );

View File

@ -33,6 +33,7 @@ import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.execution.RuntimeInformation;
import org.apache.maven.execution.SessionContext;
import org.apache.maven.extension.BuildExtensionScanner;
import org.apache.maven.extension.ExtensionScanningException;
import org.apache.maven.lifecycle.LifecycleExecutor;
@ -542,7 +543,12 @@ public class DefaultMaven
ReactorManager rpm,
EventDispatcher dispatcher )
{
return new MavenSession( container, request, dispatcher, rpm );
MavenSession session = new MavenSession( container, request, dispatcher, rpm );
SessionContext ctx = new SessionContext( session );
ctx.store( buildContextManager );
return session;
}
// ----------------------------------------------------------------------

View File

@ -28,6 +28,7 @@ import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@ -48,6 +49,8 @@ public class MavenSession
private MavenExecutionRequest request;
private Map reports = new LinkedHashMap();
public MavenSession( PlexusContainer container,
MavenExecutionRequest request,
EventDispatcher eventDispatcher,
@ -156,4 +159,5 @@ public class MavenSession
{
return request;
}
}

View File

@ -0,0 +1,157 @@
package org.apache.maven.execution;
/*
* 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.artifact.repository.ArtifactRepository;
import org.apache.maven.context.BuildContext;
import org.apache.maven.context.BuildContextManager;
import org.apache.maven.context.ManagedBuildData;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.settings.Settings;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Build context object that supplies information about how Maven was invoked, including all of the
* information available in the MavenExecutionRequest (in read-only form).
*/
public class SessionContext
implements ManagedBuildData
{
public static final String BUILD_CONTEXT_KEY = SessionContext.class.getName();
private static final String REQUEST_KEY = "request";
private MavenSession session;
private SessionContext()
{
}
public SessionContext( MavenSession session )
{
this.session = session;
}
public String getStorageKey()
{
return BUILD_CONTEXT_KEY;
}
public static SessionContext read( BuildContextManager buildContextManager )
{
BuildContext buildContext = buildContextManager.readBuildContext( false );
SessionContext sessionContext = new SessionContext();
if ( buildContext != null )
{
if ( !buildContext.retrieve( sessionContext ) )
{
return null;
}
}
return sessionContext;
}
public void store( BuildContextManager buildContextManager )
{
BuildContext buildContext = buildContextManager.readBuildContext( true );
buildContext.store( this );
buildContextManager.storeBuildContext( buildContext );
}
public Map getData()
{
return Collections.singletonMap( REQUEST_KEY, session );
}
public void setData( Map data )
{
this.session = (MavenSession) data.get( REQUEST_KEY );
}
//------------------------------------------------------------
// DELEGATED METHODS, USING DEFENSIVE COPIES WHERE POSSIBLE.
//------------------------------------------------------------
public EventDispatcher getEventDispatcher()
{
return session.getEventDispatcher();
}
public Properties getExecutionProperties()
{
return new Properties( session.getExecutionProperties() );
}
public String getExecutionRootDirectory()
{
return session.getExecutionRootDirectory();
}
public List getGoals()
{
return Collections.unmodifiableList( session.getGoals() );
}
public ArtifactRepository getLocalRepository()
{
return session.getLocalRepository();
}
public MavenExecutionRequest getRequest()
{
return session.getRequest();
}
public Settings getSettings()
{
return session.getSettings();
}
public List getSortedProjects()
{
return Collections.unmodifiableList( session.getSortedProjects() );
}
public Date getStartTime()
{
return new Date( session.getStartTime().getTime() );
}
public boolean isUsingPOMsFromFilesystem()
{
return session.isUsingPOMsFromFilesystem();
}
public MavenSession getSession()
{
return session;
}
}

View File

@ -0,0 +1,187 @@
package org.apache.maven.lifecycle;
import org.apache.maven.context.BuildContext;
import org.apache.maven.context.BuildContextManager;
import org.apache.maven.context.ManagedBuildData;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReport;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* Build context that contains the current project used by the executing mojo, plus any parent
* project instances (not inheritance-wise, but fork-wise) in a stack that will be restored once the
* current forked-execution is completed. This class also tracks the reports executed for a project,
* for future reference by other mojos using the ${reports} expression.
*
* @author jdcasey
*
*/
public class LifecycleExecutionContext
implements ManagedBuildData
{
public static final String BUILD_CONTEXT_KEY = LifecycleExecutionContext.class.getName();
private static final String CURRENT_PROJECT_KEY = "current-project";
private static final String PROJECT_STACK_KEY = "fork-project-stack";
private static final String REPORTS_KEY = "reports";
private MavenProject currentProject;
private Stack forkedProjectStack = new Stack();
private Map reports = new HashMap();
public LifecycleExecutionContext( MavenProject project )
{
this.currentProject = project;
}
private LifecycleExecutionContext()
{
// used for retrieval.
}
/**
* Serialize the data in this context for storage. Any class in maven-core or the bootclasspath is legal
* here as a datatype in the data map.
*/
public Map getData()
{
Map data = new HashMap();
data.put( CURRENT_PROJECT_KEY, currentProject );
data.put( PROJECT_STACK_KEY, forkedProjectStack );
data.put( REPORTS_KEY, reports );
return data;
}
/**
* Retrieve the master key under which the serialized data map for this context will be stored
* in the main {@link BuildContext}.
*/
public String getStorageKey()
{
return BUILD_CONTEXT_KEY;
}
/**
* Deserialize the data for this context. Any class in maven-core or the bootclasspath is legal
* here as a datatype in the data map.
*/
public void setData( Map data )
{
this.currentProject = (MavenProject) data.get( CURRENT_PROJECT_KEY );
this.forkedProjectStack = (Stack) data.get( PROJECT_STACK_KEY );
this.reports = (Map) data.get( REPORTS_KEY );
}
/**
* Push the existing currentProject onto the forked-project stack, and set the specified project
* as the new current project. This signifies the beginning of a new forked-execution context.
*/
public void addForkedProject( MavenProject project )
{
forkedProjectStack.push( currentProject );
currentProject = project;
}
/**
* Peel off the last forked project from the stack, and restore it as the currentProject. This
* signifies the cleanup of a completed forked-execution context.
*/
public MavenProject removeForkedProject()
{
if ( !forkedProjectStack.isEmpty() )
{
MavenProject lastCurrent = currentProject;
currentProject = (MavenProject) forkedProjectStack.pop();
return lastCurrent;
}
return null;
}
/**
* Return the current project for use in a mojo execution.
*/
public MavenProject getCurrentProject()
{
return currentProject;
}
/**
* Convenience method to read the current context instance out of the main {@link BuildContext} provided
* by the specified {@link BuildContextManager}. If no current context exist, return null.
*/
public static LifecycleExecutionContext read( BuildContextManager buildContextManager )
{
BuildContext buildContext = buildContextManager.readBuildContext( true );
LifecycleExecutionContext ctx = new LifecycleExecutionContext();
if ( buildContext.retrieve( ctx ) )
{
return ctx;
}
return null;
}
/**
* Remove the current lifecycle context from the main {@link BuildContext} provided by the
* specified {@link BuildContextManager}.
*/
public static void delete( BuildContextManager buildContextManager )
{
BuildContext buildContext = buildContextManager.readBuildContext( false );
if ( buildContext != null )
{
buildContext.delete( BUILD_CONTEXT_KEY );
}
}
/**
* Store this lifecycle context in the main {@link BuildContext} provided by the specified
* {@link BuildContextManager}.
*/
public void store( BuildContextManager buildContextManager )
{
BuildContext buildContext = buildContextManager.readBuildContext( true );
buildContext.store( this );
buildContextManager.storeBuildContext( buildContext );
}
/**
* Retrieve the list of reports ({@link MavenReport} instances) that have been executed against
* this project, for use in another mojo's execution.
*/
public List getReports()
{
return new ArrayList( reports.values() );
}
/**
* Clear the reports for this project
*/
public void clearReports()
{
reports.clear();
}
/**
* Add a newly-executed report ({@link MavenReport} instance) to the reports collection, for
* future reference.
*/
public void addReport( MojoDescriptor mojoDescriptor, MavenReport report )
{
reports.put( mojoDescriptor.getId(), report );
}
}

View File

@ -0,0 +1,269 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.model.LifecycleBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.apache.maven.model.Build;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginContainer;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.model.ReportSet;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ModelUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Set of utilities used to create and manipulate MojoBindings, both singly and in collections that
* constitute LifecycleBindings instances. Some of the methods contained here have fairly generic
* names, but have a specialized purpose for this package (such as those that build plugin keys
* that lack the version); therefore, this class and all of its methods are package-scoped.
*/
final class BindingUtils
{
/**
* Builds a mapping of groupId:artifactId --&gt; Plugin from the POM. If a plugin is listed
* without a groupId, the {@link BindingUtils#createPluginKey(Plugin)} method will fill it in
* using org.apache.maven.plugins.
*/
static Map buildPluginMap( MavenProject project )
{
Map pluginMap = new HashMap();
if ( project != null )
{
Build build = project.getBuild();
if ( build != null )
{
for ( Iterator it = build.getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
pluginMap.put( createPluginKey( plugin ), plugin );
}
}
}
return pluginMap;
}
/**
* Builds a mapping of groupId:artifactId --&gt; Plugin from a PluginContainer, such as the build
* or pluginManagement section of a POM. If a plugin is listed without a groupId, the
* {@link BindingUtils#createPluginKey(Plugin)} method will fill it in using org.apache.maven.plugins.
*/
static Map buildPluginMap( PluginContainer pluginContainer )
{
Map pluginMap = new HashMap();
if ( pluginContainer != null )
{
for ( Iterator it = pluginContainer.getPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
pluginMap.put( createPluginKey( plugin ), plugin );
}
}
return pluginMap;
}
/**
* Create a key for the given Plugin, for use in mappings. The key consists of groupId:artifactId,
* where groupId == org.apache.maven.plugins if the Plugin instance has a groupId == null.
*/
static String createPluginKey( Plugin plugin )
{
return createPluginKey( plugin.getGroupId(), plugin.getArtifactId() );
}
/**
* Create a key for use in looking up Plugin instances from mappings. The key consists of
* groupId:artifactId, where groupId == org.apache.maven.plugins if the supplied groupId
* value == null.
*/
static String createPluginKey( String groupId, String artifactId )
{
return ( groupId == null ? PluginDescriptor.getDefaultPluginGroupId() : groupId ) + ":" + artifactId;
}
/**
* Merge the ReportPlugin and ReportSet configurations, with the ReportSet configuration taking
* precedence.
*/
static Object mergeConfigurations( ReportPlugin reportPlugin, ReportSet reportSet )
{
if ( reportPlugin == null && reportSet == null )
{
return null;
}
else if ( reportSet == null )
{
return reportPlugin.getConfiguration();
}
else if ( reportPlugin == null )
{
return reportSet.getConfiguration();
}
else
{
return mergeRawConfigurations( reportSet.getConfiguration(), reportPlugin.getConfiguration() );
}
}
/**
* Merge the Plugin and PluginExecution configurations, with the PluginExecution configuration
* taking precedence.
*/
static Object mergeConfigurations( Plugin plugin, PluginExecution execution )
{
if ( plugin == null && execution == null )
{
return null;
}
else if ( execution == null )
{
return plugin.getConfiguration();
}
else if ( plugin == null )
{
return execution.getConfiguration();
}
else
{
return mergeRawConfigurations( execution.getConfiguration(), plugin.getConfiguration() );
}
}
/**
* Merge two configurations, assuming they are Xpp3Dom instances. This method creates a defensive
* copy of the dominant configuration before merging, to avoid polluting the original dominant
* one.
*/
static Object mergeRawConfigurations( Object dominant, Object recessive )
{
Xpp3Dom dominantConfig = (Xpp3Dom) dominant;
Xpp3Dom recessiveConfig = (Xpp3Dom) recessive;
if ( recessiveConfig == null )
{
return dominantConfig;
}
else if ( dominantConfig == null )
{
return recessiveConfig;
}
else
{
return Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( dominantConfig ), recessiveConfig );
}
}
/**
* Inject any plugin configuration available from the specified POM into the MojoBinding, after
* first merging in the applicable configuration from the POM's pluginManagement section.
*/
static void injectProjectConfiguration( MojoBinding binding, MavenProject project )
{
Map pluginMap = buildPluginMap( project );
Plugin plugin = (Plugin) pluginMap.get( createPluginKey( binding.getGroupId(), binding.getArtifactId() ) );
if ( plugin == null )
{
plugin = new Plugin();
plugin.setGroupId( binding.getGroupId() );
plugin.setArtifactId( binding.getArtifactId() );
}
injectPluginManagementInfo( plugin, project );
PluginExecution exec = (PluginExecution) plugin.getExecutionsAsMap().get( binding.getExecutionId() );
binding.setConfiguration( mergeConfigurations( plugin, exec ) );
}
/**
* Inject any plugin configuration available from the specified POM into the MojoBindings
* present in the given LifecycleBindings instance, after first merging in the configuration
* from the POM's pluginManagement section.
*/
static void injectProjectConfiguration( LifecycleBindings bindings, MavenProject project )
{
Map pluginsByVersionlessKey = buildPluginMap( project );
for ( Iterator lifecycleIt = bindings.getBindingList().iterator(); lifecycleIt.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) lifecycleIt.next();
for ( Iterator phaseIt = binding.getPhasesInOrder().iterator(); phaseIt.hasNext(); )
{
Phase phase = (Phase) phaseIt.next();
for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); )
{
MojoBinding mojo = (MojoBinding) mojoIt.next();
String pluginKey = createPluginKey( mojo.getGroupId(), mojo.getArtifactId() );
Plugin plugin = (Plugin) pluginsByVersionlessKey.get( pluginKey );
if ( plugin == null )
{
plugin = new Plugin();
plugin.setGroupId( mojo.getGroupId() );
plugin.setArtifactId( mojo.getArtifactId() );
}
injectPluginManagementInfo( plugin, project );
PluginExecution exec = (PluginExecution) plugin.getExecutionsAsMap().get( mojo.getExecutionId() );
mojo.setConfiguration( mergeConfigurations( plugin, exec ) );
}
}
}
}
/**
* Inject any applicable configuration available from the POM's pluginManagement section into the
* specified Plugin instance.
*/
static void injectPluginManagementInfo( Plugin plugin, MavenProject project )
{
if ( project == null )
{
return;
}
Build build = project.getBuild();
if ( build == null )
{
return;
}
PluginManagement plugMgmt = build.getPluginManagement();
if ( plugMgmt == null )
{
return;
}
Map plugMgmtMap = buildPluginMap( plugMgmt );
String key = createPluginKey( plugin );
Plugin mgmtPlugin = (Plugin) plugMgmtMap.get( key );
if ( mgmtPlugin != null )
{
ModelUtils.mergePluginDefinitions( plugin, mgmtPlugin, false );
}
}
}

View File

@ -0,0 +1,736 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleBindingLoader;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.lifecycle.model.LifecycleBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.plan.DirectInvocationModifier;
import org.apache.maven.lifecycle.plan.LifecyclePlannerException;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.model.ReportSet;
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.Lifecycle;
import org.apache.maven.plugin.loader.PluginLoader;
import org.apache.maven.plugin.loader.PluginLoaderException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.collections.ActiveMap;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
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.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* Responsible for the gross construction of LifecycleBindings, or mappings of MojoBinding instances
* to different parts of the three lifecycles: clean, build, and site. Also, handles transcribing
* these LifecycleBindings instances into lists of MojoBinding's, which can be consumed by the
* LifecycleExecutor.
*
* @author jdcasey
*
*/
public class DefaultLifecycleBindingManager
implements LifecycleBindingManager, LogEnabled
{
private ActiveMap bindingsByPackaging;
private ActiveMap legacyMappingsByPackaging;
private PluginLoader pluginLoader;
private MojoBindingFactory mojoBindingFactory;
private LegacyLifecycleMappingParser legacyLifecycleMappingParser;
private Logger logger;
// configured. Moved out of DefaultLifecycleExecutor...
private List legacyLifecycles;
// configured. Moved out of DefaultLifecycleExecutor...
private List defaultReports;
/**
* Retrieve the LifecycleBindings given by the lifecycle mapping component/file for the project's
* packaging. Any applicable mojo configuration will be injected into the LifecycleBindings from
* the POM.
*/
public LifecycleBindings getBindingsForPackaging( MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException
{
String packaging = project.getPackaging();
LifecycleBindings bindings = null;
LifecycleBindingLoader loader = (LifecycleBindingLoader) bindingsByPackaging.get( packaging );
if ( loader != null )
{
bindings = loader.getBindings();
}
// TODO: Remove this once we no longer have to support legacy-style lifecycle mappings
if ( bindings == null )
{
LifecycleMapping mapping = (LifecycleMapping) legacyMappingsByPackaging.get( packaging );
if ( mapping != null )
{
bindings = legacyLifecycleMappingParser.parseMappings( mapping, packaging );
}
}
if ( bindings == null )
{
bindings = searchPluginsWithExtensions( project );
}
else
{
BindingUtils.injectProjectConfiguration( bindings, project );
}
if ( bindings == null )
{
bindings = getDefaultBindings( project );
}
return bindings;
}
/**
* Search all plugins configured in the POM that have extensions == true, looking for either a
* {@link LifecycleBindingLoader} instance, or a {@link LifecycleMapping} instance that matches
* the project's packaging. For the first match found, construct the corresponding LifecycleBindings
* instance and return it after POM configurations have been injected into any appropriate
* MojoBinding instances contained within.
*/
private LifecycleBindings searchPluginsWithExtensions( MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException
{
List plugins = project.getBuildPlugins();
String packaging = project.getPackaging();
LifecycleBindings bindings = null;
for ( Iterator it = plugins.iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
if ( plugin.isExtensions() )
{
LifecycleBindingLoader loader = null;
try
{
loader = (LifecycleBindingLoader) pluginLoader.loadPluginComponent( LifecycleBindingLoader.ROLE, packaging,
plugin, project );
}
catch ( ComponentLookupException e )
{
logger.debug( LifecycleBindingLoader.ROLE + " for packaging: " + packaging
+ " could not be retrieved from plugin: " + plugin.getKey() + ".\nReason: " + e.getMessage(), e );
}
catch ( PluginLoaderException e )
{
throw new LifecycleLoaderException( "Failed to load plugin: " + plugin.getKey() + ". Reason: "
+ e.getMessage(), e );
}
if ( loader != null )
{
bindings = loader.getBindings();
}
// TODO: Remove this once we no longer have to support legacy-style lifecycle mappings
if ( bindings == null )
{
LifecycleMapping mapping = null;
try
{
mapping = (LifecycleMapping) pluginLoader.loadPluginComponent( LifecycleMapping.ROLE, packaging, plugin,
project );
}
catch ( ComponentLookupException e )
{
logger.debug( LifecycleMapping.ROLE + " for packaging: " + packaging
+ " could not be retrieved from plugin: " + plugin.getKey() + ".\nReason: " + e.getMessage(), e );
}
catch ( PluginLoaderException e )
{
throw new LifecycleLoaderException( "Failed to load plugin: " + plugin.getKey() + ". Reason: "
+ e.getMessage(), e );
}
if ( mapping != null )
{
bindings = legacyLifecycleMappingParser.parseMappings( mapping, packaging );
}
}
if ( bindings != null )
{
break;
}
}
}
if ( bindings != null )
{
BindingUtils.injectProjectConfiguration( bindings, project );
}
return bindings;
}
/**
* Construct the LifecycleBindings for the default lifecycle mappings, including injection of
* configuration from the project into each MojoBinding, where appropriate.
*/
public LifecycleBindings getDefaultBindings( MavenProject project )
throws LifecycleSpecificationException
{
LifecycleBindings bindings = legacyLifecycleMappingParser.parseDefaultMappings( legacyLifecycles );
BindingUtils.injectProjectConfiguration( bindings, project );
return bindings;
}
public void enableLogging( Logger logger )
{
this.logger = logger;
}
/**
* Construct the LifecycleBindings that constitute the extra mojos bound to the lifecycle within
* the POM itself.
*/
public LifecycleBindings getProjectCustomBindings( MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException
{
String projectId = project.getId();
LifecycleBindings bindings = new LifecycleBindings();
bindings.setPackaging( project.getPackaging() );
List plugins = project.getBuildPlugins();
if ( plugins != null )
{
for ( Iterator it = plugins.iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
BindingUtils.injectPluginManagementInfo( plugin, project );
PluginDescriptor pluginDescriptor = null;
List executions = plugin.getExecutions();
if ( executions != null )
{
for ( Iterator execIt = executions.iterator(); execIt.hasNext(); )
{
PluginExecution execution = (PluginExecution) execIt.next();
List goals = execution.getGoals();
if ( goals != null && !goals.isEmpty() )
{
for ( Iterator goalIterator = goals.iterator(); goalIterator.hasNext(); )
{
String goal = (String) goalIterator.next();
if ( goal == null )
{
logger.warn( "Execution: " + execution.getId() + " in plugin: " + plugin.getKey() + " in the POM has a null goal." );
continue;
}
MojoBinding mojoBinding = new MojoBinding();
mojoBinding.setGroupId( plugin.getGroupId() );
mojoBinding.setArtifactId( plugin.getArtifactId() );
mojoBinding.setVersion( plugin.getVersion() );
mojoBinding.setGoal( goal );
mojoBinding.setConfiguration( BindingUtils.mergeConfigurations( plugin, execution ) );
mojoBinding.setExecutionId( execution.getId() );
mojoBinding.setOrigin( "POM" );
String phase = execution.getPhase();
if ( phase == null )
{
if ( pluginDescriptor == null )
{
try
{
pluginDescriptor = pluginLoader.loadPlugin( plugin, project );
}
catch ( PluginLoaderException e )
{
throw new LifecycleLoaderException( "Failed to load plugin: " + plugin + ". Reason: "
+ e.getMessage(), e );
}
}
if ( pluginDescriptor.getMojos() == null )
{
logger.error( "Somehow, the PluginDescriptor for plugin: " + plugin.getKey() + " contains no mojos. This is highly irregular. Ignoring..." );
continue;
}
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
phase = mojoDescriptor.getPhase();
if ( phase == null )
{
throw new LifecycleSpecificationException( "No phase specified for goal: " + goal
+ " in plugin: " + plugin.getKey() + " from POM: " + projectId );
}
}
LifecycleUtils.addMojoBinding( phase, mojoBinding, bindings );
}
}
}
}
}
}
LifecycleUtils.setOrigin( bindings, "POM" );
return bindings;
}
/**
* Construct the LifecycleBindings that constitute the mojos mapped to the lifecycles by an overlay
* specified in a plugin. Inject mojo configuration from the POM into all appropriate MojoBinding
* instances.
*/
public LifecycleBindings getPluginLifecycleOverlay( PluginDescriptor pluginDescriptor, String lifecycleId,
MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException
{
Lifecycle lifecycleOverlay = null;
try
{
lifecycleOverlay = pluginDescriptor.getLifecycleMapping( lifecycleId );
}
catch ( IOException e )
{
throw new LifecycleLoaderException( "Unable to read lifecycle mapping file: " + e.getMessage(), e );
}
catch ( XmlPullParserException e )
{
throw new LifecycleLoaderException( "Unable to parse lifecycle mapping file: " + e.getMessage(), e );
}
if ( lifecycleOverlay == null )
{
throw new LifecycleLoaderException( "LegacyLifecycle '" + lifecycleId + "' not found in plugin" );
}
LifecycleBindings bindings = new LifecycleBindings();
for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
{
org.apache.maven.plugin.lifecycle.Phase phase = (org.apache.maven.plugin.lifecycle.Phase) i.next();
List phaseBindings = new ArrayList();
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();
// 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>
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
MojoBinding binding;
if ( goal.indexOf( ":" ) > 0 )
{
binding = mojoBindingFactory.parseMojoBinding( goal, project, false );
}
else
{
binding = new MojoBinding();
binding.setGroupId( pluginDescriptor.getGroupId() );
binding.setArtifactId( pluginDescriptor.getArtifactId() );
binding.setVersion( pluginDescriptor.getVersion() );
binding.setGoal( goal );
}
Xpp3Dom configuration = (Xpp3Dom) exec.getConfiguration();
if ( phase.getConfiguration() != null )
{
configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ), configuration );
}
binding.setConfiguration( configuration );
binding.setOrigin( lifecycleId );
LifecycleUtils.addMojoBinding( phase.getId(), binding, bindings );
phaseBindings.add( binding );
}
}
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
// [jdcasey; 08-March-2007] Not sure what the above to-do references...how _should_
// this work??
for ( Iterator j = phaseBindings.iterator(); j.hasNext(); )
{
MojoBinding binding = (MojoBinding) j.next();
Xpp3Dom configuration = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( (Xpp3Dom) phase.getConfiguration() ),
(Xpp3Dom) binding.getConfiguration() );
binding.setConfiguration( configuration );
}
}
}
return bindings;
}
/**
* Retrieve the list of MojoBinding instances that correspond to the reports configured for the
* specified project. Inject all appropriate configuration from the POM for each MojoBinding, using
* the following precedence rules:
* <br/>
* <ol>
* <li>report-set-level configuration</li>
* <li>reporting-level configuration</li>
* <li>execution-level configuration</li>
* <li>plugin-level configuration</li>
* </ol>
*/
public List getReportBindings( MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException
{
if ( project.getModel().getReports() != null )
{
logger.error( "Plugin contains a <reports/> section: this is IGNORED - please use <reporting/> instead." );
}
List reportPlugins = getReportPluginsForProject( project );
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( getReportsForPlugin( reportPlugin, null, project ) );
}
else
{
for ( Iterator j = reportSets.iterator(); j.hasNext(); )
{
ReportSet reportSet = (ReportSet) j.next();
reports.addAll( getReportsForPlugin( reportPlugin, reportSet, project ) );
}
}
}
}
return reports;
}
/**
* Retrieve the ReportPlugin instances referenced in the specified POM.
*/
private List getReportPluginsForProject( MavenProject project )
{
List reportPlugins = project.getReportPlugins();
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, ":" );
if ( tok.countTokens() != 2 )
{
logger.warn( "Invalid default report ignored: '" + report + "' (must be groupId:artifactId)" );
}
else
{
String groupId = tok.nextToken();
String artifactId = tok.nextToken();
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 );
reportPlugins.add( reportPlugin );
}
}
}
}
return reportPlugins;
}
/**
* Retrieve any reports from the specified ReportPlugin which are referenced in the specified POM.
*/
private List getReportsForPlugin( ReportPlugin reportPlugin, ReportSet reportSet, MavenProject project )
throws LifecycleLoaderException
{
PluginDescriptor pluginDescriptor;
try
{
pluginDescriptor = pluginLoader.loadReportPlugin( reportPlugin, project );
}
catch ( PluginLoaderException e )
{
throw new LifecycleLoaderException( "Failed to load report plugin: " + reportPlugin.getKey() + ". Reason: "
+ e.getMessage(), e );
}
String pluginKey = BindingUtils.createPluginKey( reportPlugin.getGroupId(), reportPlugin.getArtifactId() );
Plugin plugin = (Plugin) BindingUtils.buildPluginMap( project ).get( pluginKey );
List reports = new ArrayList();
for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); )
{
MojoDescriptor mojoDescriptor = (MojoDescriptor) i.next();
// 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();
}
MojoBinding binding = new MojoBinding();
binding.setGroupId( pluginDescriptor.getGroupId() );
binding.setArtifactId( pluginDescriptor.getArtifactId() );
binding.setVersion( pluginDescriptor.getVersion() );
binding.setGoal( mojoDescriptor.getGoal() );
binding.setExecutionId( id );
binding.setOrigin( "POM" );
Object reportConfig = BindingUtils.mergeConfigurations( reportPlugin, reportSet );
if ( plugin == null )
{
plugin = new Plugin();
plugin.setGroupId( pluginDescriptor.getGroupId() );
plugin.setArtifactId( pluginDescriptor.getArtifactId() );
}
BindingUtils.injectPluginManagementInfo( plugin, project );
Map execMap = plugin.getExecutionsAsMap();
PluginExecution exec = (PluginExecution) execMap.get( id );
Object pluginConfig = plugin.getConfiguration();
if ( exec != null )
{
pluginConfig = BindingUtils.mergeConfigurations( plugin, exec );
}
reportConfig = BindingUtils.mergeRawConfigurations( reportConfig, pluginConfig );
binding.setConfiguration( reportConfig );
reports.add( binding );
}
}
return reports;
}
/**
* Determine whether the first list contains all of the same MojoBinding instances, in the same
* order, starting at index zero, as the second list. If so, it is either a perfect super-list
* or an equal list, and return true. Return false otherwise.
*/
private static boolean isSameOrSuperListOfMojoBindings( List superCandidate, List check )
{
if ( superCandidate == null || check == null )
{
return false;
}
if ( superCandidate.size() < check.size() )
{
return false;
}
List superKeys = new ArrayList( superCandidate.size() );
for ( Iterator it = superCandidate.iterator(); it.hasNext(); )
{
MojoBinding binding = (MojoBinding) it.next();
superKeys.add( LifecycleUtils.createMojoBindingKey( binding, true ) );
}
List checkKeys = new ArrayList( check.size() );
for ( Iterator it = check.iterator(); it.hasNext(); )
{
MojoBinding binding = (MojoBinding) it.next();
checkKeys.add( LifecycleUtils.createMojoBindingKey( binding, true ) );
}
return superKeys.subList( 0, checkKeys.size() ).equals( checkKeys );
}
/**
* Traverse the specified LifecycleBindings instance for all of the specified tasks. If the task
* is found to be a phase name, construct the list of all MojoBindings that lead up to that phase
* in that lifecycle, and add them to the master MojoBinding list. If the task is not a phase name,
* treat it as a direct mojo invocation, parse it into a MojoBinding (resolving the plugin prefix
* first if necessary), and add it to the master MojoBinding list. Finally, return the master list.
*/
public List assembleMojoBindingList( List tasks, LifecycleBindings bindings, MavenProject project )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
return assembleMojoBindingList( tasks, bindings, Collections.EMPTY_MAP, project );
}
/**
* Traverse the specified LifecycleBindings instance for all of the specified tasks. If the task
* is found to be a phase name, construct the list of all MojoBindings that lead up to that phase
* in that lifecycle, and add them to the master MojoBinding list. If the task is not a phase name,
* treat it as a direct mojo invocation, parse it into a MojoBinding (resolving the plugin prefix
* first if necessary), and add it to the master MojoBinding list.
*
* Then, iterate through all MojoBindings in the master list, and for each one that maps to an
* entry in directInvocationModifiers, substitute the resultant MojoBinding list from that
* modifier in place of the original MojoBinding.
*
* Finally, return the modified master list.
*/
public List assembleMojoBindingList( List tasks, LifecycleBindings lifecycleBindings, Map directInvocationModifiers,
MavenProject project )
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
List planBindings = new ArrayList();
List lastMojoBindings = null;
for ( Iterator it = tasks.iterator(); it.hasNext(); )
{
String task = (String) it.next();
LifecycleBinding binding = LifecycleUtils.findLifecycleBindingForPhase( task, lifecycleBindings );
if ( binding != null )
{
List mojoBindings = LifecycleUtils.getMojoBindingListForLifecycle( task, binding );
// save these so we can reference the originals...
List originalMojoBindings = mojoBindings;
// if these mojo bindings are a superset of the last bindings, only add the difference.
if ( isSameOrSuperListOfMojoBindings( mojoBindings, lastMojoBindings ) )
{
List revised = new ArrayList( mojoBindings );
revised.removeAll( lastMojoBindings );
if ( revised.isEmpty() )
{
continue;
}
mojoBindings = revised;
}
planBindings.addAll( mojoBindings );
lastMojoBindings = originalMojoBindings;
}
else
{
MojoBinding mojoBinding = mojoBindingFactory.parseMojoBinding( task, project, true );
BindingUtils.injectProjectConfiguration( mojoBinding, project );
mojoBinding.setOrigin( "direct invocation" );
String key = LifecycleUtils.createMojoBindingKey( mojoBinding, true );
DirectInvocationModifier modifier = (DirectInvocationModifier) directInvocationModifiers.get( key );
if ( modifier != null )
{
planBindings.addAll( modifier.getModifiedBindings( project, this ) );
}
else
{
planBindings.add( mojoBinding );
}
}
}
return planBindings;
}
}

View File

@ -0,0 +1,135 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.loader.PluginLoader;
import org.apache.maven.plugin.loader.PluginLoaderException;
import org.apache.maven.project.MavenProject;
import java.util.StringTokenizer;
/**
* Responsible for constructing or parsing MojoBinding instances from one of several sources, potentially
* using the {@link PluginLoader} to resolve any plugin prefixes first.
*
* @author jdcasey
*
*/
public class DefaultMojoBindingFactory
implements MojoBindingFactory
{
PluginLoader pluginLoader;
/**
* Parse the specified mojo string into a MojoBinding, optionally allowing plugin-prefix references.
* If a plugin-prefix is allowed and used, resolve the prefix and use the resulting PluginDescriptor
* to set groupId and artifactId on the MojoBinding instance.
*/
public MojoBinding parseMojoBinding( String bindingSpec, MavenProject project, boolean allowPrefixReference )
throws LifecycleSpecificationException, LifecycleLoaderException
{
StringTokenizer tok = new StringTokenizer( bindingSpec, ":" );
int numTokens = tok.countTokens();
MojoBinding binding = null;
if ( numTokens == 2 )
{
if ( !allowPrefixReference )
{
String msg = "Mapped-prefix lookup of mojos are only supported from direct invocation. "
+ "Please use specification of the form groupId:artifactId[:version]:goal instead.";
throw new LifecycleSpecificationException( msg );
}
String prefix = tok.nextToken();
PluginDescriptor pluginDescriptor;
try
{
pluginDescriptor = pluginLoader.findPluginForPrefix( prefix, project );
}
catch ( PluginLoaderException e )
{
throw new LifecycleLoaderException(
"Failed to find plugin for prefix: " + prefix + ". Reason: " + e.getMessage(),
e );
}
binding = createMojoBinding( pluginDescriptor.getGroupId(), pluginDescriptor.getArtifactId(),
pluginDescriptor.getVersion(), tok.nextToken(), project );
}
else if ( numTokens == 3 || numTokens == 4 )
{
binding = new MojoBinding();
String groupId = tok.nextToken();
String artifactId = tok.nextToken();
String version = null;
if ( numTokens == 4 )
{
version = tok.nextToken();
}
String goal = tok.nextToken();
binding = createMojoBinding( groupId, artifactId, version, goal, project );
}
else
{
String message = "Invalid task '" + bindingSpec + "': you must specify a valid lifecycle phase, or"
+ " a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal";
throw new LifecycleSpecificationException( message );
}
return binding;
}
/**
* Create a new MojoBinding instance with the specified information, and inject POM configurations
* appropriate to that mojo before returning it.
*/
public MojoBinding createMojoBinding( String groupId, String artifactId, String version, String goal, MavenProject project )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( groupId );
binding.setArtifactId( artifactId );
binding.setVersion( version );
binding.setGoal( goal );
BindingUtils.injectProjectConfiguration( binding, project );
return binding;
}
/**
* Simplified version of {@link MojoBindingFactory#parseMojoBinding(String, MavenProject, boolean)}
* which assumes the project is null and prefixes are not allowed. This method will <b>never</b>
* result in the {@link PluginLoader} being used to resolve the PluginDescriptor.
*/
public MojoBinding parseMojoBinding( String bindingSpec )
throws LifecycleSpecificationException
{
try
{
return parseMojoBinding( bindingSpec, null, false );
}
catch ( LifecycleLoaderException e )
{
IllegalStateException error = new IllegalStateException( e.getMessage()
+ "\n\nTHIS SHOULD BE IMPOSSIBLE DUE TO THE USAGE OF THE PLUGIN-LOADER." );
error.initCause( e );
throw error;
}
}
}

View File

@ -1,4 +1,4 @@
package org.apache.maven.lifecycle;
package org.apache.maven.lifecycle.binding;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@ -24,9 +24,9 @@ import java.util.List;
import java.util.Map;
/**
* Class Lifecycle.
* Class LegacyLifecycle.
*/
public class Lifecycle
public class LegacyLifecycle
{
/**
* Field id

View File

@ -0,0 +1,177 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.lifecycle.model.BuildBinding;
import org.apache.maven.lifecycle.model.CleanBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.apache.maven.lifecycle.model.SiteBinding;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* Responsible for parsing the Maven-2.0.x lifecycle-definition syntaxes. This class is partitioned
* from the others, because this syntax should be deprecated and removed from support, eventually.
*
* @author jdcasey
*
*/
public class LegacyLifecycleMappingParser
{
public static final String ROLE = LegacyLifecycleMappingParser.class.getName();
private MojoBindingFactory mojoBindingFactory;
public LifecycleBindings parseDefaultMappings( List lifecycles )
throws LifecycleSpecificationException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.setPackaging( "unmatched" );
for ( Iterator it = lifecycles.iterator(); it.hasNext(); )
{
LegacyLifecycle lifecycle = (LegacyLifecycle) it.next();
if ( "clean".equals( lifecycle.getId() ) )
{
bindings.setCleanBinding( parseCleanBindings( lifecycle.getDefaultPhases(), Collections.EMPTY_LIST ) );
}
else if ( "site".equals( lifecycle.getId() ) )
{
bindings.setSiteBinding( parseSiteBindings( lifecycle.getDefaultPhases(), Collections.EMPTY_LIST ) );
}
else if ( "default".equals( lifecycle.getId() ) )
{
bindings.setBuildBinding( parseBuildBindings( lifecycle.getDefaultPhases(), Collections.EMPTY_LIST ) );
}
else
{
throw new LifecycleSpecificationException( "Unrecognized lifecycle: " + lifecycle.getId() );
}
}
LifecycleUtils.setOrigin( bindings, "default lifecycle" );
return bindings;
}
public LifecycleBindings parseMappings( LifecycleMapping mapping, String packaging )
throws LifecycleSpecificationException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.setPackaging( packaging );
bindings.setCleanBinding( parseCleanBindings( mapping.getPhases( "clean" ), mapping.getOptionalMojos( "clean" ) ) );
bindings.setBuildBinding( parseBuildBindings( mapping.getPhases( "default" ), mapping.getOptionalMojos( "default" ) ) );
bindings.setSiteBinding( parseSiteBindings( mapping.getPhases( "site" ), mapping.getOptionalMojos( "site" ) ) );
LifecycleUtils.setOrigin( bindings, "packaging: " + packaging );
return bindings;
}
private BuildBinding parseBuildBindings( Map phases, List optionalKeys )
throws LifecycleSpecificationException
{
BuildBinding binding = new BuildBinding();
if ( phases != null )
{
binding.setValidate( parsePhaseBindings( (String) phases.get( "validate" ), optionalKeys ) );
binding.setInitialize( parsePhaseBindings( (String) phases.get( "initialize" ), optionalKeys ) );
binding.setGenerateSources( parsePhaseBindings( (String) phases.get( "generate-sources" ), optionalKeys ) );
binding.setProcessSources( parsePhaseBindings( (String) phases.get( "process-sources" ), optionalKeys ) );
binding.setGenerateResources( parsePhaseBindings( (String) phases.get( "generate-resources" ), optionalKeys ) );
binding.setProcessResources( parsePhaseBindings( (String) phases.get( "process-resources" ), optionalKeys ) );
binding.setCompile( parsePhaseBindings( (String) phases.get( "compile" ), optionalKeys ) );
binding.setProcessClasses( parsePhaseBindings( (String) phases.get( "process-classes" ), optionalKeys ) );
binding.setGenerateTestSources( parsePhaseBindings( (String) phases.get( "generate-test-sources" ), optionalKeys ) );
binding.setProcessTestSources( parsePhaseBindings( (String) phases.get( "process-test-sources" ), optionalKeys ) );
binding.setGenerateTestResources( parsePhaseBindings( (String) phases.get( "generate-test-resources" ), optionalKeys ) );
binding.setProcessTestResources( parsePhaseBindings( (String) phases.get( "process-test-resources" ), optionalKeys ) );
binding.setTestCompile( parsePhaseBindings( (String) phases.get( "test-compile" ), optionalKeys ) );
binding.setProcessTestClasses( parsePhaseBindings( (String) phases.get( "process-test-classes" ), optionalKeys ) );
binding.setTest( parsePhaseBindings( (String) phases.get( "test" ), optionalKeys ) );
binding.setPreparePackage( parsePhaseBindings( (String) phases.get( "prepare-package" ), optionalKeys ) );
binding.setCreatePackage( parsePhaseBindings( (String) phases.get( "package" ), optionalKeys ) );
binding.setPreIntegrationTest( parsePhaseBindings( (String) phases.get( "pre-integration-test" ), optionalKeys ) );
binding.setIntegrationTest( parsePhaseBindings( (String) phases.get( "integration-test" ), optionalKeys ) );
binding.setPostIntegrationTest( parsePhaseBindings( (String) phases.get( "post-integration-test" ), optionalKeys ) );
binding.setVerify( parsePhaseBindings( (String) phases.get( "verify" ), optionalKeys ) );
binding.setInstall( parsePhaseBindings( (String) phases.get( "install" ), optionalKeys ) );
binding.setDeploy( parsePhaseBindings( (String) phases.get( "deploy" ), optionalKeys ) );
}
return binding;
}
private CleanBinding parseCleanBindings( Map phaseMappings, List optionalKeys )
throws LifecycleSpecificationException
{
CleanBinding binding = new CleanBinding();
if ( phaseMappings != null )
{
binding.setPreClean( parsePhaseBindings( (String) phaseMappings.get( "pre-clean" ), optionalKeys ) );
binding.setClean( parsePhaseBindings( (String) phaseMappings.get( "clean" ), optionalKeys ) );
binding.setPostClean( parsePhaseBindings( (String) phaseMappings.get( "post-clean" ), optionalKeys ) );
}
return binding;
}
private Phase parsePhaseBindings( String bindingList, List optionalKeys )
throws LifecycleSpecificationException
{
Phase phase = new Phase();
if ( bindingList != null )
{
for ( StringTokenizer tok = new StringTokenizer( bindingList, "," ); tok.hasMoreTokens(); )
{
String rawBinding = tok.nextToken().trim();
MojoBinding binding = mojoBindingFactory.parseMojoBinding( rawBinding );
if ( optionalKeys != null && optionalKeys.contains( rawBinding ) )
{
binding.setOptional( true );
}
if ( binding == null )
{
continue;
}
phase.addBinding( binding );
}
}
return phase;
}
private SiteBinding parseSiteBindings( Map phases, List optionalKeys )
throws LifecycleSpecificationException
{
SiteBinding binding = new SiteBinding();
if ( phases != null )
{
binding.setPreSite( parsePhaseBindings( (String) phases.get( "pre-site" ), optionalKeys ) );
binding.setSite( parsePhaseBindings( (String) phases.get( "site" ), optionalKeys ) );
binding.setPostSite( parsePhaseBindings( (String) phases.get( "post-site" ), optionalKeys ) );
binding.setSiteDeploy( parsePhaseBindings( (String) phases.get( "site-deploy" ), optionalKeys ) );
}
return binding;
}
}

View File

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

View File

@ -0,0 +1,43 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.plugin.loader.PluginLoader;
import org.apache.maven.project.MavenProject;
/**
* Responsible for constructing or parsing MojoBinding instances from one of several sources, potentially
* using the {@link PluginLoader} to resolve any plugin prefixes first.
*
* @author jdcasey
*
*/
public interface MojoBindingFactory
{
String ROLE = MojoBindingFactory.class.getName();
/**
* Parse the specified mojo string into a MojoBinding, optionally allowing plugin-prefix references.
* If a plugin-prefix is allowed and used, resolve the prefix and use the resulting PluginDescriptor
* to set groupId and artifactId on the MojoBinding instance.
*/
MojoBinding parseMojoBinding( String bindingSpec, MavenProject project, boolean allowPrefixReference )
throws LifecycleSpecificationException, LifecycleLoaderException;
/**
* Create a new MojoBinding instance with the specified information, and inject POM configurations
* appropriate to that mojo before returning it.
*/
MojoBinding createMojoBinding( String groupId, String artifactId, String version, String goal, MavenProject project );
/**
* Simplified version of {@link MojoBindingFactory#parseMojoBinding(String, MavenProject, boolean)}
* which assumes the project is null and prefixes are not allowed. This method will <b>never</b>
* result in the {@link PluginLoader} being used to resolve the PluginDescriptor.
*/
MojoBinding parseMojoBinding( String bindingSpec )
throws LifecycleSpecificationException;
}

View File

@ -25,7 +25,7 @@ import java.util.List;
import java.util.Map;
/**
* Lifecycle mapping for a POM.
* LegacyLifecycle mapping for a POM.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @version $Id$

View File

@ -24,7 +24,7 @@ import java.util.List;
import java.util.Map;
/**
* Class Lifecycle.
* Class LegacyLifecycle.
*/
public class Lifecycle
{

View File

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

View File

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

View File

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

View File

@ -0,0 +1,27 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.project.MavenProject;
import java.util.List;
/**
* Responsible for creating a plan of execution for a given project and list of tasks. This build plan
* consists of MojoBinding instances that carry all the information necessary to execute a mojo,
* including configuration from the POM and other sources. NOTE: the build plan may be constructed
* of a main lifecycle binding-set, plus any number of lifecycle modifiers and direct-invocation
* modifiers, to handle cases of forked execution.
*
* @author jdcasey
*
*/
public interface BuildPlanner
{
/**
* Orchestrates construction of the build plan which will be used by the user of LifecycleExecutor.
*/
BuildPlan constructBuildPlan( List tasks, MavenProject project )
throws LifecycleLoaderException, LifecycleSpecificationException, LifecyclePlannerException;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,25 @@
package org.apache.maven.lifecycle.plan;
import org.apache.maven.lifecycle.LifecycleException;
/**
* Signals an error during build-plan construction.
*
* @author jdcasey
*
*/
public class LifecyclePlannerException
extends LifecycleException
{
public LifecyclePlannerException( String message, Throwable cause )
{
super( message, cause );
}
public LifecyclePlannerException( String message )
{
super( message );
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,30 @@
package org.apache.maven.lifecycle.statemgmt;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/**
* Remove the execution-project used during the fork, now that the forking mojo is finished executing.
*
* @author jdcasey
*
*/
public class ClearForkedContextMojo
extends AbstractMojo
{
private MavenProject project;
private int forkId = -1;
public void execute()
throws MojoExecutionException, MojoFailureException
{
getLog().info( "Cleaning up forked execution context [fork id: " + forkId + "]" );
project.clearExecutionProject();
}
}

View File

@ -0,0 +1,39 @@
package org.apache.maven.lifecycle.statemgmt;
import org.apache.maven.context.BuildContextManager;
import org.apache.maven.lifecycle.LifecycleExecutionContext;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/**
* Restore the lifecycle execution context's current-project, and set the project instance from the
* forked execution to project.getExecutionProject() for the forking mojo to use.
*
* @author jdcasey
*
*/
public class EndForkedExecutionMojo
extends AbstractMojo
{
private int forkId = -1;
private BuildContextManager buildContextManager;
public void execute()
throws MojoExecutionException, MojoFailureException
{
getLog().info( "Ending forked execution [fork id: " + forkId + "]" );
LifecycleExecutionContext ctx = LifecycleExecutionContext.read( buildContextManager );
MavenProject executionProject = ctx.removeForkedProject();
MavenProject project = ctx.getCurrentProject();
project.setExecutionProject( executionProject );
ctx.store( buildContextManager );
}
}

View File

@ -0,0 +1,36 @@
package org.apache.maven.lifecycle.statemgmt;
import org.apache.maven.context.BuildContextManager;
import org.apache.maven.lifecycle.LifecycleExecutionContext;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/**
* Setup a new project instance for the forked executions to use.
*
* @author jdcasey
*
*/
public class StartForkedExecutionMojo
extends AbstractMojo
{
private MavenProject project;
private int forkId = -1;
private BuildContextManager buildContextManager;
public void execute()
throws MojoExecutionException, MojoFailureException
{
getLog().info( "Starting forked execution [fork id: " + forkId + "]" );
LifecycleExecutionContext ctx = LifecycleExecutionContext.read( buildContextManager );
ctx.addForkedProject( new MavenProject( project ) );
ctx.store( buildContextManager );
}
}

View File

@ -0,0 +1,149 @@
package org.apache.maven.lifecycle.statemgmt;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.codehaus.plexus.util.xml.Xpp3Dom;
/**
* Constructs and matches MojoBinding instances that refer to the forked-execution context manager
* mojos.
*
* @author jdcasey
*
*/
public final class StateManagementUtils
{
public static final String GROUP_ID = "org.apache.maven.plugins.internal";
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 START_FORKED_EXECUTION_GOAL = "start-fork";
public static final String VERSION = "2.1";
public static final String CLEAR_FORKED_EXECUTION_GOAL = "clear-fork-context";
private static int CURRENT_FORK_ID = 0;
private StateManagementUtils()
{
}
/**
* Create a new MojoBinding instance that refers to the internal mojo used to setup a new
* forked-execution context. Also, set the configuration to contain the forkId for this new
* context.
*/
public static MojoBinding createStartForkedExecutionMojoBinding()
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( GROUP_ID );
binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION );
binding.setGoal( START_FORKED_EXECUTION_GOAL );
binding.setOrigin( ORIGIN );
CURRENT_FORK_ID = (int) System.currentTimeMillis();
Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" );
forkId.setValue( "" + CURRENT_FORK_ID );
config.addChild( forkId );
binding.setConfiguration( config );
return binding;
}
/**
* Create a new MojoBinding instance that refers to the internal mojo used to end a
* forked-execution context. Also, set the configuration to contain the forkId for this new
* context.
*/
public static MojoBinding createEndForkedExecutionMojoBinding()
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( GROUP_ID );
binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION );
binding.setGoal( END_FORKED_EXECUTION_GOAL );
binding.setOrigin( ORIGIN );
Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" );
forkId.setValue( "" + CURRENT_FORK_ID );
config.addChild( forkId );
binding.setConfiguration( config );
return binding;
}
/**
* Create a new MojoBinding instance that refers to the internal mojo used to cleanup a completed
* forked-execution context. Also, set the configuration to contain the forkId for this new
* context.
*/
public static MojoBinding createClearForkedExecutionMojoBinding()
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( GROUP_ID );
binding.setArtifactId( ARTIFACT_ID );
binding.setVersion( VERSION );
binding.setGoal( CLEAR_FORKED_EXECUTION_GOAL );
binding.setOrigin( ORIGIN );
Xpp3Dom config = new Xpp3Dom( "configuration" );
Xpp3Dom forkId = new Xpp3Dom( "forkId" );
forkId.setValue( "" + CURRENT_FORK_ID );
config.addChild( forkId );
binding.setConfiguration( config );
return binding;
}
/**
* Return true if the specified MojoBinding refers to the internal mojo used to setup a new
* forked-execution context. This is useful for formatting when listing the build plan, when
* expression of these actual mojo names isn't necessarily useful, and can be confusing.
*/
public static boolean isForkedExecutionStartMarker( MojoBinding binding )
{
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& START_FORKED_EXECUTION_GOAL.equals( binding.getGoal() );
}
/**
* Return true if the specified MojoBinding refers to the internal mojo used to end a
* forked-execution context. This is useful for formatting when listing the build plan, when
* expression of these actual mojo names isn't necessarily useful, and can be confusing.
*/
public static boolean isForkedExecutionEndMarker( MojoBinding binding )
{
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& END_FORKED_EXECUTION_GOAL.equals( binding.getGoal() );
}
/**
* Return true if the specified MojoBinding refers to the internal mojo used to clean up a completed
* forked-execution context. This is useful for formatting when listing the build plan, when
* expression of these actual mojo names isn't necessarily useful, and can be confusing.
*/
public static boolean isForkedExecutionClearMarker( MojoBinding binding )
{
return GROUP_ID.equals( binding.getGroupId() ) && ARTIFACT_ID.equals( binding.getArtifactId() )
&& CLEAR_FORKED_EXECUTION_GOAL.equals( binding.getGoal() );
}
}

View File

@ -36,8 +36,11 @@ import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.context.BuildContextManager;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.RuntimeInformation;
import org.apache.maven.lifecycle.LifecycleExecutionContext;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.monitor.event.EventDispatcher;
@ -92,6 +95,17 @@ public class DefaultPluginManager
extends AbstractLogEnabled
implements PluginManager, Contextualizable
{
private static final List RESERVED_GROUP_IDS;
static
{
List rgids = new ArrayList();
rgids.add( StateManagementUtils.GROUP_ID );
RESERVED_GROUP_IDS = rgids;
}
protected PlexusContainer container;
protected PluginDescriptorBuilder pluginDescriptorBuilder;
@ -119,6 +133,8 @@ public class DefaultPluginManager
protected PluginMappingManager pluginMappingManager;
private BuildContextManager buildContextManager;
// END component requirements
public DefaultPluginManager()
@ -157,6 +173,7 @@ public class DefaultPluginManager
// All version-resolution logic has been moved to DefaultPluginVersionManager.
if ( plugin.getVersion() == null )
{
getLogger().debug( "Resolving version for plugin: " + plugin.getKey() );
String version = pluginVersionManager.resolvePluginVersion( plugin.getGroupId(), plugin.getArtifactId(),
project, session );
plugin.setVersion( version );
@ -189,27 +206,38 @@ public class DefaultPluginManager
// the 'Can't find plexus container for plugin: xxx' error.
try
{
VersionRange versionRange = VersionRange.createFromVersionSpec( plugin.getVersion() );
// if the groupId is internal, don't try to resolve it...
if ( !RESERVED_GROUP_IDS.contains( plugin.getGroupId() ) )
{
VersionRange versionRange = VersionRange.createFromVersionSpec( plugin.getVersion() );
List remoteRepositories = new ArrayList();
List remoteRepositories = new ArrayList();
remoteRepositories.addAll( project.getPluginArtifactRepositories() );
remoteRepositories.addAll( project.getPluginArtifactRepositories() );
remoteRepositories.addAll( project.getRemoteArtifactRepositories() );
remoteRepositories.addAll( project.getRemoteArtifactRepositories() );
checkRequiredMavenVersion( plugin, localRepository, remoteRepositories );
checkRequiredMavenVersion( plugin, localRepository, remoteRepositories );
Artifact pluginArtifact =
artifactFactory.createPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), versionRange );
Artifact pluginArtifact =
artifactFactory.createPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), versionRange );
pluginArtifact = project.replaceWithActiveArtifact( pluginArtifact );
pluginArtifact = project.replaceWithActiveArtifact( pluginArtifact );
artifactResolver.resolve( pluginArtifact, project.getPluginArtifactRepositories(), localRepository );
artifactResolver.resolve( pluginArtifact, project.getPluginArtifactRepositories(), localRepository );
// if ( !pluginCollector.isPluginInstalled( plugin ) )
// {
// }
addPlugin( plugin, pluginArtifact, project, localRepository );
// if ( !pluginCollector.isPluginInstalled( plugin ) )
// {
// }
addPlugin( plugin, pluginArtifact, project, localRepository );
}
else
{
getLogger().debug( "Skipping resolution for Maven built-in plugin: " + plugin.getKey() );
PluginDescriptor pd = pluginCollector.getPluginDescriptor( plugin );
pd.setClassRealm( container.getContainerRealm() );
}
project.addPlugin( plugin );
}
@ -236,7 +264,9 @@ public class DefaultPluginManager
}
}
return pluginCollector.getPluginDescriptor( plugin );
PluginDescriptor pluginDescriptor = pluginCollector.getPluginDescriptor( plugin );
return pluginDescriptor;
}
/**
@ -548,23 +578,11 @@ public class DefaultPluginManager
PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
String goalId = mojoDescriptor.getGoal();
String groupId = pluginDescriptor.getGroupId();
String artifactId = pluginDescriptor.getArtifactId();
String executionId = mojoExecution.getExecutionId();
Xpp3Dom dom = project.getGoalConfiguration( groupId, artifactId, executionId, goalId );
Xpp3Dom reportDom = project.getReportConfiguration( groupId, artifactId, executionId );
dom = Xpp3Dom.mergeXpp3Dom( dom, reportDom );
if ( mojoExecution.getConfiguration() != null )
Xpp3Dom dom = (Xpp3Dom) mojoExecution.getConfiguration();
if ( dom != null )
{
dom = Xpp3Dom.mergeXpp3Dom( dom, mojoExecution.getConfiguration() );
// make a defensive copy, to keep things from getting polluted.
dom = new Xpp3Dom( dom );
}
plugin = getConfiguredMojo( session, dom, project, false, mojoExecution );
@ -597,6 +615,20 @@ public class DefaultPluginManager
plugin.execute();
// NEW: If the mojo that just executed is a report, store it in the LifecycleExecutionContext
// for reference by future mojos.
if ( plugin instanceof MavenReport )
{
LifecycleExecutionContext ctx = LifecycleExecutionContext.read( buildContextManager );
if ( ctx == null )
{
ctx = new LifecycleExecutionContext( project );
}
ctx.addReport( mojoDescriptor, (MavenReport) plugin );
ctx.store( buildContextManager );
}
container.setLookupRealm( oldRealm );
dispatcher.dispatchEnd( event, goalExecId );
@ -768,9 +800,16 @@ public class DefaultPluginManager
// PlexusConfiguration mergedConfiguration = mergeConfiguration( pomConfiguration,
// mojoDescriptor.getConfiguration() );
ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution,
pathTranslator, getLogger(),
project,
// NEW: Pass in the LifecycleExecutionContext so we have access to the current project,
// forked project stack (future), and reports.
LifecycleExecutionContext ctx = LifecycleExecutionContext.read( buildContextManager );
if ( ctx == null )
{
ctx = new LifecycleExecutionContext( project );
}
ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution, pathTranslator,
ctx, getLogger(),
session.getExecutionProperties() );
PlexusConfiguration extractedMojoConfiguration =
@ -1181,7 +1220,7 @@ public class DefaultPluginManager
}
// ----------------------------------------------------------------------
// Lifecycle
// LegacyLifecycle
// ----------------------------------------------------------------------
public void contextualize( Context context )

View File

@ -39,10 +39,6 @@ public class MojoExecution
private Xpp3Dom configuration;
private List forkedExecutions = new ArrayList();
private List reports;
public MojoExecution( MojoDescriptor mojoDescriptor )
{
this.mojoDescriptor = mojoDescriptor;
@ -79,26 +75,6 @@ public class MojoExecution
return configuration;
}
public void addMojoExecution( MojoExecution execution )
{
forkedExecutions.add( execution );
}
public void setReports( List reports )
{
this.reports = reports;
}
public List getReports()
{
return reports;
}
public List getForkedExecutions()
{
return forkedExecutions;
}
public void setConfiguration( Xpp3Dom configuration )
{
this.configuration = configuration;

View File

@ -20,6 +20,7 @@ package org.apache.maven.plugin;
*/
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleExecutionContext;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject;
@ -74,6 +75,49 @@ public class PluginParameterExpressionEvaluator
private final Properties properties;
private final LifecycleExecutionContext lifecycleExecutionContext;
public PluginParameterExpressionEvaluator( MavenSession context,
MojoExecution mojoExecution,
PathTranslator pathTranslator,
LifecycleExecutionContext lifecycleExecutionContext,
Logger logger,
Properties properties )
{
this.context = context;
this.mojoExecution = mojoExecution;
this.pathTranslator = pathTranslator;
this.lifecycleExecutionContext = lifecycleExecutionContext;
this.logger = logger;
this.properties = properties;
this.project = lifecycleExecutionContext.getCurrentProject();
String basedir = null;
if ( project != null )
{
File projectFile = project.getFile();
// this should always be the case for non-super POM instances...
if ( projectFile != null )
{
basedir = projectFile.getParentFile().getAbsolutePath();
}
}
if ( basedir == null )
{
basedir = System.getProperty( "user.dir" );
}
this.basedir = basedir;
}
/**
* @deprecated Use {@link PluginParameterExpressionEvaluator#PluginParameterExpressionEvaluator(MavenSession, MojoExecution, PathTranslator, LifecycleExecutionContext, Logger, Properties)}
* instead.
*/
public PluginParameterExpressionEvaluator( MavenSession context,
MojoExecution mojoExecution,
PathTranslator pathTranslator,
@ -84,10 +128,12 @@ public class PluginParameterExpressionEvaluator
this.context = context;
this.mojoExecution = mojoExecution;
this.pathTranslator = pathTranslator;
this.lifecycleExecutionContext = new LifecycleExecutionContext( project );
this.logger = logger;
this.project = project;
this.properties = properties;
this.project = project;
String basedir = null;
if ( project != null )
@ -192,7 +238,7 @@ public class PluginParameterExpressionEvaluator
}
else if ( "reports".equals( expression ) )
{
value = mojoExecution.getReports();
value = lifecycleExecutionContext.getReports();
}
else if ( "project".equals( expression ) )
{

View File

@ -0,0 +1,349 @@
package org.apache.maven.plugin.loader;
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.context.BuildContextManager;
import org.apache.maven.execution.SessionContext;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.plugin.InvalidPluginException;
import org.apache.maven.plugin.MavenPluginCollector;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginMappingManager;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.version.PluginVersionNotFoundException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import java.util.Iterator;
/**
* Responsible for loading plugins, reports, and any components contained therein. Will resolve
* plugin versions and plugin prefixes as necessary for plugin resolution.
*
* @author jdcasey
*
*/
public class DefaultPluginLoader
implements PluginLoader, LogEnabled
{
private Logger logger;
// FIXME: Move the functionality used from this into the PluginLoader when PluginManager refactor is complete.
private PluginManager pluginManager;
private PluginMappingManager pluginMappingManager;
private BuildContextManager buildContextManager;
private MavenPluginCollector pluginCollector;
/**
* Lookup a component with the specified role + roleHint in the plugin's {@link ClassRealm}.
* Load the plugin first.
*/
public Object loadPluginComponent( String role, String roleHint, Plugin plugin, MavenProject project )
throws ComponentLookupException, PluginLoaderException
{
loadPlugin( plugin, project );
try
{
return pluginManager.getPluginComponent( plugin, role, roleHint );
}
catch ( PluginManagerException e )
{
Throwable cause = e.getCause();
if ( cause != null && ( cause instanceof ComponentLookupException ) )
{
StringBuffer message = new StringBuffer();
message.append( "ComponentLookupException in PluginManager while looking up a component in the realm of: " );
message.append( plugin.getKey() );
message.append( ".\nReason: " );
message.append( cause.getMessage() );
message.append( "\n\nStack-Trace inside of PluginManager was:\n\n" );
StackTraceElement[] elements = e.getStackTrace();
for ( int i = 0; i < elements.length; i++ )
{
if ( elements[i].getClassName().indexOf( "PluginManager" ) < 0 )
{
break;
}
message.append( elements[i] );
}
logger.debug( message.toString() + "\n" );
throw (ComponentLookupException) cause;
}
else
{
throw new PluginLoaderException( plugin, "Failed to lookup plugin component. Reason: " + e.getMessage(), e );
}
}
}
/**
* Load the {@link PluginDescriptor} instance for the plugin implied by the specified MojoBinding,
* using the project for {@link ArtifactRepository} and other supplemental plugin information as
* necessary.
*/
public PluginDescriptor loadPlugin( MojoBinding mojoBinding, MavenProject project )
throws PluginLoaderException
{
PluginDescriptor pluginDescriptor = null;
Plugin plugin = new Plugin();
plugin.setGroupId( mojoBinding.getGroupId() );
plugin.setArtifactId( mojoBinding.getArtifactId() );
plugin.setVersion( mojoBinding.getVersion() );
pluginDescriptor = loadPlugin( plugin, project );
// fill in any blanks once we know more about this plugin.
if ( pluginDescriptor != null )
{
mojoBinding.setGroupId( pluginDescriptor.getGroupId() );
mojoBinding.setArtifactId( pluginDescriptor.getArtifactId() );
mojoBinding.setVersion( pluginDescriptor.getVersion() );
}
return pluginDescriptor;
}
/**
* Determine the appropriate {@link PluginDescriptor} instance for use with the specified plugin
* prefix, using the following strategies (in order):
* <br/>
* <ol>
* <li>Search for a plugin that has already been loaded with the specified prefix</li>
* <li>Search for a plugin configured in the POM that has a matching prefix</li>
* <li>Search the pluginGroups specified in the settings.xml for a matching plugin</li>
* <li>Use groupId == org.apache.maven.plugins, and artifactId == maven-&lt;prefix&gt;-plugin,
* and try to resolve based on that.</li>
* </ol>
*/
public PluginDescriptor findPluginForPrefix( String prefix, MavenProject project )
throws PluginLoaderException
{
PluginDescriptor pluginDescriptor = pluginCollector.getPluginDescriptorForPrefix( prefix );
if ( pluginDescriptor == null )
{
pluginDescriptor = loadFromProject( prefix, project );
}
if ( pluginDescriptor == null )
{
pluginDescriptor = loadByPrefix( prefix, project );
}
if ( pluginDescriptor == null )
{
Plugin plugin = new Plugin();
plugin.setArtifactId( PluginDescriptor.getDefaultPluginArtifactId( prefix ) );
pluginDescriptor = loadPlugin( plugin, project );
}
if ( pluginDescriptor == null )
{
throw new PluginLoaderException( "Cannot find plugin with prefix: " + prefix );
}
return pluginDescriptor;
}
/**
* Look for a plugin configured in the current project that has a prefix matching the one
* specified. Return the {@link PluginDescriptor} if a match is found.
*/
private PluginDescriptor loadFromProject( String prefix, MavenProject project )
throws PluginLoaderException
{
PluginDescriptor result = null;
for ( Iterator it = project.getBuildPlugins().iterator(); it.hasNext(); )
{
Plugin plugin = (Plugin) it.next();
PluginDescriptor pluginDescriptor = loadPlugin( plugin, project );
if ( prefix.equals( pluginDescriptor.getGoalPrefix() ) )
{
result = pluginDescriptor;
break;
}
}
return result;
}
/**
* Look for a plugin in the pluginGroups specified in the settings.xml that has a prefix
* matching the one specified. Return the {@link PluginDescriptor} if a match is found.
*/
private PluginDescriptor loadByPrefix( String prefix, MavenProject project )
throws PluginLoaderException
{
SessionContext ctx = SessionContext.read( buildContextManager );
Settings settings = ctx.getSettings();
Plugin plugin = pluginMappingManager.getByPrefix( prefix, settings.getPluginGroups(),
project.getPluginArtifactRepositories(), ctx.getLocalRepository() );
PluginDescriptor pluginDescriptor = null;
if ( plugin != null )
{
pluginDescriptor = loadPlugin( plugin, project );
}
return pluginDescriptor;
}
/**
* Load the {@link PluginDescriptor} instance for the specified plugin, using the project for
* the {@link ArtifactRepository} and other supplemental plugin information as necessary.
*/
public PluginDescriptor loadPlugin( Plugin plugin, MavenProject project )
throws PluginLoaderException
{
if ( plugin.getGroupId() == null )
{
plugin.setGroupId( PluginDescriptor.getDefaultPluginGroupId() );
}
SessionContext ctx = SessionContext.read( buildContextManager );
try
{
PluginDescriptor result = pluginManager.verifyPlugin( plugin, project, ctx.getSession() );
// 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 );
return result;
}
catch ( ArtifactResolutionException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginNotFoundException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginVersionResolutionException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( InvalidPluginException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginManagerException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginVersionNotFoundException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
}
public void enableLogging( Logger logger )
{
this.logger = logger;
}
/**
* Load the {@link PluginDescriptor} instance for the report plugin implied by the specified MojoBinding,
* using the project for {@link ArtifactRepository} and other supplemental report/plugin information as
* necessary.
*/
public PluginDescriptor loadReportPlugin( MojoBinding mojoBinding, MavenProject project )
throws PluginLoaderException
{
ReportPlugin plugin = new ReportPlugin();
plugin.setGroupId( mojoBinding.getGroupId() );
plugin.setArtifactId( mojoBinding.getArtifactId() );
plugin.setVersion( mojoBinding.getVersion() );
PluginDescriptor pluginDescriptor = loadReportPlugin( plugin, project );
mojoBinding.setVersion( pluginDescriptor.getVersion() );
return pluginDescriptor;
}
/**
* Load the {@link PluginDescriptor} instance for the specified report plugin, using the project for
* the {@link ArtifactRepository} and other supplemental report/plugin information as necessary.
*/
public PluginDescriptor loadReportPlugin( ReportPlugin plugin, MavenProject project )
throws PluginLoaderException
{
// TODO: Shouldn't we be injecting pluginManagement info here??
SessionContext ctx = SessionContext.read( buildContextManager );
try
{
return pluginManager.verifyReportPlugin( plugin, project, ctx.getSession() );
}
catch ( ArtifactResolutionException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( ArtifactNotFoundException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginNotFoundException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginVersionResolutionException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( InvalidPluginException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginManagerException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
catch ( PluginVersionNotFoundException e )
{
throw new PluginLoaderException( plugin, "Failed to load plugin. Reason: " + e.getMessage(), e );
}
}
}

View File

@ -0,0 +1,74 @@
package org.apache.maven.plugin.loader;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
/**
* Responsible for loading plugins, reports, and any components contained therein. Will resolve
* plugin versions and plugin prefixes as necessary for plugin resolution.
*
* @author jdcasey
*
*/
public interface PluginLoader
{
/**
* Lookup a component with the specified role + roleHint in the plugin's {@link ClassRealm}.
* Load the plugin first.
*/
Object loadPluginComponent( String role, String roleHint, Plugin plugin, MavenProject project )
throws ComponentLookupException, PluginLoaderException;
/**
* Load the {@link PluginDescriptor} instance for the specified plugin, using the project for
* the {@link ArtifactRepository} and other supplemental plugin information as necessary.
*/
PluginDescriptor loadPlugin( Plugin plugin, MavenProject project )
throws PluginLoaderException;
/**
* Load the {@link PluginDescriptor} instance for the plugin implied by the specified MojoBinding,
* using the project for {@link ArtifactRepository} and other supplemental plugin information as
* necessary.
*/
PluginDescriptor loadPlugin( MojoBinding mojoBinding, MavenProject project )
throws PluginLoaderException;
/**
* Load the {@link PluginDescriptor} instance for the specified report plugin, using the project for
* the {@link ArtifactRepository} and other supplemental report/plugin information as necessary.
*/
PluginDescriptor loadReportPlugin( ReportPlugin reportPlugin, MavenProject project )
throws PluginLoaderException;
/**
* Load the {@link PluginDescriptor} instance for the report plugin implied by the specified MojoBinding,
* using the project for {@link ArtifactRepository} and other supplemental report/plugin information as
* necessary.
*/
PluginDescriptor loadReportPlugin( MojoBinding mojoBinding, MavenProject project )
throws PluginLoaderException;
/**
* Determine the appropriate {@link PluginDescriptor} instance for use with the specified plugin
* prefix, using the following strategies (in order):
* <br/>
* <ol>
* <li>Search for a plugin that has already been loaded with the specified prefix</li>
* <li>Search for a plugin configured in the POM that has a matching prefix</li>
* <li>Search the pluginGroups specified in the settings.xml for a matching plugin</li>
* <li>Use groupId == org.apache.maven.plugins, and artifactId == maven-&lt;prefix&gt;-plugin,
* and try to resolve based on that.</li>
* </ol>
*/
PluginDescriptor findPluginForPrefix( String prefix, MavenProject project )
throws PluginLoaderException;
}

View File

@ -0,0 +1,58 @@
package org.apache.maven.plugin.loader;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.ReportPlugin;
/**
* Signifies a failure to load a plugin. This is used to abstract the specific errors which may be
* encountered at lower levels, and provide a dependable interface to the plugin-loading framework.
*
* @author jdcasey
*
*/
public class PluginLoaderException
extends Exception
{
private String pluginKey;
public PluginLoaderException( Plugin plugin, String message, Throwable cause )
{
super( message, cause );
this.pluginKey = plugin.getKey();
}
public PluginLoaderException( Plugin plugin, String message )
{
super( message );
this.pluginKey = plugin.getKey();
}
public PluginLoaderException( String message )
{
super( message );
}
public PluginLoaderException( String message, Throwable cause )
{
super( message, cause );
}
public PluginLoaderException( ReportPlugin plugin, String message, Throwable cause )
{
super( message, cause );
this.pluginKey = plugin.getKey();
}
public PluginLoaderException( ReportPlugin plugin, String message )
{
super( message );
this.pluginKey = plugin.getKey();
}
public String getPluginKey()
{
return pluginKey;
}
}

View File

@ -90,6 +90,7 @@ public class DefaultPluginVersionManager
// first pass...if the plugin is specified in the pom, try to retrieve the version from there.
String version = getVersionFromPluginConfig( groupId, artifactId, project, resolveAsReportPlugin );
getLogger().debug( "Version from POM: " + version );
// NOTE: We CANNOT check the current project version here, so delay it until later.
// It will prevent plugins from building themselves, if they are part of the lifecycle mapping.
@ -107,6 +108,7 @@ public class DefaultPluginVersionManager
}
}
}
getLogger().debug( "Version from another POM in the reactor: " + version );
// third pass...we're always checking for latest install/deploy, so retrieve the version for LATEST metadata and
// also set that resolved version as the <useVersion/> in settings.xml.
@ -114,6 +116,7 @@ public class DefaultPluginVersionManager
{
// 1. resolve the version to be used
version = resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.LATEST_VERSION );
getLogger().debug( "Version from LATEST metadata: " + version );
}
// final pass...retrieve the version for RELEASE and also set that resolved version as the <useVersion/>
@ -122,6 +125,7 @@ public class DefaultPluginVersionManager
{
// 1. resolve the version to be used
version = resolveMetaVersion( groupId, artifactId, project, localRepository, Artifact.RELEASE_VERSION );
getLogger().debug( "Version from RELEASE metadata: " + version );
}
// if we're still empty here, and the current project matches the plugin in question, use the current project's
@ -130,6 +134,7 @@ public class DefaultPluginVersionManager
project.getArtifactId().equals( artifactId ) )
{
version = project.getVersion();
getLogger().debug( "Version from POM itself (this project IS the plugin project): " + version );
}
// if we still haven't found a version, then fail early before we get into the update goop.

View File

@ -0,0 +1,117 @@
<plugin>
<description>Maven Internal State-Management Plugins</description>
<groupId>org.apache.maven.plugins.internal</groupId>
<artifactId>maven-state-management</artifactId>
<version>2.1</version>
<goalPrefix>statemgmt</goalPrefix>
<isolatedRealm>false</isolatedRealm>
<inheritedByDefault>true</inheritedByDefault>
<mojos>
<mojo>
<goal>start-fork</goal>
<description>Setup the appropriate build state to initiate a forked execution.</description>
<requiresDirectInvocation>false</requiresDirectInvocation>
<requiresProject>true</requiresProject>
<requiresReports>false</requiresReports>
<aggregator>false</aggregator>
<requiresOnline>false</requiresOnline>
<inheritedByDefault>true</inheritedByDefault>
<implementation>org.apache.maven.lifecycle.statemgmt.StartForkedExecutionMojo</implementation>
<language>java</language>
<instantiationStrategy>per-lookup</instantiationStrategy>
<executionStrategy>once-per-session</executionStrategy>
<parameters>
<parameter>
<name>project</name>
<type>org.apache.maven.project.MavenProject</type>
<required>true</required>
<editable>false</editable>
<description>The current MavenProject instance, which will have a new executionProject set after execution.</description>
</parameter>
<parameter>
<name>forkId</name>
<type>int</type>
<required>true</required>
<editable>true</editable>
<description>The current fork identifier.</description>
</parameter>
</parameters>
<configuration>
<project implementation="org.apache.maven.project.MavenProject" default-value="${project}"/>
<forkId implementation="int" default-value="-1">${forkId}</forkId>
</configuration>
<requirements>
<requirement>
<role>org.apache.maven.context.BuildContextManager</role>
<field-name>buildContextManager</field-name>
</requirement>
</requirements>
</mojo>
<mojo>
<goal>end-fork</goal>
<description>Restore the non-fork currentProject instance, for use in the forking mojo.</description>
<requiresDirectInvocation>false</requiresDirectInvocation>
<requiresProject>true</requiresProject>
<requiresReports>false</requiresReports>
<aggregator>false</aggregator>
<requiresOnline>false</requiresOnline>
<inheritedByDefault>true</inheritedByDefault>
<implementation>org.apache.maven.lifecycle.statemgmt.EndForkedExecutionMojo</implementation>
<language>java</language>
<instantiationStrategy>per-lookup</instantiationStrategy>
<executionStrategy>once-per-session</executionStrategy>
<parameters>
<parameter>
<name>forkId</name>
<type>int</type>
<required>true</required>
<editable>true</editable>
<description>The current fork identifier.</description>
</parameter>
</parameters>
<configuration>
<forkId implementation="int" default-value="-1">${forkId}</forkId>
</configuration>
<requirements>
<requirement>
<role>org.apache.maven.context.BuildContextManager</role>
<field-name>buildContextManager</field-name>
</requirement>
</requirements>
</mojo>
<mojo>
<goal>clear-fork-context</goal>
<description>Tear down any build state used during the previous forked execution.</description>
<requiresDirectInvocation>false</requiresDirectInvocation>
<requiresProject>true</requiresProject>
<requiresReports>false</requiresReports>
<aggregator>false</aggregator>
<requiresOnline>false</requiresOnline>
<inheritedByDefault>true</inheritedByDefault>
<implementation>org.apache.maven.lifecycle.statemgmt.ClearForkedContextMojo</implementation>
<language>java</language>
<instantiationStrategy>per-lookup</instantiationStrategy>
<executionStrategy>once-per-session</executionStrategy>
<parameters>
<parameter>
<name>project</name>
<type>org.apache.maven.project.MavenProject</type>
<required>true</required>
<editable>false</editable>
<description>The current MavenProject instance, which will have the current executionProject cleared after execution.</description>
</parameter>
<parameter>
<name>forkId</name>
<type>int</type>
<required>true</required>
<editable>true</editable>
<description>The current fork identifier.</description>
</parameter>
</parameters>
<configuration>
<project implementation="org.apache.maven.project.MavenProject" default-value="${project}"/>
<forkId implementation="int" default-value="-1">${forkId}</forkId>
</configuration>
</mojo>
</mojos>
</plugin>

View File

@ -52,6 +52,9 @@ under the License.
<role>org.apache.maven.plugin.PluginManager</role>
<implementation>org.apache.maven.plugin.DefaultPluginManager</implementation>
<requirements>
<requirement>
<role>org.apache.maven.context.BuildContextManager</role>
</requirement>
<requirement>
<role>org.apache.maven.ArtifactFilterManager</role>
</requirement>
@ -260,102 +263,28 @@ under the License.
<role>org.apache.maven.lifecycle.LifecycleExecutor</role>
<implementation>org.apache.maven.lifecycle.DefaultLifecycleExecutor</implementation>
<requirements>
<requirement>
<role>org.apache.maven.context.BuildContextManager</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.LifecycleBindingManager</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.loader.PluginLoader</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.PluginManager</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.handler.manager.ArtifactHandlerManager</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.plan.BuildPlanner</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.MojoBindingFactory</role>
</requirement>
</requirements>
<configuration>
<lifecycles>
<lifecycle>
<id>default</id>
<!-- START SNIPPET: lifecycle -->
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>prepare-package</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>
<!-- END SNIPPET: lifecycle -->
</lifecycle>
<lifecycle>
<id>clean</id>
<phases>
<phase>pre-clean</phase>
<phase>clean</phase>
<phase>post-clean</phase>
</phases>
<default-phases>
<clean>org.apache.maven.plugins:maven-clean-plugin:clean</clean>
</default-phases>
</lifecycle>
<lifecycle>
<id>site</id>
<phases>
<phase>pre-site</phase>
<phase>site</phase>
<phase>post-site</phase>
<phase>site-deploy</phase>
</phases>
<default-phases>
<site>org.apache.maven.plugins:maven-site-plugin:site</site>
<site-deploy>org.apache.maven.plugins:maven-site-plugin:deploy</site-deploy>
</default-phases>
</lifecycle>
</lifecycles>
<!-- START SNIPPET: default-reports -->
<defaultReports>
<report>org.apache.maven.plugins:maven-project-info-reports-plugin</report>
<!-- TODO: currently in mojo - should they be defaults any more?
<report>org.apache.maven.plugins:maven-checkstyle-plugin</report>
<report>org.apache.maven.plugins:maven-javadoc-plugin</report>
<report>org.apache.maven.plugins:maven-changelog-plugin</report>
<report>org.apache.maven.plugins:maven-surefire-report-plugin</report>
<report>org.apache.maven.plugins:maven-jdepend-plugin</report>
<report>org.apache.maven.plugins:maven-jxr-plugin</report>
<report>org.apache.maven.plugins:maven-taglist-plugin</report>
-->
</defaultReports>
<!-- END SNIPPET: default-reports -->
<!-- START SNIPPET: default-lifecycle -->
<!-- NOT USED, ACCORDING TO CODE.
<defaultPhases>
<process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
<compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
<process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
<test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
<test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
<package>
org.apache.maven.plugins:maven-jar-plugin:jar,
org.apache.maven.plugins:maven-source-plugin:jar
</package>
<install>org.apache.maven.plugins:maven-install-plugin:install</install>
<deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
</defaultPhases>
-->
<!-- END SNIPPET: default-lifecycle -->
</configuration>
</component>
<!-- TODO: issues with the lifecycle:
@ -621,5 +550,182 @@ under the License.
</requirement>
</requirements>
</component>
<component>
<role>org.codehaus.plexus.collections.ActiveMap</role>
<role-hint>lifecycle-loaders-by-packaging</role-hint>
<implementation>org.codehaus.plexus.collections.DefaultActiveMap</implementation>
<configuration>
<role>org.apache.maven.lifecycle.LifecycleBindingLoader</role>
</configuration>
</component>
<component>
<role>org.codehaus.plexus.collections.ActiveMap</role>
<role-hint>legacy-lifecycle-mappings-by-packaging</role-hint>
<implementation>org.codehaus.plexus.collections.DefaultActiveMap</implementation>
<configuration>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
</configuration>
</component>
<component>
<role>org.apache.maven.plugin.loader.PluginLoader</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.plugin.loader.DefaultPluginLoader</implementation>
<requirements>
<requirement>
<role>org.apache.maven.plugin.MavenPluginCollector</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.PluginManager</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.PluginMappingManager</role>
</requirement>
<requirement>
<role>org.apache.maven.context.BuildContextManager</role>
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.lifecycle.binding.LifecycleBindingManager</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.lifecycle.binding.DefaultLifecycleBindingManager</implementation>
<requirements>
<requirement>
<role>org.apache.maven.plugin.loader.PluginLoader</role>
</requirement>
<requirement>
<role>org.codehaus.plexus.collections.ActiveMap</role>
<role-hint>lifecycle-loaders-by-packaging</role-hint>
<field-name>bindingsByPackaging</field-name>
</requirement>
<requirement>
<role>org.codehaus.plexus.collections.ActiveMap</role>
<role-hint>legacy-lifecycle-mappings-by-packaging</role-hint>
<field-name>legacyMappingsByPackaging</field-name>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.MojoBindingFactory</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.LegacyLifecycleMappingParser</role>
</requirement>
</requirements>
<configuration>
<legacyLifecycles>
<legacyLifecycle>
<id>default</id>
<!-- START SNIPPET: lifecycle -->
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>prepare-package</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>
<!-- END SNIPPET: lifecycle -->
</legacyLifecycle>
<legacyLifecycle>
<id>clean</id>
<phases>
<phase>pre-clean</phase>
<phase>clean</phase>
<phase>post-clean</phase>
</phases>
<default-phases>
<clean>org.apache.maven.plugins:maven-clean-plugin:clean</clean>
</default-phases>
</legacyLifecycle>
<legacyLifecycle>
<id>site</id>
<phases>
<phase>pre-site</phase>
<phase>site</phase>
<phase>post-site</phase>
<phase>site-deploy</phase>
</phases>
<default-phases>
<site>org.apache.maven.plugins:maven-site-plugin:site</site>
<site-deploy>org.apache.maven.plugins:maven-site-plugin:deploy</site-deploy>
</default-phases>
</legacyLifecycle>
</legacyLifecycles>
<!-- START SNIPPET: default-reports -->
<defaultReports>
<report>org.apache.maven.plugins:maven-project-info-reports-plugin</report>
<!-- TODO: currently in mojo - should they be defaults any more?
<report>org.apache.maven.plugins:maven-checkstyle-plugin</report>
<report>org.apache.maven.plugins:maven-javadoc-plugin</report>
<report>org.apache.maven.plugins:maven-changelog-plugin</report>
<report>org.apache.maven.plugins:maven-surefire-report-plugin</report>
<report>org.apache.maven.plugins:maven-jdepend-plugin</report>
<report>org.apache.maven.plugins:maven-jxr-plugin</report>
<report>org.apache.maven.plugins:maven-taglist-plugin</report>
-->
</defaultReports>
<!-- END SNIPPET: default-reports -->
</configuration>
</component>
<component>
<role>org.apache.maven.lifecycle.plan.BuildPlanner</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.lifecycle.plan.DefaultBuildPlanner</implementation>
<requirements>
<requirement>
<role>org.apache.maven.plugin.loader.PluginLoader</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.LifecycleBindingManager</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.binding.MojoBindingFactory</role>
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.lifecycle.binding.MojoBindingFactory</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.lifecycle.binding.DefaultMojoBindingFactory</implementation>
<requirements>
<requirement>
<role>org.apache.maven.plugin.loader.PluginLoader</role>
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.lifecycle.binding.LegacyLifecycleMappingParser</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.lifecycle.binding.LegacyLifecycleMappingParser</implementation>
<requirements>
<requirement>
<role>org.apache.maven.lifecycle.binding.MojoBindingFactory</role>
</requirement>
</requirements>
</component>
</components>
</component-set>

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.binding.LegacyLifecycleMappingParser;
import org.apache.maven.lifecycle.binding.LegacyLifecycleParsingTestComponent;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.lifecycle.model.BuildBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.codehaus.plexus.PlexusTestCase;
import java.util.List;
public class LegacyLifecycleMappingParserTest
extends PlexusTestCase
{
private LegacyLifecycleParsingTestComponent testComponent;
private LifecycleMapping testMapping;
private LifecycleMapping testMapping2;
private LegacyLifecycleMappingParser parser;
public void setUp()
throws Exception
{
super.setUp();
parser = (LegacyLifecycleMappingParser) lookup( LegacyLifecycleMappingParser.ROLE, "default" );
testComponent = (LegacyLifecycleParsingTestComponent) lookup( LegacyLifecycleParsingTestComponent.ROLE, "default" );
testMapping = (LifecycleMapping) lookup( LifecycleMapping.ROLE, "test-mapping" );
testMapping2 = (LifecycleMapping) lookup( LifecycleMapping.ROLE, "test-mapping2" );
}
public void tearDown()
throws Exception
{
release( testComponent );
release( testMapping );
release( testMapping2 );
super.tearDown();
}
public void testParseDefaultMappings_UsingExistingDefaultMappings()
throws LifecycleSpecificationException
{
List lifecycles = testComponent.getLifecycles();
LifecycleBindings bindings = parser.parseDefaultMappings( lifecycles );
// <clean>org.apache.maven.plugins:maven-clean-plugin:clean</clean>
List cleanPhase = bindings.getCleanBinding().getClean().getBindings();
assertEquals( 1, cleanPhase.size() );
MojoBinding binding = (MojoBinding) cleanPhase.get( 0 );
assertMojo( "org.apache.maven.plugins", "maven-clean-plugin", "clean", binding );
// <site>org.apache.maven.plugins:maven-site-plugin:site</site>
List sitePhase = bindings.getSiteBinding().getSite().getBindings();
assertEquals( 1, sitePhase.size() );
binding = (MojoBinding) sitePhase.get( 0 );
assertMojo( "org.apache.maven.plugins", "maven-site-plugin", "site", binding );
// <site-deploy>org.apache.maven.plugins:maven-site-plugin:deploy</site-deploy>
List siteDeployPhase = bindings.getSiteBinding().getSiteDeploy().getBindings();
assertEquals( 1, siteDeployPhase.size() );
binding = (MojoBinding) siteDeployPhase.get( 0 );
assertMojo( "org.apache.maven.plugins", "maven-site-plugin", "deploy", binding );
}
private void assertMojo( String groupId, String artifactId, String goal, MojoBinding binding )
{
assertEquals( groupId, binding.getGroupId() );
assertEquals( artifactId, binding.getArtifactId() );
assertEquals( goal, binding.getGoal() );
}
public void testParseMappings_SparselyPopulatedMappings()
throws LifecycleSpecificationException
{
LifecycleBindings bindings = parser.parseMappings( testMapping, "test-mapping" );
BuildBinding bb = bindings.getBuildBinding();
assertNotNull( bb );
// <phases>
// <package>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</package>
// <install>org.apache.maven.plugins:maven-install-plugin:install</install>
// <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
// </phases>
// <optional-mojos>
// <optional-mojo>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</optional-mojo>
// </optional-mojos>
List mojos = bb.getCreatePackage().getBindings();
assertEquals( 1, mojos.size() );
assertMojo( "org.apache.maven.plugins", "maven-site-plugin", "attach-descriptor", (MojoBinding) mojos.get( 0 ) );
assertTrue( ( (MojoBinding) mojos.get( 0 ) ).isOptional() );
mojos = bb.getInstall().getBindings();
assertEquals( 1, mojos.size() );
assertMojo( "org.apache.maven.plugins", "maven-install-plugin", "install", (MojoBinding) mojos.get( 0 ) );
assertFalse( ( (MojoBinding) mojos.get( 0 ) ).isOptional() );
mojos = bb.getDeploy().getBindings();
assertEquals( 1, mojos.size() );
assertMojo( "org.apache.maven.plugins", "maven-deploy-plugin", "deploy", (MojoBinding) mojos.get( 0 ) );
assertFalse( ( (MojoBinding) mojos.get( 0 ) ).isOptional() );
}
public void testParseMappings_MappingsWithTwoBindingsInOnePhase()
throws LifecycleSpecificationException
{
LifecycleBindings bindings = parser.parseMappings( testMapping2, "test-mapping2" );
BuildBinding bb = bindings.getBuildBinding();
assertNotNull( bb );
// <phases>
// <package>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</package>
// <install>org.apache.maven.plugins:maven-install-plugin:install</install>
// <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
// </phases>
// <optional-mojos>
// <optional-mojo>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</optional-mojo>
// </optional-mojos>
List mojos = bb.getCreatePackage().getBindings();
assertEquals( 2, mojos.size() );
assertMojo( "org.apache.maven.plugins", "maven-site-plugin", "attach-descriptor", (MojoBinding) mojos.get( 0 ) );
assertTrue( ( (MojoBinding) mojos.get( 0 ) ).isOptional() );
assertMojo( "org.apache.maven.plugins", "maven-clean-plugin", "clean", (MojoBinding) mojos.get( 1 ) );
mojos = bb.getInstall().getBindings();
assertEquals( 1, mojos.size() );
assertMojo( "org.apache.maven.plugins", "maven-install-plugin", "install", (MojoBinding) mojos.get( 0 ) );
assertFalse( ( (MojoBinding) mojos.get( 0 ) ).isOptional() );
mojos = bb.getDeploy().getBindings();
assertEquals( 1, mojos.size() );
assertMojo( "org.apache.maven.plugins", "maven-deploy-plugin", "deploy", (MojoBinding) mojos.get( 0 ) );
assertFalse( ( (MojoBinding) mojos.get( 0 ) ).isOptional() );
}
}

View File

@ -0,0 +1,362 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.plan.LifecyclePlannerException;
import org.apache.maven.model.Build;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
public class DefaultLifecycleBindingManagerTest
extends PlexusTestCase
{
private LifecycleBindingManager mgr;
public void setUp()
throws Exception
{
super.setUp();
this.mgr = (LifecycleBindingManager) lookup( LifecycleBindingManager.ROLE, "default" );
}
public void testLookup()
{
assertNotNull( mgr );
}
public void testGetBindingsForPackaging_TestMergePluginConfigToBinding()
throws LifecycleLoaderException, LifecycleSpecificationException
{
Model model = new Model();
model.setGroupId( "group" );
model.setArtifactId( "artifact" );
model.setVersion( "1" );
Build build = new Build();
model.setBuild( build );
Plugin plugin = new Plugin();
build.addPlugin( plugin );
plugin.setGroupId( "org.apache.maven.plugins" );
plugin.setArtifactId( "maven-compiler-plugin" );
Properties pluginConfig = new Properties();
pluginConfig.setProperty( "test", "value" );
pluginConfig.setProperty( "test2", "other-value" );
plugin.setConfiguration( createConfiguration( pluginConfig ) );
MavenProject project = new MavenProject( model );
LifecycleBindings lifecycleBindings = mgr.getBindingsForPackaging( project );
List bindings = lifecycleBindings.getBuildBinding().getCompile().getBindings();
assertNotNull( bindings );
assertEquals( 1, bindings.size() );
MojoBinding binding = (MojoBinding) bindings.get( 0 );
Xpp3Dom config = (Xpp3Dom) binding.getConfiguration();
assertNotNull( config );
assertEquals( "value", config.getChild( "test" ).getValue() );
assertEquals( "other-value", config.getChild( "test2" ).getValue() );
}
public void testGetBindingsForPackaging_TestMergePluginManagementConfigToBinding()
throws LifecycleLoaderException, LifecycleSpecificationException
{
Model model = new Model();
model.setGroupId( "group" );
model.setArtifactId( "artifact" );
model.setVersion( "1" );
Build build = new Build();
model.setBuild( build );
PluginManagement plugMgmt = new PluginManagement();
build.setPluginManagement( plugMgmt );
Plugin plugin = new Plugin();
plugMgmt.addPlugin( plugin );
plugin.setGroupId( "org.apache.maven.plugins" );
plugin.setArtifactId( "maven-compiler-plugin" );
Properties pluginConfig = new Properties();
pluginConfig.setProperty( "test", "value" );
pluginConfig.setProperty( "test2", "other-value" );
plugin.setConfiguration( createConfiguration( pluginConfig ) );
MavenProject project = new MavenProject( model );
LifecycleBindings lifecycleBindings = mgr.getBindingsForPackaging( project );
List bindings = lifecycleBindings.getBuildBinding().getCompile().getBindings();
assertNotNull( bindings );
assertEquals( 1, bindings.size() );
MojoBinding binding = (MojoBinding) bindings.get( 0 );
Xpp3Dom config = (Xpp3Dom) binding.getConfiguration();
assertNotNull( config );
assertEquals( "value", config.getChild( "test" ).getValue() );
assertEquals( "other-value", config.getChild( "test2" ).getValue() );
}
public void testGetProjectCustomBindings_ExecutionConfigShouldOverridePluginConfig()
throws LifecycleLoaderException, LifecycleSpecificationException
{
Model model = new Model();
model.setGroupId( "group" );
model.setArtifactId( "artifact" );
model.setVersion( "1" );
Build build = new Build();
model.setBuild( build );
Plugin plugin = new Plugin();
build.addPlugin( plugin );
plugin.setGroupId( "plugin.group" );
plugin.setArtifactId( "plugin-artifact" );
plugin.setVersion( "1" );
Properties pluginConfig = new Properties();
pluginConfig.setProperty( "test", "value" );
pluginConfig.setProperty( "test2", "other-value" );
plugin.setConfiguration( createConfiguration( pluginConfig ) );
PluginExecution exec = new PluginExecution();
plugin.addExecution( exec );
exec.setId( "test-execution" );
exec.setPhase( "validate" );
exec.setGoals( Collections.singletonList( "goal" ) );
Properties execConfig = new Properties();
execConfig.setProperty( "test", "value2" );
exec.setConfiguration( createConfiguration( execConfig ) );
MavenProject project = new MavenProject( model );
LifecycleBindings lifecycleBindings = mgr.getProjectCustomBindings( project );
List bindings = lifecycleBindings.getBuildBinding().getValidate().getBindings();
assertNotNull( bindings );
assertEquals( 1, bindings.size() );
MojoBinding binding = (MojoBinding) bindings.get( 0 );
Xpp3Dom config = (Xpp3Dom) binding.getConfiguration();
assertEquals( "value2", config.getChild( "test" ).getValue() );
assertEquals( "other-value", config.getChild( "test2" ).getValue() );
}
private Object createConfiguration( Properties configProperties )
{
Xpp3Dom config = new Xpp3Dom( "configuration" );
for ( Iterator it = configProperties.keySet().iterator(); it.hasNext(); )
{
String key = (String) it.next();
String value = configProperties.getProperty( key );
Xpp3Dom child = new Xpp3Dom( key );
child.setValue( value );
config.addChild( child );
}
return config;
}
public void testAssembleMojoBindingList_ReturnBindingsUpToStopPhaseForSinglePhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
bindings.getCleanBinding().getPostClean().addBinding( newMojoBinding( "goal", "artifact", "post-clean" ) );
List result = mgr.assembleMojoBindingList( Collections.singletonList( "clean" ), bindings, new MavenProject( new Model() ) );
assertEquals( 2, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
}
public void testAssembleMojoBindingList_CombinePreviousBindingsWhenSubsetOfNextBindingsForTwoPhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "post-clean" ) );
List tasks = new ArrayList( 2 );
tasks.add( "clean" );
tasks.add( "post-clean" );
List result = mgr.assembleMojoBindingList( tasks, bindings, new MavenProject( new Model() ) );
assertEquals( 3, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
binding = (MojoBinding) result.get( 2 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "post-clean", binding.getGoal() );
}
public void testAssembleMojoBindingList_IgnoreSuccessiveBindingsWhenSameAsPreviousOnesForTwoPhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
List tasks = new ArrayList( 2 );
tasks.add( "clean" );
tasks.add( "post-clean" );
List result = mgr.assembleMojoBindingList( tasks, bindings, new MavenProject( new Model() ) );
assertEquals( 2, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
}
public void testAssembleMojoBindingList_ReturnBindingsUpToStopPhasesForTwoPhaseTaskList()
throws LifecycleSpecificationException, LifecyclePlannerException, LifecycleLoaderException
{
LifecycleBindings bindings = new LifecycleBindings();
bindings.getCleanBinding().getPreClean().addBinding( newMojoBinding( "goal", "artifact", "pre-clean" ) );
bindings.getCleanBinding().getClean().addBinding( newMojoBinding( "goal", "artifact", "clean" ) );
bindings.getCleanBinding().getPostClean().addBinding( newMojoBinding( "goal", "artifact", "post-clean" ) );
bindings.getBuildBinding().getInitialize().addBinding( newMojoBinding( "goal", "artifact", "initialize" ) );
bindings.getBuildBinding().getCompile().addBinding( newMojoBinding( "goal", "artifact", "compile" ) );
bindings.getBuildBinding().getCreatePackage().addBinding( newMojoBinding( "goal", "artifact", "package" ) );
List tasks = new ArrayList( 2 );
tasks.add( "clean" );
tasks.add( "compile" );
List result = mgr.assembleMojoBindingList( tasks, bindings, new MavenProject( new Model() ) );
assertEquals( 4, result.size() );
MojoBinding binding = (MojoBinding) result.get( 0 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "pre-clean", binding.getGoal() );
binding = (MojoBinding) result.get( 1 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "clean", binding.getGoal() );
binding = (MojoBinding) result.get( 2 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "initialize", binding.getGoal() );
binding = (MojoBinding) result.get( 3 );
assertEquals( "goal", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "compile", binding.getGoal() );
}
public void testAssembleMojoBindingList_ThrowErrorForInvalidPhaseNameAsSingletonTaskList()
throws LifecyclePlannerException, LifecycleLoaderException
{
try
{
mgr.assembleMojoBindingList( Collections.singletonList( "dud" ), new LifecycleBindings(),
new MavenProject( new Model() ) );
fail( "Should fail with LifecycleSpecificationException due to invalid phase/direct mojo reference." );
}
catch ( LifecycleSpecificationException e )
{
// expected.
}
}
private MojoBinding newMojoBinding( String groupId, String artifactId, String goal )
{
MojoBinding binding = new MojoBinding();
binding.setGroupId( groupId );
binding.setArtifactId( artifactId );
binding.setGoal( goal );
return binding;
}
}

View File

@ -0,0 +1,83 @@
package org.apache.maven.lifecycle.binding;
import org.apache.maven.lifecycle.LifecycleLoaderException;
import org.apache.maven.lifecycle.LifecycleSpecificationException;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusTestCase;
public class DefaultMojoBindingFactoryTest
extends PlexusTestCase
{
private MojoBindingFactory factory;
public void setUp() throws Exception
{
super.setUp();
factory = (MojoBindingFactory) lookup( MojoBindingFactory.ROLE, "default" );
}
public void testPrefixGoalSpec_PrefixReferenceNotAllowed()
throws LifecycleLoaderException
{
String spec = "prefix:goal";
try
{
factory.parseMojoBinding( spec, new MavenProject( new Model() ), false );
fail( "Should fail when prefix references are not allowed." );
}
catch ( LifecycleSpecificationException e )
{
// expected.
}
}
public void testGroupIdArtifactIdGoalSpec_ShouldParseCorrectly()
throws LifecycleSpecificationException, LifecycleLoaderException
{
String spec = "group:artifact:goal";
MojoBinding binding = factory.parseMojoBinding( spec, new MavenProject( new Model() ), false );
assertEquals( "group", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertNull( binding.getVersion() );
assertEquals( "goal", binding.getGoal() );
}
public void testGroupIdArtifactIdVersionGoalSpec_ShouldParseCorrectly()
throws LifecycleSpecificationException, LifecycleLoaderException
{
String spec = "group:artifact:version:goal";
MojoBinding binding = factory.parseMojoBinding( spec, new MavenProject( new Model() ), false );
assertEquals( "group", binding.getGroupId() );
assertEquals( "artifact", binding.getArtifactId() );
assertEquals( "version", binding.getVersion() );
assertEquals( "goal", binding.getGoal() );
}
public void testSpecWithTooManyParts_ShouldFail()
throws LifecycleLoaderException
{
String spec = "group:artifact:version:type:goal";
try
{
factory.parseMojoBinding( spec, new MavenProject( new Model() ), false );
fail( "Should fail because spec has too many parts (type part is not allowed)." );
}
catch ( LifecycleSpecificationException e )
{
// expected
}
}
}

View File

@ -0,0 +1,16 @@
package org.apache.maven.lifecycle.binding;
import java.util.List;
public class LegacyLifecycleParsingTestComponent
{
public static final String ROLE = LegacyLifecycleParsingTestComponent.class.getName();
private List legacyLifecycles;
public List getLifecycles()
{
return legacyLifecycles;
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
version=2.1-SNAPSHOT

View File

@ -0,0 +1,112 @@
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.binding.LegacyLifecycleParsingTestComponent</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.lifecycle.binding.LegacyLifecycleParsingTestComponent</implementation>
<configuration>
<legacyLifecycles>
<legacyLifecycle>
<id>default</id>
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>prepare-package</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>
</legacyLifecycle>
<legacyLifecycle>
<id>clean</id>
<phases>
<phase>pre-clean</phase>
<phase>clean</phase>
<phase>post-clean</phase>
</phases>
<default-phases>
<clean>org.apache.maven.plugins:maven-clean-plugin:clean</clean>
</default-phases>
</legacyLifecycle>
<legacyLifecycle>
<id>site</id>
<phases>
<phase>pre-site</phase>
<phase>site</phase>
<phase>post-site</phase>
<phase>site-deploy</phase>
</phases>
<default-phases>
<site>org.apache.maven.plugins:maven-site-plugin:site</site>
<site-deploy>org.apache.maven.plugins:maven-site-plugin:deploy</site-deploy>
</default-phases>
</legacyLifecycle>
</legacyLifecycles>
</configuration>
</component>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>test-mapping</role-hint>
<implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
<configuration>
<lifecycles>
<lifecycle>
<id>default</id>
<!-- START SNIPPET: pom-lifecycle -->
<phases>
<package>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</package>
<install>org.apache.maven.plugins:maven-install-plugin:install</install>
<deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
</phases>
<optional-mojos>
<optional-mojo>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</optional-mojo>
</optional-mojos>
<!-- END SNIPPET: pom-lifecycle -->
</lifecycle>
</lifecycles>
</configuration>
</component>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>test-mapping2</role-hint>
<implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
<configuration>
<lifecycles>
<lifecycle>
<id>default</id>
<!-- START SNIPPET: pom-lifecycle -->
<phases>
<package>
org.apache.maven.plugins:maven-site-plugin:attach-descriptor,
org.apache.maven.plugins:maven-clean-plugin:clean
</package>
<install>org.apache.maven.plugins:maven-install-plugin:install</install>
<deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
</phases>
<optional-mojos>
<optional-mojo>org.apache.maven.plugins:maven-site-plugin:attach-descriptor</optional-mojo>
</optional-mojos>
<!-- END SNIPPET: pom-lifecycle -->
</lifecycle>
</lifecycles>
</configuration>
</component>
</components>
</component-set>

View File

@ -41,7 +41,7 @@ import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleExecutor;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.io.jdom.MavenJDOMWriter;
@ -67,17 +67,15 @@ import org.apache.maven.settings.validation.SettingsValidationResult;
import org.apache.maven.settings.validation.SettingsValidator;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.MutablePlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.component.repository.exception.ComponentRepositoryException;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.configuration.PlexusConfigurationException;
import org.codehaus.plexus.logging.LoggerManager;
import org.codehaus.plexus.util.StringUtils;
@ -94,13 +92,11 @@ import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
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.Arrays;
/**
* Class intended to be used by clients who wish to embed Maven into their applications
@ -489,34 +485,37 @@ public class MavenEmbedder
// Execution of phases/goals
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// Lifecycle information
// LegacyLifecycle information
// ----------------------------------------------------------------------
public List getLifecyclePhases()
throws MavenEmbedderException
{
List phases = new ArrayList();
return getBuildLifecyclePhases();
}
ComponentDescriptor descriptor = container.getComponentDescriptor( LifecycleExecutor.ROLE );
public List getAllLifecyclePhases()
{
return LifecycleUtils.getValidPhaseNames();
}
PlexusConfiguration configuration = descriptor.getConfiguration();
public List getDefaultLifecyclePhases()
{
return getBuildLifecyclePhases();
}
PlexusConfiguration[] phasesConfigurations =
configuration.getChild( "lifecycles" ).getChild( 0 ).getChild( "phases" ).getChildren( "phase" );
public List getBuildLifecyclePhases()
{
return LifecycleUtils.getValidBuildPhaseNames();
}
try
{
for ( int i = 0; i < phasesConfigurations.length; i++ )
{
phases.add( phasesConfigurations[i].getValue() );
}
}
catch ( PlexusConfigurationException e )
{
throw new MavenEmbedderException( "Cannot retrieve default lifecycle phasesConfigurations.", e );
}
public List getCleanLifecyclePhases()
{
return LifecycleUtils.getValidCleanPhaseNames();
}
return phases;
public List getSiteLifecyclePhases()
{
return LifecycleUtils.getValidSitePhaseNames();
}
// ----------------------------------------------------------------------
@ -524,7 +523,7 @@ public class MavenEmbedder
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// Lifecycle
// LegacyLifecycle
// ----------------------------------------------------------------------
private void start( Configuration configuration )
@ -645,7 +644,7 @@ public class MavenEmbedder
}
// ----------------------------------------------------------------------
// Lifecycle
// LegacyLifecycle
// ----------------------------------------------------------------------
private void handleExtensions( List extensions )

View File

@ -202,7 +202,7 @@ public class DefaultMavenExecutionRequestDefaultsPopulator
}
// ----------------------------------------------------------------------------
// Lifecycle
// LegacyLifecycle
// ----------------------------------------------------------------------------
public void contextualize( Context context )

View File

@ -26,6 +26,7 @@ import org.codehaus.plexus.util.FileUtils;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
@ -36,20 +37,20 @@ public abstract class AbstractEmbedderExecutionTestCase
protected File runWithProject( String goal )
throws Exception
{
return runWithProject( goal, null );
return runWithProject( Collections.singletonList( goal ), null );
}
protected File runWithProject( String goal,
Properties properties )
throws Exception
{
return runWithProject( new String[]{goal}, properties );
return runWithProject( Collections.singletonList( goal ), properties );
}
protected File runWithProject( String[] goals )
throws Exception
{
return runWithProject( goals, null );
return runWithProject( Arrays.asList( goals ), null );
}
protected File runWithProject( String[] goals,
@ -83,6 +84,8 @@ public abstract class AbstractEmbedderExecutionTestCase
FileUtils.copyDirectoryStructure( testDirectory, targetDirectory );
MavenExecutionRequest request = new DefaultMavenExecutionRequest()
.setShowErrors( true )
.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_DEBUG )
.setBaseDirectory( targetDirectory )
.setGoals( goals );

View File

@ -64,6 +64,11 @@ public class MavenEmbedderTest
basedir = System.getProperty( "basedir" );
if ( basedir == null )
{
basedir = new File( "." ).getCanonicalPath();
}
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Configuration configuration = new DefaultConfiguration()
@ -202,7 +207,7 @@ public class MavenEmbedderTest
}
// ----------------------------------------------------------------------
// Lifecycle phases
// LegacyLifecycle phases
// ----------------------------------------------------------------------
public void testRetrievingLifecyclePhases()

41
maven-lifecycle/pom.xml Normal file
View File

@ -0,0 +1,41 @@
<?xml version="1.0"?><project>
<parent>
<artifactId>maven</artifactId>
<groupId>org.apache.maven</groupId>
<version>2.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>maven-lifecycle</artifactId>
<name>Maven Lifecycle Model</name>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
<configuration>
<version>1.0.0</version>
<model>src/main/mdo/maven-lifecycle.mdo</model>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,84 @@
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.io.xpp3.LifecycleBindingsXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
/**
* @author jdcasey
*/
public class ClassLoaderXmlBindingLoader
implements LifecycleBindingLoader
{
// configuration.
private String path;
public ClassLoaderXmlBindingLoader()
{
// for plexus init.
}
public ClassLoaderXmlBindingLoader( String path )
{
this.path = path;
}
public LifecycleBindings getBindings()
throws LifecycleLoaderException, LifecycleSpecificationException
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL url = loader.getResource( getPath() );
if ( url == null )
{
throw new LifecycleLoaderException( "Classpath resource: " + getPath() + " could not be found." );
}
InputStreamReader reader;
try
{
reader = new InputStreamReader( url.openStream() );
}
catch ( IOException e )
{
throw new LifecycleLoaderException( "Failed to open stream for classpath resource: " + getPath() + ". Reason: "
+ e.getMessage(), e );
}
LifecycleBindings bindings;
try
{
bindings = new LifecycleBindingsXpp3Reader().read( reader );
}
catch ( IOException e )
{
throw new LifecycleLoaderException( "Classpath resource: " + getPath() + " could not be read. Reason: "
+ e.getMessage(), e );
}
catch ( XmlPullParserException e )
{
throw new LifecycleLoaderException( "Classpath resource: " + getPath() + " could not be parsed. Reason: "
+ e.getMessage(), e );
}
LifecycleUtils.setOrigin( bindings, url.toExternalForm() );
return bindings;
}
public String getPath()
{
return path;
}
public void setPath( String path )
{
this.path = path;
}
}

View File

@ -0,0 +1,13 @@
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.model.LifecycleBindings;
public interface LifecycleBindingLoader
{
String ROLE = LifecycleBindingLoader.class.getName();
LifecycleBindings getBindings()
throws LifecycleLoaderException, LifecycleSpecificationException;
}

View File

@ -0,0 +1,17 @@
package org.apache.maven.lifecycle;
public class LifecycleException
extends Exception
{
public LifecycleException( String message, Throwable cause )
{
super( message, cause );
}
public LifecycleException( String message )
{
super( message );
}
}

View File

@ -0,0 +1,17 @@
package org.apache.maven.lifecycle;
public class LifecycleLoaderException
extends LifecycleException
{
public LifecycleLoaderException( String message, Throwable cause )
{
super( message, cause );
}
public LifecycleLoaderException( String message )
{
super( message );
}
}

View File

@ -0,0 +1,17 @@
package org.apache.maven.lifecycle;
public class LifecycleSpecificationException
extends LifecycleException
{
public LifecycleSpecificationException( String message, Throwable cause )
{
super( message, cause );
}
public LifecycleSpecificationException( String message )
{
super( message );
}
}

View File

@ -0,0 +1,671 @@
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.model.BuildBinding;
import org.apache.maven.lifecycle.model.CleanBinding;
import org.apache.maven.lifecycle.model.LifecycleBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.apache.maven.lifecycle.model.SiteBinding;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class LifecycleUtils
{
private LifecycleUtils()
{
}
public static void setOrigin( LifecycleBindings bindings, String origin )
{
for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) bindingIt.next();
if ( binding == null )
{
continue;
}
for ( Iterator phaseIt = binding.getPhasesInOrder().iterator(); phaseIt.hasNext(); )
{
Phase phase = (Phase) phaseIt.next();
if ( phase == null )
{
continue;
}
for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); )
{
MojoBinding mojoBinding = (MojoBinding) mojoIt.next();
mojoBinding.setOrigin( origin );
}
}
}
}
public static List getMojoBindingListForLifecycle( String stopPhase, LifecycleBindings bindings )
throws NoSuchPhaseException
{
LifecycleBinding binding = findLifecycleBindingForPhase( stopPhase, bindings );
if ( binding == null )
{
throw new NoSuchPhaseException( stopPhase, "Phase not found in any lifecycle." );
}
return getMojoBindingListForLifecycle( stopPhase, binding );
}
public static List getMojoBindingListForLifecycle( String stopPhase, LifecycleBinding lifecycle )
throws NoSuchPhaseException
{
List phaseNames = lifecycle.getPhaseNamesInOrder();
int idx = phaseNames.indexOf( stopPhase );
if ( idx < 0 )
{
throw new NoSuchPhaseException( stopPhase, "Phase not found in lifecycle: " + lifecycle.getId() );
}
List phases = lifecycle.getPhasesInOrder();
List bindings = new ArrayList();
for ( int i = 0; i <= idx; i++ )
{
Phase phase = (Phase) phases.get( i );
List phaseBindings = phase.getBindings();
if ( phaseBindings != null && !phaseBindings.isEmpty() )
{
bindings.addAll( phaseBindings );
}
}
return bindings;
}
/**
* @return null if the phase is not contained in any of the lifecycles.
*/
public static LifecycleBinding findLifecycleBindingForPhase( String phaseName, LifecycleBindings lifecycles )
{
List lifecyclesAvailable = lifecycles.getBindingList();
for ( Iterator it = lifecyclesAvailable.iterator(); it.hasNext(); )
{
LifecycleBinding lifecycle = (LifecycleBinding) it.next();
if ( lifecycle.getPhaseNamesInOrder().indexOf( phaseName ) > -1 )
{
return lifecycle;
}
}
return null;
}
public static void removeMojoBinding( String phaseName, MojoBinding mojoBinding, LifecycleBinding lifecycleBinding,
boolean considerExecutionId )
throws NoSuchPhaseException
{
List phaseNames = lifecycleBinding.getPhaseNamesInOrder();
int idx = phaseNames.indexOf( phaseName );
if ( idx < 0 )
{
throw new NoSuchPhaseException( phaseName, "Phase: " + phaseName + " not found in lifecycle: "
+ lifecycleBinding.getId() );
}
List phases = lifecycleBinding.getPhasesInOrder();
Phase phase = (Phase) phases.get( idx );
if ( phase != null )
{
List mojoBindings = phase.getBindings();
String targetKey = createMojoBindingKey( mojoBinding, considerExecutionId );
for ( Iterator it = mojoBindings.iterator(); it.hasNext(); )
{
MojoBinding candidate = (MojoBinding) it.next();
String candidateKey = createMojoBindingKey( candidate, considerExecutionId );
if ( candidateKey.equals( targetKey ) )
{
it.remove();
}
}
phase.setBindings( mojoBindings );
}
}
public static void addMojoBinding( String phaseName, MojoBinding mojoBinding, LifecycleBinding lifecycleBinding )
throws NoSuchPhaseException
{
List phaseNames = lifecycleBinding.getPhaseNamesInOrder();
int idx = phaseNames.indexOf( phaseName );
if ( idx < 0 )
{
throw new NoSuchPhaseException( phaseName, "Phase: " + phaseName + " not found in lifecycle: "
+ lifecycleBinding.getId() );
}
List phases = lifecycleBinding.getPhasesInOrder();
Phase phase = (Phase) phases.get( idx );
phase.addBinding( mojoBinding );
}
public static void addMojoBinding( String phaseName, MojoBinding mojo, LifecycleBindings bindings )
throws LifecycleSpecificationException
{
LifecycleBinding binding = findLifecycleBindingForPhase( phaseName, bindings );
if ( binding == null )
{
throw new NoSuchPhaseException( phaseName, "Phase not found in any lifecycle: " + phaseName );
}
addMojoBinding( phaseName, mojo, binding );
}
public static LifecycleBindings mergeBindings( LifecycleBindings existingBindings, LifecycleBindings newBindings,
LifecycleBindings defaultBindings, boolean mergeConfigIfExecutionIdMatches )
{
return mergeBindings( existingBindings, newBindings, defaultBindings, mergeConfigIfExecutionIdMatches, false );
}
public static LifecycleBindings mergeBindings( LifecycleBindings existingBindings, LifecycleBindings newBindings,
LifecycleBindings defaultBindings, boolean mergeConfigIfExecutionIdMatches,
boolean reverseConfigMergeDirection )
{
LifecycleBindings result = new LifecycleBindings();
result.setPackaging( newBindings.getPackaging() );
CleanBinding cb = (CleanBinding) cloneBinding( existingBindings.getCleanBinding() );
if ( defaultBindings != null && isNullOrEmpty( cb ) )
{
cb = (CleanBinding) cloneBinding( defaultBindings.getCleanBinding() );
}
if ( cb == null )
{
cb = new CleanBinding();
}
result.setCleanBinding( cb );
BuildBinding bb = (BuildBinding) cloneBinding( existingBindings.getBuildBinding() );
if ( defaultBindings != null && isNullOrEmpty( bb ) )
{
bb = (BuildBinding) cloneBinding( defaultBindings.getBuildBinding() );
}
if ( bb == null )
{
bb = new BuildBinding();
}
result.setBuildBinding( bb );
SiteBinding sb = (SiteBinding) cloneBinding( existingBindings.getSiteBinding() );
if ( defaultBindings != null && isNullOrEmpty( sb ) )
{
sb = (SiteBinding) cloneBinding( defaultBindings.getSiteBinding() );
}
if ( sb == null )
{
sb = new SiteBinding();
}
result.setSiteBinding( sb );
for ( Iterator bindingIt = newBindings.getBindingList().iterator(); bindingIt.hasNext(); )
{
LifecycleBinding lifecycleBinding = (LifecycleBinding) bindingIt.next();
if ( lifecycleBinding != null )
{
List phaseNames = lifecycleBinding.getPhaseNamesInOrder();
List phases = lifecycleBinding.getPhasesInOrder();
for ( int i = 0; i < phases.size(); i++ )
{
Phase phase = (Phase) phases.get( i );
String name = (String) phaseNames.get( i );
if ( phase != null && phase.getBindings() != null && !phase.getBindings().isEmpty() )
{
for ( Iterator phaseIt = phase.getBindings().iterator(); phaseIt.hasNext(); )
{
MojoBinding mojoBinding = (MojoBinding) phaseIt.next();
mojoBinding = cloneMojoBinding( mojoBinding );
if ( mergeConfigIfExecutionIdMatches )
{
MojoBinding matchingBinding = findMatchingMojoBinding( mojoBinding, existingBindings, true );
if ( matchingBinding != null )
{
Xpp3Dom existingConfig = new Xpp3Dom( (Xpp3Dom) matchingBinding.getConfiguration() );
Xpp3Dom configuration;
if ( reverseConfigMergeDirection )
{
configuration = Xpp3Dom.mergeXpp3Dom( existingConfig, (Xpp3Dom) mojoBinding.getConfiguration() );
}
else
{
configuration = Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) mojoBinding.getConfiguration(), existingConfig );
}
mojoBinding.setConfiguration( configuration );
if ( mojoBinding.getOrigin() == null && matchingBinding.getOrigin() != null )
{
mojoBinding.setOrigin( matchingBinding.getOrigin() );
}
LifecycleBinding resultBinding = findLifecycleBindingForPhase( name, result );
try
{
removeMojoBinding( name, matchingBinding, resultBinding, true );
}
catch ( NoSuchPhaseException e )
{
IllegalStateException error = new IllegalStateException(
e.getMessage()
+ "\nSomething strange is going on. Merging should not encounter such inconsistencies." );
error.initCause( e );
throw error;
}
}
}
try
{
addMojoBinding( name, mojoBinding, result );
}
catch ( LifecycleSpecificationException e )
{
// NOTE: this shouldn't happen as long as normal components are used
// to create/read these LifecycleBindings instances.
IllegalArgumentException error = new IllegalArgumentException(
"Project bindings are invalid. Reason: "
+ e.getMessage() );
error.initCause( e );
throw error;
}
}
}
}
}
}
return result;
}
private static boolean isNullOrEmpty( LifecycleBinding binding )
{
if ( binding == null )
{
return true;
}
for ( Iterator it = binding.getPhasesInOrder().iterator(); it.hasNext(); )
{
Phase phase = (Phase) it.next();
if ( !phase.getBindings().isEmpty() )
{
return false;
}
}
return true;
}
public static MojoBinding findMatchingMojoBinding( MojoBinding mojoBinding, LifecycleBindings inBindings,
boolean considerExecutionId )
{
String key = createMojoBindingKey( mojoBinding, considerExecutionId );
return (MojoBinding) mapMojoBindingsByKey( inBindings, considerExecutionId ).get( key );
}
private static Map mapMojoBindingsByKey( LifecycleBindings bindings, boolean considerExecutionId )
{
Map byKey = new HashMap();
for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) bindingIt.next();
if ( binding != null )
{
for ( Iterator phaseIt = binding.getPhasesInOrder().iterator(); phaseIt.hasNext(); )
{
Phase phase = (Phase) phaseIt.next();
if ( phase != null )
{
for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); )
{
MojoBinding mojoBinding = (MojoBinding) mojoIt.next();
byKey.put( createMojoBindingKey( mojoBinding, considerExecutionId ), mojoBinding );
}
}
}
}
}
return byKey;
}
public static void removeMojoBindings( List toRemove, LifecycleBindings bindings, boolean considerExecutionId )
throws NoSuchPhaseException
{
if ( bindings.getCleanBinding() != null )
{
removeMojoBindings( toRemove, bindings.getCleanBinding(), considerExecutionId );
}
if ( bindings.getBuildBinding() != null )
{
removeMojoBindings( toRemove, bindings.getBuildBinding(), considerExecutionId );
}
if ( bindings.getSiteBinding() != null )
{
removeMojoBindings( toRemove, bindings.getSiteBinding(), considerExecutionId );
}
}
public static void removeMojoBindings( List toRemove, LifecycleBinding removeFrom, boolean considerExecutionId )
throws NoSuchPhaseException
{
// remove where gid:aid:goal matches.
List targets = new ArrayList();
for ( Iterator it = toRemove.iterator(); it.hasNext(); )
{
MojoBinding binding = (MojoBinding) it.next();
targets.add( createMojoBindingKey( binding, considerExecutionId ) );
}
List phases = removeFrom.getPhasesInOrder();
for ( int i = 0; i < phases.size(); i++ )
{
Phase phase = (Phase) phases.get( i );
List phaseBindings = phase.getBindings();
for ( Iterator mojoIt = phaseBindings.iterator(); mojoIt.hasNext(); )
{
MojoBinding binding = (MojoBinding) mojoIt.next();
String key = createMojoBindingKey( binding, considerExecutionId );
if ( targets.contains( key ) )
{
mojoIt.remove();
}
}
phase.setBindings( phaseBindings );
}
}
public static String createMojoBindingKey( MojoBinding mojoBinding, boolean considerExecutionId )
{
String key = mojoBinding.getGroupId() + ":" + mojoBinding.getArtifactId() + ":" + mojoBinding.getGoal();
if ( considerExecutionId )
{
key += ":" + mojoBinding.getExecutionId();
}
return key;
}
public static LifecycleBindings cloneBindings( LifecycleBindings bindings )
{
LifecycleBindings result = new LifecycleBindings();
if ( bindings.getCleanBinding() != null )
{
result.setCleanBinding( (CleanBinding) cloneBinding( bindings.getCleanBinding() ) );
}
if ( bindings.getBuildBinding() != null )
{
result.setBuildBinding( (BuildBinding) cloneBinding( bindings.getBuildBinding() ) );
}
if ( bindings.getSiteBinding() != null )
{
result.setSiteBinding( (SiteBinding) cloneBinding( bindings.getSiteBinding() ) );
}
return result;
}
public static LifecycleBinding cloneBinding( LifecycleBinding binding )
{
if ( binding == null )
{
return null;
}
LifecycleBinding result;
if ( binding instanceof CleanBinding )
{
result = new CleanBinding();
}
else if ( binding instanceof SiteBinding )
{
result = new SiteBinding();
}
else if ( binding instanceof BuildBinding )
{
result = new BuildBinding();
}
else
{
throw new IllegalArgumentException( "Unrecognized LifecycleBinding type: " + binding.getClass().getName()
+ "; cannot clone." );
}
List phases = binding.getPhasesInOrder();
List names = binding.getPhaseNamesInOrder();
for ( int i = 0; i < phases.size(); i++ )
{
Phase phase = (Phase) phases.get( i );
String phaseName = (String) names.get( i );
for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); )
{
MojoBinding originalBinding = (MojoBinding) mojoIt.next();
MojoBinding newBinding = cloneMojoBinding( originalBinding );
try
{
addMojoBinding( phaseName, newBinding, result );
}
catch ( NoSuchPhaseException e )
{
IllegalStateException error = new IllegalStateException( e.getMessage()
+ "\nSomething strange is going on. Cloning should not encounter such inconsistencies." );
error.initCause( e );
throw error;
}
}
}
return result;
}
public static MojoBinding cloneMojoBinding( MojoBinding binding )
{
MojoBinding result = new MojoBinding();
result.setGroupId( binding.getGroupId() );
result.setArtifactId( binding.getArtifactId() );
result.setVersion( binding.getVersion() );
result.setConfiguration( binding.getConfiguration() );
result.setExecutionId( binding.getExecutionId() );
result.setGoal( binding.getGoal() );
result.setOrigin( binding.getOrigin() );
return result;
}
public static Phase findPhaseForMojoBinding( MojoBinding mojoBinding, LifecycleBindings lifecycleBindings,
boolean considerExecutionId )
{
String targetKey = createMojoBindingKey( mojoBinding, considerExecutionId );
for ( Iterator lifecycleIt = lifecycleBindings.getBindingList().iterator(); lifecycleIt.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) lifecycleIt.next();
for ( Iterator phaseIt = binding.getPhasesInOrder().iterator(); phaseIt.hasNext(); )
{
Phase phase = (Phase) phaseIt.next();
for ( Iterator mojoIt = phase.getBindings().iterator(); mojoIt.hasNext(); )
{
MojoBinding candidate = (MojoBinding) mojoIt.next();
String key = createMojoBindingKey( candidate, considerExecutionId );
if ( key.equals( targetKey ) )
{
return phase;
}
}
}
}
return null;
}
public static boolean isMojoBindingPresent( MojoBinding binding, List candidates, boolean considerExecutionId )
{
String key = createMojoBindingKey( binding, considerExecutionId );
for ( Iterator it = candidates.iterator(); it.hasNext(); )
{
MojoBinding candidate = (MojoBinding) it.next();
String candidateKey = createMojoBindingKey( candidate, considerExecutionId );
if ( candidateKey.equals( key ) )
{
return true;
}
}
return false;
}
public static boolean isValidPhaseName( String phaseName )
{
LifecycleBindings test = new LifecycleBindings();
for ( Iterator it = test.getBindingList().iterator(); it.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) it.next();
if ( binding.getPhaseNamesInOrder().contains( phaseName ) )
{
return true;
}
}
return false;
}
public static List getValidPhaseNames()
{
List phaseNames = new ArrayList();
LifecycleBindings bindings = new LifecycleBindings();
for ( Iterator bindingIt = bindings.getBindingList().iterator(); bindingIt.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) bindingIt.next();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{
phaseNames.add( phaseNameIt.next() );
}
}
return phaseNames;
}
public static List getValidBuildPhaseNames()
{
List phaseNames = new ArrayList();
LifecycleBinding binding = new BuildBinding();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{
phaseNames.add( phaseNameIt.next() );
}
return phaseNames;
}
public static List getValidCleanPhaseNames()
{
List phaseNames = new ArrayList();
LifecycleBinding binding = new CleanBinding();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{
phaseNames.add( phaseNameIt.next() );
}
return phaseNames;
}
public static List getValidSitePhaseNames()
{
List phaseNames = new ArrayList();
LifecycleBinding binding = new SiteBinding();
for ( Iterator phaseNameIt = binding.getPhaseNamesInOrder().iterator(); phaseNameIt.hasNext(); )
{
phaseNames.add( phaseNameIt.next() );
}
return phaseNames;
}
}

View File

@ -0,0 +1,18 @@
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.model.MojoBinding;
public final class MojoBindingUtils
{
private MojoBindingUtils()
{
}
public static String toString( MojoBinding mojoBinding )
{
return mojoBinding.getGroupId() + ":" + mojoBinding.getArtifactId() + ":"
+ ( mojoBinding.getVersion() == null ? "" : mojoBinding.getVersion() + ":" ) + mojoBinding.getGoal();
}
}

View File

@ -0,0 +1,26 @@
package org.apache.maven.lifecycle;
public class NoSuchLifecycleException
extends LifecycleSpecificationException
{
private final String packaging;
public NoSuchLifecycleException( String packaging, String message, Throwable cause )
{
super( message, cause );
this.packaging = packaging;
}
public NoSuchLifecycleException( String phase, String message )
{
super( message );
this.packaging = phase;
}
public String getPackaging()
{
return packaging;
}
}

View File

@ -0,0 +1,26 @@
package org.apache.maven.lifecycle;
public class NoSuchPhaseException
extends LifecycleSpecificationException
{
private final String phase;
public NoSuchPhaseException( String phase, String message, Throwable cause )
{
super( message, cause );
this.phase = phase;
}
public NoSuchPhaseException( String phase, String message )
{
super( message );
this.phase = phase;
}
public String getPhase()
{
return phase;
}
}

View File

@ -0,0 +1,620 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<!--
*** NOTE: If you add a new lifecycle or phase, be sure to update the codeSegments! ***
-->
<model>
<id>build-lifecycle</id>
<name>LifecycleBindings</name>
<description>Model for lifecycle specifications starting in Maven 2.1</description>
<defaults>
<default>
<key>package</key>
<value>org.apache.maven.lifecycle.model</value>
</default>
</defaults>
<classes>
<class rootElement="true" xml.tagName="lifecycles">
<name>LifecycleBindings</name>
<version>1.0.0</version>
<description>Specifies phase bindings for clean, site, and default lifecycles.</description>
<fields>
<field>
<version>1.0.0</version>
<name>packaging</name>
<type>String</type>
<required>true</required>
<description>POM packaging to which this lifecycle specification applies.</description>
</field>
<field xml.tagName="clean">
<version>1.0.0</version>
<name>cleanBinding</name>
<defaultValue>new CleanBinding()</defaultValue>
<description>The binding for the clean lifecycle</description>
<association>
<type>CleanBinding</type>
</association>
</field>
<field xml.tagName="build">
<version>1.0.0</version>
<name>buildBinding</name>
<defaultValue>new BuildBinding()</defaultValue>
<description>The binding for the main build (default) lifecycle</description>
<association>
<type>BuildBinding</type>
</association>
</field>
<field xml.tagName="site">
<version>1.0.0</version>
<name>siteBinding</name>
<defaultValue>new SiteBinding()</defaultValue>
<description>The binding for the site lifecycle</description>
<association>
<type>SiteBinding</type>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public java.util.List getBindingList()
{
java.util.List lifecycles = new java.util.ArrayList();
if ( getCleanBinding() != null )
{
lifecycles.add( getCleanBinding() );
}
if ( getBuildBinding() != null )
{
lifecycles.add( getBuildBinding() );
}
if ( getSiteBinding() != null )
{
lifecycles.add( getSiteBinding() );
}
return java.util.Collections.unmodifiableList( lifecycles );
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>LifecycleBinding</name>
<version>1.0.0</version>
<description>Base-class for all lifecycle bindings.</description>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String getId()
{
throw new UnsupportedOperationException( "Unsupported in base-class." );
}
public java.util.List getPhasesInOrder()
{
throw new UnsupportedOperationException( "Unsupported in base-class." );
}
public java.util.List getPhaseNamesInOrder()
{
throw new UnsupportedOperationException( "Unsupported in base-class." );
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>CleanBinding</name>
<superClass>LifecycleBinding</superClass>
<version>1.0.0</version>
<fields>
<field xml.tagName="pre-clean">
<name>preClean</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="clean">
<name>clean</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="post-clean">
<name>postClean</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String getId()
{
return "clean";
}
public java.util.List getPhasesInOrder()
{
java.util.List phases = new java.util.ArrayList();
phases.add( getPreClean() );
phases.add( getClean() );
phases.add( getPostClean() );
return java.util.Collections.unmodifiableList( phases );
}
public java.util.List getPhaseNamesInOrder()
{
java.util.List phases = new java.util.ArrayList();
phases.add( "pre-clean" );
phases.add( "clean" );
phases.add( "post-clean" );
return java.util.Collections.unmodifiableList( phases );
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>BuildBinding</name>
<superClass>LifecycleBinding</superClass>
<version>1.0.0</version>
<fields>
<field>
<name>validate</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field>
<name>initialize</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="generate-sources">
<name>generateSources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="process-sources">
<name>processSources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="generate-resources">
<name>generateResources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="process-resources">
<name>processResources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field>
<name>compile</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="process-classes">
<name>processClasses</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="generate-test-sources">
<name>generateTestSources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="process-test-sources">
<name>processTestSources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="generate-test-resources">
<name>generateTestResources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="process-test-resources">
<name>processTestResources</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="test-compile">
<name>testCompile</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="process-test-classes">
<name>processTestClasses</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="test">
<name>test</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="prepare-package">
<name>preparePackage</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="package">
<name>createPackage</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="pre-integration-test">
<name>preIntegrationTest</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="integration-test">
<name>integrationTest</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="post-integration-test">
<name>postIntegrationTest</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field>
<name>verify</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field>
<name>install</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field>
<name>deploy</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String getId()
{
return "build";
}
public java.util.List getPhasesInOrder()
{
java.util.List phases = new java.util.ArrayList();
phases.add( getValidate() );
phases.add( getInitialize() );
phases.add( getGenerateSources() );
phases.add( getProcessSources() );
phases.add( getGenerateResources() );
phases.add( getProcessResources() );
phases.add( getCompile() );
phases.add( getProcessClasses() );
phases.add( getGenerateTestSources() );
phases.add( getProcessTestSources() );
phases.add( getGenerateTestResources() );
phases.add( getProcessTestResources() );
phases.add( getTestCompile() );
phases.add( getProcessTestClasses() );
phases.add( getTest() );
phases.add( getPreparePackage() );
phases.add( getCreatePackage() );
phases.add( getPreIntegrationTest() );
phases.add( getIntegrationTest() );
phases.add( getPostIntegrationTest() );
phases.add( getVerify() );
phases.add( getInstall() );
phases.add( getDeploy() );
return java.util.Collections.unmodifiableList( phases );
}
public java.util.List getPhaseNamesInOrder()
{
java.util.List phases = new java.util.ArrayList();
phases.add( "validate" );
phases.add( "initialize" );
phases.add( "generate-sources" );
phases.add( "process-sources" );
phases.add( "generate-resources" );
phases.add( "process-resources" );
phases.add( "compile" );
phases.add( "process-classes" );
phases.add( "generate-test-sources" );
phases.add( "process-test-sources" );
phases.add( "generate-test-resources" );
phases.add( "process-test-resources" );
phases.add( "test-compile" );
phases.add( "process-test-classes" );
phases.add( "test" );
phases.add( "prepare-package" );
phases.add( "package" );
phases.add( "pre-integration-test" );
phases.add( "integration-test" );
phases.add( "post-integration-test" );
phases.add( "verify" );
phases.add( "install" );
phases.add( "deploy" );
return java.util.Collections.unmodifiableList( phases );
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>SiteBinding</name>
<superClass>LifecycleBinding</superClass>
<version>1.0.0</version>
<fields>
<field xml.tagName="pre-site">
<name>preSite</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="site">
<name>site</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="post-site">
<name>postSite</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
<field xml.tagName="site-deploy">
<name>siteDeploy</name>
<version>1.0.0</version>
<defaultValue>new Phase()</defaultValue>
<association>
<type>Phase</type>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0</version>
<code><![CDATA[
public String getId()
{
return "site";
}
public java.util.List getPhasesInOrder()
{
java.util.List phases = new java.util.ArrayList();
phases.add( getPreSite() );
phases.add( getSite() );
phases.add( getPostSite() );
phases.add( getSiteDeploy() );
return java.util.Collections.unmodifiableList( phases );
}
public java.util.List getPhaseNamesInOrder()
{
java.util.List phases = new java.util.ArrayList();
phases.add( "pre-site" );
phases.add( "site" );
phases.add( "post-site" );
phases.add( "site-deploy" );
return java.util.Collections.unmodifiableList( phases );
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
<name>Phase</name>
<version>1.0.0</version>
<description>Contains a series of mojo bindings for a given phase of a lifecycle.</description>
<fields>
<field>
<name>bindings</name>
<version>1.0.0</version>
<description>Collection of mojo bindings for a phase.</description>
<association>
<type>MojoBinding</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
</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>
<name>MojoBinding</name>
<superClass>LifecycleStep</superClass>
<version>1.0.0</version>
<description>A binding of one mojo to one lifecycle phase, possibly including configuration.</description>
<fields>
<field>
<name>groupId</name>
<required>true</required>
<version>1.0.0</version>
<description>Plugin's groupId.</description>
<type>String</type>
</field>
<field>
<name>artifactId</name>
<required>true</required>
<version>1.0.0</version>
<description>Plugin's artifactId.</description>
<type>String</type>
</field>
<field>
<name>version</name>
<required>true</required>
<version>1.0.0</version>
<description>Plugin's version.</description>
<type>String</type>
</field>
<field>
<name>goal</name>
<required>true</required>
<version>1.0.0</version>
<description>Mojo's goal name.</description>
<type>String</type>
</field>
<field>
<name>executionId</name>
<version>1.0.0</version>
<defaultValue>default</defaultValue>
<description>A name for this mojo binding, for purposes of merging configurations via inheritance, etc.</description>
<type>String</type>
</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>
<name>configuration</name>
<version>1.0.0</version>
<description>Mojo binding's configuration.</description>
<type>DOM</type>
</field>
<field>
<name>optional</name>
<version>1.0.0</version>
<description>Marks a mojo binding as optional (not required for execution of the lifecycle).</description>
<type>boolean</type>
</field>
</fields>
</class>
</classes>
</model>

View File

@ -0,0 +1,61 @@
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.model.CleanBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.codehaus.plexus.PlexusTestCase;
import java.util.List;
public class ClassLoaderXmlBindingLoaderTest
extends PlexusTestCase
{
public void testBeanAccess_ParseSingleCleanBinding()
throws LifecycleLoaderException, LifecycleSpecificationException
{
LifecycleBindings bindings = new ClassLoaderXmlBindingLoader( "single-clean-mapping.xml" ).getBindings();
CleanBinding cleanBinding = bindings.getCleanBinding();
assertNotNull( cleanBinding );
Phase preClean = cleanBinding.getPreClean();
assertNotNull( preClean );
List mojos = preClean.getBindings();
assertNotNull( mojos );
assertEquals( 1, mojos.size() );
MojoBinding mojo = (MojoBinding) mojos.get( 0 );
assertEquals( "group", mojo.getGroupId() );
assertEquals( "artifact", mojo.getArtifactId() );
assertNull( mojo.getVersion() );
assertEquals( "goalOne", mojo.getGoal() );
}
public void testComponentAccess_ParseSingleCleanBinding()
throws Exception
{
LifecycleBindingLoader loader = (LifecycleBindingLoader) lookup( LifecycleBindingLoader.ROLE, "single-clean-mapping" );
LifecycleBindings bindings = loader.getBindings();
CleanBinding cleanBinding = bindings.getCleanBinding();
assertNotNull( cleanBinding );
Phase preClean = cleanBinding.getPreClean();
assertNotNull( preClean );
List mojos = preClean.getBindings();
assertNotNull( mojos );
assertEquals( 1, mojos.size() );
MojoBinding mojo = (MojoBinding) mojos.get( 0 );
assertEquals( "group", mojo.getGroupId() );
assertEquals( "artifact", mojo.getArtifactId() );
assertNull( mojo.getVersion() );
assertEquals( "goalOne", mojo.getGoal() );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.LifecycleBindingLoader</role>
<role-hint>single-clean-mapping</role-hint>
<implementation>org.apache.maven.lifecycle.ClassLoaderXmlBindingLoader</implementation>
<configuration>
<path>single-clean-mapping.xml</path>
</configuration>
</component>
</components>
</component-set>

View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<lifecycles>
<clean>
<pre-clean>
<bindings>
<binding>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<goal>goalOne</goal>
</binding>
</bindings>
</pre-clean>
</clean>
</lifecycles>

View File

@ -0,0 +1,14 @@
package org.apache.maven.context;
import org.apache.maven.project.MavenProject;
public class ProjectScopedContext
extends ScopedBuildContext
{
public ProjectScopedContext( MavenProject project, BuildContext parentBuildContext )
{
super( project.getId(), parentBuildContext );
}
}

View File

@ -64,6 +64,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
/**
* The concern of the project is provide runtime values based on the model. <p/>
@ -147,6 +148,8 @@ public class MavenProject
private Map moduleAdjustments;
private Stack previousExecutionProjects = new Stack();
public MavenProject()
{
Model model = new Model();
@ -1425,11 +1428,16 @@ public class MavenProject
public MavenProject getExecutionProject()
{
return executionProject;
return ( executionProject == null ? this : executionProject );
}
public void setExecutionProject( MavenProject executionProject )
{
if ( this.executionProject != null )
{
previousExecutionProjects.push( this.executionProject );
}
this.executionProject = executionProject;
}
@ -1650,4 +1658,16 @@ public class MavenProject
list.add( file.getPath() );
}
}
public void clearExecutionProject()
{
if ( !previousExecutionProjects.isEmpty() )
{
executionProject = (MavenProject) previousExecutionProjects.pop();
}
else
{
executionProject = null;
}
}
}

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@ -121,6 +122,7 @@ under the License.
<module>maven-build-context</module>
<module>maven-core</module>
<module>maven-error-diagnostics</module>
<module>maven-lifecycle</module>
<module>maven-model</module>
<module>maven-monitor</module>
<module>maven-plugin-api</module>