[MNG-3004] Concurrent building of multimodule projects

This commit consists of a modularization of the DefaultLifecycleExecutor into smaller
components. This is primarily done with the intention of extracting execution strategy 
somewhat from the rest of the logic.

It also contains three differenent execution strategies:
A) Linear ("Classic")
B) Parallel (Based on Dan's original implemementation)
C) Weave (Still experimental) 

 
The command line -T option activates parallel running, and the argument
is in the form -T <[nThreads, a float][C][W]|auto>

Notes:
* The output demultiplexer is disabled in this commit, and output will appear intermingled.
* The modello plugin has known problems
* Surefire must be run in forkmode at least once.


git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@931884 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Kristian Rosenvold 2010-04-08 11:29:13 +00:00
parent a3bcfe7d11
commit 83237e46af
83 changed files with 7790 additions and 2300 deletions

View File

@ -25,11 +25,8 @@
import java.util.Set;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.*;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.LifecycleExecutor;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
@ -55,7 +52,7 @@ public MavenExecutionPlan calculateExecutionPlan( MavenSession session, String..
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException
{
return new MavenExecutionPlan( Collections.<MojoExecution> emptyList(), null, null );
return new MavenExecutionPlan(null, null, null );
}
public void execute( MavenSession session )

View File

@ -40,6 +40,7 @@
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.lifecycle.LifecycleExecutor;
import org.apache.maven.lifecycle.internal.LifecycleWeaveBuilder;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelSource;
import org.apache.maven.model.building.UrlModelSource;
@ -191,7 +192,8 @@ private MavenExecutionResult doExecute( MavenExecutionRequest request )
// Reactor
// Workspace
// User Local Repository
delegatingLocalArtifactRepository.setBuildReactor( new ReactorArtifactRepository( projectMap, session ) );
final boolean isWeaveMode = LifecycleWeaveBuilder.isWeaveMode( request);
delegatingLocalArtifactRepository.setBuildReactor( new ReactorArtifactRepository( projectMap, isWeaveMode ) );
}
catch ( org.apache.maven.DuplicateProjectException e )
{
@ -245,7 +247,7 @@ private MavenExecutionResult doExecute( MavenExecutionRequest request )
}
result.setTopologicallySortedProjects( session.getProjects() );
if ( result.hasExceptions() )
{
return result;

View File

@ -1,19 +1,13 @@
package org.apache.maven;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.LocalArtifactRepository;
import java.io.File;
import java.util.*;
/**
* An implementation of a repository that knows how to search the Maven reactor for artifacts.
*
@ -27,11 +21,15 @@ public class ReactorArtifactRepository
private Map<String, List<String>> availableVersions;
private final boolean isWeaveMode;
private final int hashCode;
public ReactorArtifactRepository( Map<String, MavenProject> reactorProjects, MavenSession session )
@SuppressWarnings({"ConstantConditions"})
public ReactorArtifactRepository( Map<String, MavenProject> reactorProjects, boolean isWeaveMode )
{
this.reactorProjects = reactorProjects;
this.isWeaveMode = isWeaveMode;
hashCode = ( reactorProjects != null ) ? reactorProjects.keySet().hashCode() : 0;
availableVersions = new HashMap<String, List<String>>( reactorProjects.size() * 2 );
@ -70,7 +68,7 @@ public Artifact find( Artifact artifact )
Artifact projectArtifact = findMatchingArtifact( project, artifact );
if ( projectArtifact != null && projectArtifact.getFile() != null && projectArtifact.getFile().exists() )
if ( !isWeaveMode && (projectArtifact != null && projectArtifact.getFile() != null && projectArtifact.getFile().exists()) )
{
//TODO: This is really completely wrong and should probably be based on the phase that is currently being executed.
// If we are running before the packaging phase there is going to be no archive anyway, but if we are running prior to package

View File

@ -22,6 +22,8 @@
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.ArtifactTransferListener;
/**
@ -68,6 +70,21 @@ public DefaultRepositoryRequest( RepositoryRequest repositoryRequest )
setTransferListener( repositoryRequest.getTransferListener() );
}
public static RepositoryRequest getRepositoryRequest(MavenSession session, MavenProject project) {
RepositoryRequest request = new DefaultRepositoryRequest();
request.setCache(session.getRepositoryCache());
request.setLocalRepository(session.getLocalRepository());
if (project != null) {
request.setRemoteRepositories(project.getPluginArtifactRepositories());
}
request.setOffline(session.isOffline());
request.setForceUpdate(session.getRequest().isUpdateSnapshots());
request.setTransferListener(session.getRequest().getTransferListener());
return request;
}
public boolean isOffline()
{
return offline;

View File

@ -201,7 +201,7 @@ else if ( exception instanceof PluginExecutionException )
reference = exception.getClass().getSimpleName();
}
}
else if ( exception instanceof LifecycleExecutionException )
else if ( exception instanceof LifecycleExecutionException)
{
reference = getReference( exception.getCause() );
}

View File

@ -126,6 +126,10 @@ public class DefaultMavenExecutionRequest
private ExecutionListener executionListener;
private String threadCount;
private boolean perCoreThreadCount;
private boolean weaveMode;
/**
* Suppress SNAPSHOT updates.
*
@ -1024,4 +1028,28 @@ public MavenExecutionRequest setExecutionListener( ExecutionListener executionLi
return this;
}
public String getThreadCount() {
return threadCount;
}
public void setThreadCount(String threadCount) {
this.threadCount = threadCount;
}
public boolean isThreadConfigurationPresent() {
return getThreadCount() != null;
}
public boolean isPerCoreThreadCount() {
return perCoreThreadCount;
}
public void setPerCoreThreadCount(boolean perCoreThreadCount) {
this.perCoreThreadCount = perCoreThreadCount;
}
public boolean isWeaveMode() {
return weaveMode;
}
}

View File

@ -152,6 +152,15 @@ public interface MavenExecutionRequest
MavenExecutionRequest setMakeBehavior( String makeBehavior );
String getMakeBehavior();
void setThreadCount( String threadCount );
String getThreadCount();
boolean isThreadConfigurationPresent();
void setPerCoreThreadCount(boolean perCoreThreadCount);
boolean isPerCoreThreadCount();
boolean isWeaveMode();
// Recursive (really to just process the top-level POM)
MavenExecutionRequest setRecursive( boolean recursive );
boolean isRecursive();
@ -269,6 +278,6 @@ public interface MavenExecutionRequest
ExecutionListener getExecutionListener();
MavenExecutionRequest setExecutionListener( ExecutionListener executionListener );
ProjectBuildingRequest getProjectBuildingRequest();
ProjectBuildingRequest getProjectBuildingRequest();
}

View File

@ -22,6 +22,7 @@
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@ -44,9 +45,10 @@
* @version $Id$
*/
public class MavenSession
implements Cloneable
{
private PlexusContainer container;
private MavenExecutionRequest request;
private MavenExecutionResult result;
@ -56,27 +58,28 @@ public class MavenSession
private Properties executionProperties;
private MavenProject currentProject;
/**
* These projects have already been topologically sorted in the {@link org.apache.maven.Maven} component before
* being passed into the session.
*/
private List<MavenProject> projects;
private MavenProject topLevelProject;
private ProjectDependencyGraph projectDependencyGraph;
private Collection<String> blackListedProjects;
private boolean parallel;
private final Map<String,Map<String,Map<String,Object>>> pluginContextsByProjectAndPluginKey =
new ConcurrentHashMap<String,Map<String,Map<String,Object>>> ();
private final Map<String, Map<String, Map<String, Object>>> pluginContextsByProjectAndPluginKey =
new ConcurrentHashMap<String, Map<String, Map<String, Object>>>();
@Deprecated
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, MavenProject project )
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result,
MavenProject project )
{
this( container, request, result, Arrays.asList( new MavenProject[]{ project } ) );
}
this( container, request, result, Arrays.asList( new MavenProject[]{project} ) );
}
@Deprecated
public MavenSession( PlexusContainer container, Settings settings, ArtifactRepository localRepository,
@ -105,7 +108,8 @@ public MavenSession( PlexusContainer container, Settings settings, ArtifactRepos
}
@Deprecated
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, List<MavenProject> projects )
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result,
List<MavenProject> projects )
{
this.container = container;
this.request = request;
@ -143,8 +147,8 @@ public void setProjects( List<MavenProject> projects )
this.topLevelProject = null;
}
this.projects = projects;
}
}
@Deprecated
public PlexusContainer getContainer()
{
@ -198,7 +202,7 @@ public List<String> getGoals()
* Gets the user properties to use for interpolation and profile activation. The user properties have been
* configured directly by the user on his discretion, e.g. via the {@code -Dkey=value} parameter on the command
* line.
*
*
* @return The user properties, never {@code null}.
*/
public Properties getUserProperties()
@ -209,7 +213,7 @@ public Properties getUserProperties()
/**
* Gets the system properties to use for interpolation and profile activation. The system properties are collected
* from the runtime environment like {@link System#getProperties()} and environment variables.
*
*
* @return The system properties, never {@code null}.
*/
public Properties getSystemProperties()
@ -237,7 +241,7 @@ public Settings getSettings()
{
return settings;
}
public List<MavenProject> getProjects()
{
return projects;
@ -278,16 +282,16 @@ public ProjectBuildingRequest getProjectBuildingRequest()
{
return request.getProjectBuildingRequest();
}
public List<String> getPluginGroups()
{
return request.getPluginGroups();
}
public boolean isOffline()
{
return request.isOffline();
}
}
public MavenProject getTopLevelProject()
{
@ -297,10 +301,10 @@ public MavenProject getTopLevelProject()
public MavenExecutionResult getResult()
{
return result;
}
}
// Backward compat
public Map<String, Object> getPluginContext( PluginDescriptor plugin, MavenProject project )
{
String projectKey = project.getId();
@ -328,6 +332,11 @@ public Map<String, Object> getPluginContext( PluginDescriptor plugin, MavenProje
return pluginContext;
}
public ProjectDependencyGraph getProjectDependencyGraph()
{
return projectDependencyGraph;
}
public void setProjectDependencyGraph( ProjectDependencyGraph projectDependencyGraph )
{
this.projectDependencyGraph = projectDependencyGraph;
@ -338,24 +347,16 @@ public String getReactorFailureBehavior()
return request.getReactorFailureBehavior();
}
public boolean isBlackListed( MavenProject project )
@Override
public MavenSession clone()
{
return blackListedProjects != null && blackListedProjects.contains( getId( project ) );
}
public void blackList( MavenProject project )
{
if ( blackListedProjects == null )
try
{
blackListedProjects = new HashSet<String>();
return (MavenSession) super.clone();
}
if ( blackListedProjects.add( getId( project ) ) && projectDependencyGraph != null )
catch ( CloneNotSupportedException e )
{
for ( MavenProject downstreamProject : projectDependencyGraph.getDownstreamProjects( project, true ) )
{
blackListedProjects.add( getId( downstreamProject ) );
}
throw new RuntimeException( "Bug", e );
}
}
@ -375,4 +376,11 @@ public Date getStartTime()
return request.getStartTime();
}
public boolean isParallel() {
return parallel;
}
public void setParallel(boolean parallel) {
this.parallel = parallel;
}
}

View File

@ -0,0 +1,173 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import org.apache.maven.lifecycle.internal.BuilderCommon;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.StringUtils;
import java.util.*;
/**
* @author Jason van Zyl
* @author Kristian Rosenvold
*/
//TODO: The configuration for the lifecycle needs to be externalized so that I can use the annotations properly for the wiring and reference and external source for the lifecycle configuration.
public class DefaultLifecycles
implements Initializable
{
// @Configuration(source="org/apache/maven/lifecycle/lifecycles.xml")
private List<Lifecycle> lifecycles;
private List<Scheduling> schedules;
/**
* We use this to display all the lifecycles available and their phases to users. Currently this is primarily
* used in the IDE integrations where a UI is presented to the user and they can select the lifecycle phase
* they would like to execute.
*/
private Map<String, Lifecycle> lifecycleMap;
/**
* We use this to map all phases to the lifecycle that contains it. This is used so that a user can specify the
* phase they want to execute and we can easily determine what lifecycle we need to run.
*/
private Map<String, Lifecycle> phaseToLifecycleMap;
@SuppressWarnings({"UnusedDeclaration"})
public DefaultLifecycles()
{
}
public DefaultLifecycles( List<Lifecycle> lifecycles, List<Scheduling> schedules )
{
this.lifecycles = lifecycles;
this.schedules = schedules;
}
public void initialize()
throws InitializationException
{
lifecycleMap = new HashMap<String, Lifecycle>();
// If people are going to make their own lifecycles then we need to tell people how to namespace them correctly so
// that they don't interfere with internally defined lifecycles.
phaseToLifecycleMap = new HashMap<String, Lifecycle>();
for ( Lifecycle lifecycle : lifecycles )
{
for ( String phase : lifecycle.getPhases() )
{
// The first definition wins.
if ( !phaseToLifecycleMap.containsKey( phase ) )
{
phaseToLifecycleMap.put( phase, lifecycle );
}
}
lifecycleMap.put( lifecycle.getId(), lifecycle );
}
}
public List<ExecutionPlanItem> createExecutionPlanItem( MavenProject mavenProject, List<MojoExecution> executions )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
{
BuilderCommon.attachToThread( mavenProject );
List<ExecutionPlanItem> result = new ArrayList<ExecutionPlanItem>();
for ( MojoExecution mojoExecution : executions )
{
String lifeCyclePhase = mojoExecution.getMojoDescriptor().getPhase();
final Scheduling scheduling = getScheduling( "default" );
Schedule schedule = null;
if ( scheduling != null )
{
schedule = scheduling.getSchedule( mojoExecution.getPlugin() );
if ( schedule == null )
{
schedule = scheduling.getSchedule( lifeCyclePhase );
}
}
result.add( new ExecutionPlanItem( mojoExecution, schedule ) );
}
return result;
}
/**
* Gets scheduling associated with a given phase.
* <p/>
* This is part of the experimental weave mode and therefore not part of the public api.
*
* @param lifecyclePhaseName
* @return
*/
private Scheduling getScheduling( String lifecyclePhaseName )
{
for ( Scheduling schedule : schedules )
{
if ( lifecyclePhaseName.equals( schedule.getLifecycle() ) )
{
return schedule;
}
}
return null;
}
public Lifecycle get( String key )
{
return phaseToLifecycleMap.get( key );
}
public Map<String, Lifecycle> getPhaseToLifecycleMap()
{
return phaseToLifecycleMap;
}
public List<Lifecycle> getLifeCycles()
{
return lifecycles;
}
public List<Scheduling> getSchedules()
{
return schedules;
}
public String getLifecyclePhaseList()
{
Set<String> phases = new LinkedHashSet<String>();
for ( Lifecycle lifecycle : lifecycles )
{
phases.addAll( lifecycle.getPhases() );
}
return StringUtils.join( phases.iterator(), ", " );
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import java.util.Set;
import org.apache.maven.model.Plugin;
/**
* @author Kristian Rosenvold
*/
public interface LifeCyclePluginAnalyzer {
Set<Plugin> getPluginsBoundByDefaultToAllLifecycles(String packaging);
}

View File

@ -27,6 +27,14 @@
*/
public class Lifecycle
{
public Lifecycle() {
}
public Lifecycle(String id, List<String> phases, Map<String, String> defaultPhases) {
this.id = id;
this.phases = phases;
this.defaultPhases = defaultPhases;
}
// <lifecycle>
// <id>clean</id>

View File

@ -28,7 +28,7 @@
*
* @author Benjamin Bentmann
*/
interface LifecycleEventCatapult
public interface LifecycleEventCatapult
{
/**

View File

@ -1,4 +1,18 @@
package org.apache.maven.lifecycle;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
@ -52,19 +66,19 @@ public LifecycleExecutionException( String message, MavenProject project )
this.project = project;
}
LifecycleExecutionException( String message, MojoExecution execution, MavenProject project )
public LifecycleExecutionException( String message, MojoExecution execution, MavenProject project )
{
super( message );
this.project = project;
}
LifecycleExecutionException( String message, MojoExecution execution, MavenProject project, Throwable cause )
public LifecycleExecutionException( String message, MojoExecution execution, MavenProject project, Throwable cause )
{
super( message, cause );
this.project = project;
}
LifecycleExecutionException( MojoExecution execution, MavenProject project, Throwable cause )
public LifecycleExecutionException( MojoExecution execution, MavenProject project, Throwable cause )
{
this( createMessage( execution, project, cause ), execution, project, cause );
}

View File

@ -19,21 +19,10 @@
* under the License.
*/
import java.util.List;
import java.util.Set;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
/**
* @author Jason van Zyl
@ -45,25 +34,10 @@ public interface LifecycleExecutor
@Deprecated
String ROLE = LifecycleExecutor.class.getName();
/**
* Calculate the list of {@link org.apache.maven.plugin.descriptor.MojoDescriptor} objects to run for the selected lifecycle phase.
*
* @param phase
* @param session
* @return
* @throws InvalidPluginDescriptorException
* @throws LifecycleExecutionException
*/
MavenExecutionPlan calculateExecutionPlan( MavenSession session, String... tasks )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException,
InvalidPluginDescriptorException, PluginManagerException, LifecyclePhaseNotFoundException,
LifecycleNotFoundException, PluginVersionResolutionException;
// For a given project packaging find all the plugins that are bound to any registered
// lifecycles. The project builder needs to now what default plugin information needs to be
// merged into POM being built. Once the POM builder has this plugin information, versions can be assigned
// by the POM builder because they will have to be defined in plugin management. Once this is done then it
// by the POM builder because they will have to be defined in plugin management. Once this is setComplete then it
// can be passed back so that the default configuraiton information can be populated.
//
// We need to know the specific version so that we can lookup the right version of the plugin descriptor
@ -77,33 +51,4 @@ MavenExecutionPlan calculateExecutionPlan( MavenSession session, String... tasks
void execute( MavenSession session );
/**
* Calculates the forked mojo executions requested by the mojo associated with the specified mojo execution.
*
* @param mojoExecution The mojo execution for which to calculate the forked mojo executions, must not be {@code
* null}.
* @param session The current build session that holds the projects and further settings, must not be {@code null}.
*/
void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session )
throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException;
/**
* Executes the previously calculated forked mojo executions of the given mojo execution. If the specified mojo
* execution requires no forking, this method does nothing. The return value denotes a subset of the projects from
* the session that have been forked. The method {@link MavenProject#getExecutionProject()} of those projects
* returns the project clone on which the forked execution were performed. It is the responsibility of the caller to
* reset those execution projects to {@code null} once they are no longer needed to free memory and to avoid
* accidental usage by unrelated mojos.
*
* @param mojoExecution The mojo execution whose forked mojo executions should be processed, must not be {@code
* null}.
* @param session The current build session that holds the projects and further settings, must not be {@code null}.
* @return The (unmodifiable) list of projects that have been forked, can be empty if no forking was required but
* will never be {@code null}.
*/
List<MavenProject> executeForkedExecutions( MojoExecution mojoExecution, MavenSession session )
throws LifecycleExecutionException;
}

View File

@ -19,10 +19,11 @@
* under the License.
*/
import java.util.List;
import java.util.Set;
import java.util.*;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
//TODO: lifecycles being executed
//TODO: what runs in each phase
@ -30,29 +31,77 @@
//TODO: project dependencies that need downloading
//TODO: unfortunately the plugins need to be downloaded in order to get the plugin.xml file. need to externalize this from the plugin archive.
//TODO: this will be the class that people get in IDEs to modify
public class MavenExecutionPlan
public class MavenExecutionPlan implements Iterable<ExecutionPlanItem>
{
/** Individual executions that must be performed. */
private List<MojoExecution> executions;
/*
At the moment, this class is totally immutable, and this is in line with thoughts about the
pre-calculated execution plan that stays the same during the execution.
If deciding to add mutable state to this class, it should be at least considered to
separate this into a separate mutable structure.
*/
/** For project dependency resolution, the scopes of resolution required if any. */
private Set<String> requiredDependencyResolutionScopes;
private final Set<String> requiredDependencyResolutionScopes;
/** For project dependency collection, the scopes of collection required if any. */
private Set<String> requiredDependencyCollectionScopes;
private final Set<String> requiredDependencyCollectionScopes;
public MavenExecutionPlan( List<MojoExecution> executions, Set<String> requiredDependencyResolutionScopes,
Set<String> requiredDependencyCollectionScopes )
{
this.executions = executions;
private final List<ExecutionPlanItem> planItem;
private final Map<String, ExecutionPlanItem> lastInPhase;
private final List<String> phasesInOrder;
public MavenExecutionPlan(Set<String> requiredDependencyResolutionScopes, Set<String> requiredDependencyCollectionScopes, List<ExecutionPlanItem> planItem) {
this.requiredDependencyResolutionScopes = requiredDependencyResolutionScopes;
this.requiredDependencyCollectionScopes = requiredDependencyCollectionScopes;
this.planItem = planItem;
lastInPhase = new HashMap<String, ExecutionPlanItem>();
phasesInOrder = new ArrayList<String>();
for (ExecutionPlanItem executionPlanItem : getExecutionPlanItems()) {
final String phaseName = getPhase( executionPlanItem );
if (!lastInPhase.containsKey( phaseName )){
phasesInOrder.add( phaseName );
}
lastInPhase.put( phaseName, executionPlanItem );
}
}
public List<MojoExecution> getExecutions()
{
return executions;
private String getPhase( ExecutionPlanItem executionPlanItem){
final MojoExecution mojoExecution = executionPlanItem.getMojoExecution();
final MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
return mojoDescriptor.getPhase();
}
public Iterator<ExecutionPlanItem> iterator() {
return getExecutionPlanItems().iterator();
}
/**
* Returns the last ExecutionPlanItem in the supplied phase. If no items are in the specified phase,
* the closest upstream item will be returned.
* @param executionPlanItem The execution plan item
* @return The ExecutionPlanItem or null if none can be found
*/
public ExecutionPlanItem findLastInPhase( ExecutionPlanItem executionPlanItem){
ExecutionPlanItem executionPlanItem1 = lastInPhase.get( getPhase( executionPlanItem ) );
return executionPlanItem1;
}
private List<ExecutionPlanItem> getExecutionPlanItems()
{
return planItem;
}
public void forceAllComplete(){
for (ExecutionPlanItem executionPlanItem : getExecutionPlanItems()) {
executionPlanItem.forceComplete();
}
}
public Set<String> getRequiredResolutionScopes()
{
@ -64,4 +113,17 @@ public Set<String> getRequiredCollectionScopes()
return requiredDependencyCollectionScopes;
}
public List<MojoExecution> getMojoExecutions(){
List<MojoExecution> result = new ArrayList<MojoExecution>();
for ( ExecutionPlanItem executionPlanItem : planItem )
{
result.add( executionPlanItem.getMojoExecution());
}
return result;
}
public int size() {
return planItem.size();
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
/**
* @author Kristian Rosenvold
*/
public class Schedule {
private String phase;
private String mojoClass;
private boolean mojoSynchronized;
// Indicates that this phase/mojo does not need to respect the reactor-dependency graph
// (Module lifecycle order still must be respected )
private boolean parallel;
public Schedule() {
}
public Schedule( String phase, boolean mojoSynchronized, boolean parallel ) {
this.phase = phase;
this.mojoSynchronized = mojoSynchronized;
this.parallel = parallel;
}
public boolean isMissingPhase(){
return null == phase;
}
public String getPhase() {
return phase;
}
public void setPhase(String phase) {
this.phase = phase;
}
public String getMojoClass() {
return mojoClass;
}
public void setMojoClass(String mojoClass) {
this.mojoClass = mojoClass;
}
public boolean isMojoSynchronized() {
return mojoSynchronized;
}
public void setMojoSynchronized(boolean mojoSynchronized) {
this.mojoSynchronized = mojoSynchronized;
}
public boolean isParallel()
{
return parallel;
}
public void setParallel( boolean parallel )
{
this.parallel = parallel;
}
@Override
public String toString() {
return "Schedule{" +
"phase='" + phase + '\'' +
", mojoClass='" + mojoClass + '\'' +
", mojoSynchronized=" + mojoSynchronized +
", parallel=" + parallel +
'}';
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import org.apache.maven.model.Plugin;
import java.util.List;
import java.util.Map;
/**
* Class Scheduling.
*/
public class Scheduling
{
private String lifecycle;
private List<Schedule> schedules;
public Scheduling() {
}
public Scheduling(String lifecycle, List<Schedule> schedules) {
this.lifecycle = lifecycle;
this.schedules = schedules;
}
public String getLifecycle() {
return lifecycle;
}
public void setLifecycle(String lifecycle) {
this.lifecycle = lifecycle;
}
public List<Schedule> getSchedules() {
return schedules;
}
public Schedule getSchedule(String phaseName){
if (phaseName == null) return null;
for (Schedule schedule : schedules) {
if (phaseName.equals(schedule.getPhase()) )
return schedule;
}
return null;
}
public Schedule getSchedule(Plugin mojoClass){
if (mojoClass == null) return null;
for (Schedule schedule : schedules) {
if (mojoClass.getKey().equals(schedule.getMojoClass()) )
return schedule;
}
return null;
}
public void setSchedules(List<Schedule> schedules) {
this.schedules = schedules;
}
}

View File

@ -0,0 +1,102 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author Kristian Rosenvold
* This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = BuildListCalculator.class)
public class BuildListCalculator
{
@Requirement
private LifecycleTaskSegmentCalculator lifeCycleTaskSegmentCalculator;
@SuppressWarnings({"UnusedDeclaration"})
public BuildListCalculator()
{
}
public BuildListCalculator( LifecycleTaskSegmentCalculator lifeCycleTaskSegmentCalculator )
{
this.lifeCycleTaskSegmentCalculator = lifeCycleTaskSegmentCalculator;
}
public List<TaskSegment> calculateTaskSegments( MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException, LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
MavenProject rootProject = session.getTopLevelProject();
List<String> tasks = session.getGoals();
if ( tasks == null || tasks.isEmpty() )
{
if ( !StringUtils.isEmpty( rootProject.getDefaultGoal() ) )
{
tasks = Arrays.asList( StringUtils.split( rootProject.getDefaultGoal() ) );
}
}
return lifeCycleTaskSegmentCalculator.calculateTaskSegments( session, tasks );
}
public ProjectBuildList calculateProjectBuilds( MavenSession session, List<TaskSegment> taskSegments )
{
List<ProjectSegment> projectBuilds = new ArrayList<ProjectSegment>();
MavenProject rootProject = session.getTopLevelProject();
for ( TaskSegment taskSegment : taskSegments )
{
List<MavenProject> projects;
if ( taskSegment.isAggregating() )
{
projects = Collections.singletonList( rootProject );
}
else
{
projects = session.getProjects();
}
for ( MavenProject project : projects )
{
BuilderCommon.attachToThread( project ); // Not totally sure if this is needed for anything
MavenSession copiedSession = session.clone();
copiedSession.setCurrentProject( project );
projectBuilds.add( new ProjectSegment( project, taskSegment, copiedSession ) );
}
}
return new ProjectBuildList( projectBuilds );
}
}

View File

@ -0,0 +1,131 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.BuildFailure;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.*;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
/**
* Common code that is shared by the LifecycleModuleBuilder and the LifeCycleWeaveBuilder
*
* @author Kristian Rosenvold
* Builds one or more lifecycles for a full module
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = BuilderCommon.class)
public class BuilderCommon
{
@Requirement
private LifecycleDebugLogger lifecycleDebugLogger;
@Requirement
private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
@Requirement
private LifecycleDependencyResolver lifecycleDependencyResolver;
@SuppressWarnings({"UnusedDeclaration"})
public BuilderCommon()
{
}
public BuilderCommon( LifecycleDebugLogger lifecycleDebugLogger,
LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator,
LifecycleDependencyResolver lifecycleDependencyResolver )
{
this.lifecycleDebugLogger = lifecycleDebugLogger;
this.lifeCycleExecutionPlanCalculator = lifeCycleExecutionPlanCalculator;
this.lifecycleDependencyResolver = lifecycleDependencyResolver;
}
public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject project, TaskSegment taskSegment )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException,
LifecycleExecutionException
{
MavenExecutionPlan executionPlan =
lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, project, taskSegment.getTasks() );
lifecycleDebugLogger.debugProjectPlan( project, executionPlan );
// TODO: once we have calculated the build plan then we should accurately be able to download
// the project dependencies. Having it happen in the plugin manager is a tangled mess. We can optimize
// this later by looking at the build plan. Would be better to just batch download everything required
// by the reactor.
lifecycleDependencyResolver.resolveDependencies( taskSegment.isAggregating(), project, session, executionPlan );
return executionPlan;
}
public static void handleBuildError( final ReactorContext buildContext, final MavenSession rootSession,
final MavenProject mavenProject, final Exception e, final long buildStartTime )
{
buildContext.getResult().addException( e );
long buildEndTime = System.currentTimeMillis();
buildContext.getResult().addBuildSummary( new BuildFailure( mavenProject, buildEndTime - buildStartTime, e ) );
DefaultLifecycleExecutor.fireEvent( rootSession, null, LifecycleEventCatapult.PROJECT_FAILED );
if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( rootSession.getReactorFailureBehavior() ) )
{
// continue the build
}
else if ( MavenExecutionRequest.REACTOR_FAIL_AT_END.equals( rootSession.getReactorFailureBehavior() ) )
{
// continue the build but ban all projects that depend on the failed one
buildContext.getReactorBuildStatus().blackList( mavenProject );
}
else if ( MavenExecutionRequest.REACTOR_FAIL_FAST.equals( rootSession.getReactorFailureBehavior() ) )
{
buildContext.getReactorBuildStatus().halt();
}
else
{
throw new IllegalArgumentException(
"invalid reactor failure behavior " + rootSession.getReactorFailureBehavior() );
}
}
public static void attachToThread( MavenProject currentProject )
{
ClassRealm projectRealm = currentProject.getClassRealm();
if ( projectRealm != null )
{
Thread.currentThread().setContextClassLoader( projectRealm );
}
}
// Todo: I'm really wondering where this method belongs; smells like it should be on MavenProject, but for some reason it isn't ?
// This localization is kind-of a code smell.
public static String getKey( MavenProject project )
{
return project.getGroupId() + ':' + project.getArtifactId() + ':' + project.getVersion();
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.List;
/**
* @author Kristian Rosenvold
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public class BuiltLogItem
{
private final ExecutionPlanItem executionPlanItem;
private final MavenProject project;
private final long startTime;
private long endTime;
private final List<WaitLogEntry> waits = new ArrayList<WaitLogEntry>();
public BuiltLogItem( MavenProject project, ExecutionPlanItem executionPlanItem )
{
this.executionPlanItem = executionPlanItem;
this.project = project;
startTime = System.currentTimeMillis();
}
public void setComplete()
{
endTime = System.currentTimeMillis();
}
public void addWait( MavenProject upstreamProject, ExecutionPlanItem inSchedule, long startWait )
{
long now = System.currentTimeMillis();
if ( ( now - startWait ) > 1 )
{
waits.add( new WaitLogEntry( upstreamProject, inSchedule, startWait, now ) );
}
}
public String toString( long rootStart )
{
StringBuilder result = new StringBuilder();
result.append( String.format( "%1d %2d ", startTime - rootStart, endTime - rootStart ) );
result.append( project.getName() );
result.append( " " );
result.append( executionPlanItem.getMojoExecution().getArtifactId() );
for ( WaitLogEntry waitLogEntry : waits )
{
result.append( waitLogEntry.toString() );
}
return result.toString();
}
class WaitLogEntry
{
private final ExecutionPlanItem executionPlanItem;
private final MavenProject upstreamProject;
private final long start;
private final long stop;
WaitLogEntry( MavenProject upstreamProject, ExecutionPlanItem executionPlanItem, long start, long stop )
{
this.upstreamProject = upstreamProject;
this.executionPlanItem = executionPlanItem;
this.start = start;
this.stop = stop;
}
public String toString()
{
return upstreamProject.getName() + " " + executionPlanItem.getMojoExecution().getArtifactId() + ", wait=" +
( stop - start );
}
}
}

View File

@ -0,0 +1,104 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* Presents a view of the Dependency Graph that is suited for concurrent building.
*
* @author Kristian Rosenvold
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public class ConcurrencyDependencyGraph
{
private final ProjectBuildList projectBuilds;
private final ProjectDependencyGraph projectDependencyGraph;
private final HashSet<MavenProject> finishedProjects = new HashSet<MavenProject>();
public ConcurrencyDependencyGraph( ProjectBuildList projectBuilds, ProjectDependencyGraph projectDependencyGraph )
{
this.projectDependencyGraph = projectDependencyGraph;
this.projectBuilds = projectBuilds;
}
public int getNumberOfBuilds()
{
return projectBuilds.size();
}
/**
* Gets all the builds that have no reactor-dependencies
*
* @return A list of all the initial builds
*/
public List<MavenProject> getRootSchedulableBuilds()
{
List<MavenProject> result = new ArrayList<MavenProject>();
for ( ProjectSegment projectBuild : projectBuilds )
{
if ( projectDependencyGraph.getUpstreamProjects( projectBuild.getProject(), false ).size() == 0 )
{
result.add( projectBuild.getProject() );
}
}
return result;
}
/**
* Marks the provided project as finished. Returns a list of
*
* @param mavenProject The project
* @return The list of builds that are eligible for starting now that the provided project is done
*/
public List<MavenProject> markAsFinished( MavenProject mavenProject )
{
finishedProjects.add( mavenProject );
return getSchedulableNewProcesses( mavenProject );
}
private List<MavenProject> getSchedulableNewProcesses( MavenProject finishedProject )
{
List<MavenProject> result = new ArrayList<MavenProject>();
// schedule dependent projects, if all of their requirements are met
for ( MavenProject dependentProject : projectDependencyGraph.getDownstreamProjects( finishedProject, false ) )
{
final List<MavenProject> upstreamProjects =
projectDependencyGraph.getUpstreamProjects( dependentProject, false );
if ( finishedProjects.containsAll( upstreamProjects ) )
{
result.add( dependentProject );
}
}
return result;
}
public ProjectBuildList getProjectBuilds()
{
return projectBuilds;
}
}

View File

@ -0,0 +1,75 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Handles all concurrency-related logging.
* <p/>
* The logging/diagnostic needs of a concurrent build are different from a linear build. This
* delta required to analyze a concurrent build is located here.
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*
* @author Kristian Rosenvold
*/
public class ConcurrentBuildLogger
{
private final long startTime;
private final Map<MavenProject, Thread> threadMap = new ConcurrentHashMap<MavenProject, Thread>();
public ConcurrentBuildLogger()
{
startTime = System.currentTimeMillis();
}
List<BuiltLogItem> items = Collections.synchronizedList( new ArrayList<BuiltLogItem>() );
public BuiltLogItem createBuildLogItem( MavenProject project, ExecutionPlanItem current )
{
threadMap.put( project, Thread.currentThread() );
BuiltLogItem result = new BuiltLogItem( project, current );
items.add( result );
return result;
}
public String toString()
{
StringBuilder result = new StringBuilder();
for ( Map.Entry<MavenProject, Thread> mavenProjectThreadEntry : threadMap.entrySet() )
{
result.append( mavenProjectThreadEntry.getKey().getName() );
result.append( " ran on " );
result.append( mavenProjectThreadEntry.getValue().getName() );
result.append( "\n" );
}
for ( BuiltLogItem builtLogItem : items )
{
result.append( builtLogItem.toString( startTime ) );
result.append( "\n" );
}
return result.toString();
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.project.MavenProject;
import java.util.Collection;
/**
* Context of dependency artifacts for the entire build.
*
* @author Benjamin Bentmann
* @author Kristian Rosenvold (class extract only)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
// TODO: From a concurrecy perspective, this class is not good. The combination of mutable/immutable state is not nice
public class DependencyContext
{
private final Collection<String> scopesToCollect;
private final Collection<String> scopesToResolve;
private final boolean aggregating;
private volatile MavenProject lastProject;
private volatile Collection<?> lastDependencyArtifacts;
private volatile int lastDependencyArtifactCount;
private DependencyContext( Collection<String> scopesToCollect, Collection<String> scopesToResolve,
boolean aggregating )
{
this.scopesToCollect = scopesToCollect;
this.scopesToResolve = scopesToResolve;
this.aggregating = aggregating;
}
public DependencyContext( MavenExecutionPlan executionPlan, boolean aggregating )
{
this( executionPlan.getRequiredCollectionScopes(), executionPlan.getRequiredResolutionScopes(), aggregating );
}
public void setLastDependencyArtifacts( Collection<?> lastDependencyArtifacts )
{
this.lastDependencyArtifacts = lastDependencyArtifacts;
lastDependencyArtifactCount = ( lastDependencyArtifacts != null ) ? lastDependencyArtifacts.size() : 0;
}
public MavenProject getLastProject()
{
return lastProject;
}
public void setLastProject( MavenProject lastProject )
{
this.lastProject = lastProject;
}
public Collection<String> getScopesToCollect()
{
return scopesToCollect;
}
public Collection<String> getScopesToResolve()
{
return scopesToResolve;
}
public boolean isAggregating()
{
return aggregating;
}
public DependencyContext clone()
{
return new DependencyContext( scopesToCollect, scopesToResolve, aggregating );
}
public boolean isSameProject( MavenSession session )
{
return ( lastProject == session.getCurrentProject() );
}
public boolean isSameButUpdatedProject( MavenSession session )
{
if ( isSameProject( session ) )
{
if ( lastDependencyArtifacts != lastProject.getDependencyArtifacts() ||
( lastDependencyArtifacts != null && lastDependencyArtifactCount != lastDependencyArtifacts.size() ) )
{
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,128 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.lifecycle.Schedule;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Wraps individual MojoExecutions, containing information about completion status and scheduling.
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*
* @author Kristian Rosenvold
*/
public class ExecutionPlanItem
{
private final MojoExecution mojoExecution;
private final Schedule schedule;
// Completeness just indicates that it has been run or failed
private final AtomicBoolean complete = new AtomicBoolean( false );
private final Object monitor = new Object();
public ExecutionPlanItem( MojoExecution mojoExecution, Schedule schedule )
{
this.mojoExecution = mojoExecution;
this.schedule = schedule;
}
public MojoExecution getMojoExecution()
{
return mojoExecution;
}
public void setComplete()
{
boolean transitionSuccessful = ensureComplete();
if ( !transitionSuccessful )
{
throw new IllegalStateException( "Expected to be able to setComplete node, but was complete already" );
}
}
public boolean ensureComplete()
{
boolean f = complete.compareAndSet( false, true );
notifyListeners();
return f;
}
private void notifyListeners()
{
synchronized ( monitor )
{
monitor.notifyAll();
}
}
public void forceComplete()
{
final boolean b = complete.getAndSet( true );
if ( !b )
{
notifyListeners();
} // Release anyone waiting for us
}
public void waitUntilDone()
throws InterruptedException
{
synchronized ( monitor )
{
while ( !complete.get() )
{
monitor.wait( 100 );
}
}
}
public Schedule getSchedule()
{
return schedule;
}
public boolean hasSchedule( Schedule other )
{
if ( getSchedule() != null && !getSchedule().isMissingPhase() )
{
if ( other.getPhase().equals( getSchedule().getPhase() ) )
{
return true;
}
}
return false;
}
public Plugin getPlugin()
{
final MojoDescriptor mojoDescriptor = getMojoExecution().getMojoDescriptor();
return mojoDescriptor.getPluginDescriptor().getPlugin();
}
@Override
public String toString()
{
return "ExecutionPlanItem{" + ", mojoExecution=" + mojoExecution + ", schedule=" + schedule + '}' +
super.toString();
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
/**
* A task that is a goal
* <p/>
* TODO: From a concurrecy perspective, this class is not good. The combination of mutable/immutable state is not nice
*
* @author Benjamin Bentmann
*/
public final class GoalTask
{
final String pluginGoal;
public GoalTask( String pluginGoal )
{
this.pluginGoal = pluginGoal;
}
@Override
public String toString()
{
return pluginGoal;
}
}

View File

@ -0,0 +1,172 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Logs debug output from the various lifecycle phases.
*
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author Kristian Rosenvold (extracted class only)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleDebugLogger.class)
public class LifecycleDebugLogger
{
@Requirement
private Logger logger;
@SuppressWarnings({"UnusedDeclaration"})
public LifecycleDebugLogger()
{
}
public LifecycleDebugLogger( Logger logger )
{
this.logger = logger;
}
public void debug( String s )
{
logger.debug( s );
}
public void info( String s )
{
logger.info( s );
}
public void debugReactorPlan( ProjectBuildList projectBuilds )
{
if ( !logger.isDebugEnabled() )
{
return;
}
logger.debug( "=== REACTOR BUILD PLAN ================================================" );
for ( Iterator<ProjectSegment> it = projectBuilds.iterator(); it.hasNext(); )
{
ProjectSegment projectBuild = it.next();
logger.debug( "Project: " + projectBuild.getProject().getId() );
logger.debug( "Tasks: " + projectBuild.getTaskSegment().getTasks() );
logger.debug( "Style: " + ( projectBuild.getTaskSegment().isAggregating() ? "Aggregating" : "Regular" ) );
if ( it.hasNext() )
{
logger.debug( "-----------------------------------------------------------------------" );
}
}
logger.debug( "=======================================================================" );
}
public void debugProjectPlan( MavenProject currentProject, MavenExecutionPlan executionPlan )
{
logger.debug( "=== PROJECT BUILD PLAN ================================================" );
logger.debug( "Project: " + BuilderCommon.getKey( currentProject ) );
logger.debug( "Dependencies (collect): " + executionPlan.getRequiredCollectionScopes() );
logger.debug( "Dependencies (resolve): " + executionPlan.getRequiredResolutionScopes() );
for ( ExecutionPlanItem mojoExecution : executionPlan )
{
debugMojoExecution( mojoExecution.getMojoExecution() );
}
logger.debug( "=======================================================================" );
}
private void debugMojoExecution( MojoExecution mojoExecution )
{
String mojoExecId =
mojoExecution.getGroupId() + ':' + mojoExecution.getArtifactId() + ':' + mojoExecution.getVersion() + ':' +
mojoExecution.getGoal() + " (" + mojoExecution.getExecutionId() + ')';
Map<String, List<MojoExecution>> forkedExecutions = mojoExecution.getForkedExecutions();
if ( !forkedExecutions.isEmpty() )
{
for ( Map.Entry<String, List<MojoExecution>> fork : forkedExecutions.entrySet() )
{
logger.debug( "--- init fork of " + fork.getKey() + " for " + mojoExecId + " ---" );
for ( MojoExecution forkedExecution : fork.getValue() )
{
debugMojoExecution( forkedExecution );
}
logger.debug( "--- exit fork of " + fork.getKey() + " for " + mojoExecId + " ---" );
}
}
logger.debug( "-----------------------------------------------------------------------" );
logger.debug( "Goal: " + mojoExecId );
logger.debug(
"Style: " + ( mojoExecution.getMojoDescriptor().isAggregator() ? "Aggregating" : "Regular" ) );
logger.debug( "Configuration: " + mojoExecution.getConfiguration() );
}
public void logWeavePlan( MavenSession session )
{
if ( !logger.isInfoEnabled() )
{
return;
}
final ProjectDependencyGraph dependencyGraph = session.getProjectDependencyGraph();
logger.info( "=== WEAVE CONCURRENCY BUILD PLAN ================================================" );
for ( MavenProject mavenProject : dependencyGraph.getSortedProjects() )
{
StringBuilder item = new StringBuilder();
item.append( "Project: " );
item.append( mavenProject.getArtifactId() );
final List<MavenProject> upstreamProjects = dependencyGraph.getUpstreamProjects( mavenProject, false );
if ( upstreamProjects.size() > 0 )
{
item.append( " ( " );
for ( Iterator<MavenProject> it = upstreamProjects.iterator(); it.hasNext(); )
{
final MavenProject kid = it.next();
item.append( kid.getArtifactId() );
if ( it.hasNext() )
{
item.append( ", " );
}
}
item.append( ")" );
}
logger.info( item.toString() );
}
logger.info( "=======================================================================" );
}
}

View File

@ -0,0 +1,254 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.ProjectDependenciesResolver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.model.Dependency;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import java.util.*;
/**
* Resolves dependencies for the artifacts in context of the lifecycle build
*
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author Kristian Rosenvold (extracted class)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleDependencyResolver.class)
public class LifecycleDependencyResolver
{
@Requirement
private ProjectDependenciesResolver projectDependenciesResolver;
@Requirement
private Logger logger;
@SuppressWarnings({"UnusedDeclaration"})
public LifecycleDependencyResolver()
{
}
public LifecycleDependencyResolver( ProjectDependenciesResolver projectDependenciesResolver, Logger logger )
{
this.projectDependenciesResolver = projectDependenciesResolver;
this.logger = logger;
}
public void resolveDependencies( boolean aggregating, MavenProject currentProject,
MavenSession sessionForThisModule, MavenExecutionPlan executionPlan )
throws LifecycleExecutionException
{
List<MavenProject> projectsToResolve = getProjects( currentProject, sessionForThisModule, aggregating );
resolveDependencies( aggregating, sessionForThisModule, executionPlan, projectsToResolve );
}
public static List<MavenProject> getProjects( MavenProject project, MavenSession session, boolean aggregator )
{
if ( aggregator )
{
return session.getProjects();
}
else
{
return Collections.singletonList( project );
}
}
public void checkForUpdate( MavenSession session, DependencyContext dependenctContext )
throws LifecycleExecutionException
{
if ( dependenctContext.isSameButUpdatedProject( session ) )
{
resolveProjectDependencies( dependenctContext.getLastProject(), dependenctContext.getScopesToCollect(),
dependenctContext.getScopesToResolve(), session,
dependenctContext.isAggregating() );
}
dependenctContext.setLastProject( session.getCurrentProject() );
dependenctContext.setLastDependencyArtifacts( session.getCurrentProject().getDependencyArtifacts() );
}
private void resolveDependencies( boolean aggregating, MavenSession session, MavenExecutionPlan executionPlan,
List<MavenProject> projectsToResolve )
throws LifecycleExecutionException
{
for ( MavenProject project : projectsToResolve )
{
resolveDependencies( project, aggregating, session, executionPlan );
}
}
private void resolveDependencies( MavenProject project, boolean aggregating, MavenSession session,
MavenExecutionPlan executionPlan )
throws LifecycleExecutionException
{
resolveProjectDependencies( project, executionPlan.getRequiredCollectionScopes(),
executionPlan.getRequiredResolutionScopes(), session, aggregating );
}
private void resolveProjectDependencies( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
boolean aggregating )
throws LifecycleExecutionException
{
Set<Artifact> artifacts =
getProjectDependencies( project, scopesToCollect, scopesToResolve, session, aggregating );
updateProjectArtifacts( project, artifacts );
}
private void updateProjectArtifacts( MavenProject project, Set<Artifact> artifacts )
{
project.setResolvedArtifacts( artifacts );
if ( project.getDependencyArtifacts() == null )
{
project.setDependencyArtifacts( getDependencyArtifacts( project, artifacts ) );
}
}
private Set<Artifact> getProjectDependencies( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session,
boolean aggregating )
throws LifecycleExecutionException
{
Set<Artifact> artifacts;
try
{
try
{
artifacts = projectDependenciesResolver.resolve( project, scopesToCollect, scopesToResolve, session );
}
catch ( MultipleArtifactsNotFoundException e )
{
/*
* MNG-2277, the check below compensates for our bad plugin support where we ended up with aggregator
* plugins that require dependency resolution although they usually run in phases of the build where project
* artifacts haven't been assembled yet. The prime example of this is "mvn release:prepare".
*/
if ( aggregating && areAllArtifactsInReactor( session.getProjects(), e.getMissingArtifacts() ) )
{
logger.warn( "The following artifacts could not be resolved at this point of the build" +
" but seem to be part of the reactor:" );
for ( Artifact artifact : e.getMissingArtifacts() )
{
logger.warn( "o " + artifact.getId() );
}
logger.warn( "Try running the build up to the lifecycle phase \"package\"" );
artifacts = new LinkedHashSet<Artifact>( e.getResolvedArtifacts() );
}
else
{
throw e;
}
}
return artifacts;
}
catch ( ArtifactResolutionException e )
{
throw new LifecycleExecutionException( null, project, e );
}
catch ( ArtifactNotFoundException e )
{
throw new LifecycleExecutionException( null, project, e );
}
}
private Set<Artifact> getDependencyArtifacts( MavenProject project, Set<Artifact> artifacts )
{
Set<String> directDependencies = new HashSet<String>( project.getDependencies().size() * 2 );
for ( Dependency dependency : project.getDependencies() )
{
directDependencies.add( dependency.getManagementKey() );
}
Set<Artifact> dependencyArtifacts = new LinkedHashSet<Artifact>( project.getDependencies().size() * 2 );
for ( Artifact artifact : artifacts )
{
if ( directDependencies.contains( artifact.getDependencyConflictId() ) )
{
dependencyArtifacts.add( artifact );
}
}
return dependencyArtifacts;
}
private boolean areAllArtifactsInReactor( Collection<MavenProject> projects, Collection<Artifact> artifacts )
{
Set<String> projectKeys = getReactorProjectKeys( projects );
for ( Artifact artifact : artifacts )
{
String key = ArtifactUtils.key( artifact );
if ( !projectKeys.contains( key ) )
{
return false;
}
}
return true;
}
private Set<String> getReactorProjectKeys( Collection<MavenProject> projects )
{
Set<String> projectKeys = new HashSet<String>( projects.size() * 2 );
for ( MavenProject project : projects )
{
String key = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
projectKeys.add( key );
}
return projectKeys;
}
public void reResolveReactorArtifacts( ProjectBuildList projectBuilds, boolean aggregating, MavenProject project,
MavenSession session, MavenExecutionPlan executionPlan )
throws LifecycleExecutionException
{
final Set<String> reactorProjectKeys = projectBuilds.getReactorProjectKeys();
final Set<Artifact> artifactSet = project.getArtifacts();
for ( Artifact artifact : artifactSet )
{
String key = ArtifactUtils.key( artifact );
if ( reactorProjectKeys.contains( key ) )
{
artifact.setResolved( false );
}
}
resolveDependencies( aggregating, project, session, executionPlan );
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import java.util.List;
/**
* @author Benjamin Bentmann
* @author Kristian Rosenvold (extract interface only)
* <p/>
* NOTE: interface is not part of any public api and can be changed or deleted without prior notice.
*/
public interface LifecycleExecutionPlanCalculator
{
MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException;
}

View File

@ -0,0 +1,673 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.*;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.lifecycle.Execution;
import org.apache.maven.plugin.lifecycle.Phase;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.plugin.version.PluginVersionResolver;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.IOException;
import java.util.*;
/**
* @author Benjamin Bentmann
* @author Kristian Rosenvold (Extract class)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleExecutionPlanCalculator.class)
public class LifecycleExecutionPlanCalculatorImpl
implements LifecycleExecutionPlanCalculator
{
@Requirement
private PluginVersionResolver pluginVersionResolver;
@Requirement
private BuildPluginManager pluginManager;
@Requirement
private DefaultLifecycles defaultLifeCycles;
@Requirement
private MojoDescriptorCreator mojoDescriptorCreator;
@Requirement
private LifecyclePluginResolver lifecyclePluginResolver;
@SuppressWarnings({"UnusedDeclaration"})
public LifecycleExecutionPlanCalculatorImpl()
{
}
public LifecycleExecutionPlanCalculatorImpl( BuildPluginManager pluginManager, DefaultLifecycles defaultLifeCycles,
MojoDescriptorCreator mojoDescriptorCreator,
LifecyclePluginResolver lifecyclePluginResolver )
{
this.pluginManager = pluginManager;
this.defaultLifeCycles = defaultLifeCycles;
this.mojoDescriptorCreator = mojoDescriptorCreator;
this.lifecyclePluginResolver = lifecyclePluginResolver;
}
public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
{
Set<String> requiredDependencyResolutionScopes = new TreeSet<String>();
Set<String> requiredDependencyCollectionScopes = new TreeSet<String>();
final List<MojoExecution> executions =
calculateExecutionPlan( session, project, tasks, requiredDependencyResolutionScopes,
requiredDependencyCollectionScopes );
final List<ExecutionPlanItem> planItem = defaultLifeCycles.createExecutionPlanItem( project, executions );
return new MavenExecutionPlan( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
planItem );
}
public List<MojoExecution> calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks,
Set<String> requiredDependencyResolutionScopes,
Set<String> requiredDependencyCollectionScopes )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
{
lifecyclePluginResolver.resolveMissingPluginVersions( project, session );
List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
for ( Object task : tasks )
{
if ( task instanceof GoalTask )
{
String pluginGoal = ( (GoalTask) task ).pluginGoal;
MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( pluginGoal, session, project );
MojoExecution mojoExecution =
new MojoExecution( mojoDescriptor, "default-cli", MojoExecution.Source.CLI );
mojoExecutions.add( mojoExecution );
}
else if ( task instanceof LifecycleTask )
{
String lifecyclePhase = ( (LifecycleTask) task ).getLifecyclePhase();
Map<String, List<MojoExecution>> phaseToMojoMapping =
calculateLifecycleMappings( session, project, lifecyclePhase );
for ( List<MojoExecution> mojoExecutionsFromLifecycle : phaseToMojoMapping.values() )
{
mojoExecutions.addAll( mojoExecutionsFromLifecycle );
}
}
else
{
throw new IllegalStateException( "unexpected task " + task );
}
}
for ( MojoExecution mojoExecution : mojoExecutions )
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( mojoDescriptor == null )
{
mojoDescriptor = pluginManager.getMojoDescriptor( mojoExecution.getPlugin(), mojoExecution.getGoal(),
DefaultRepositoryRequest.getRepositoryRequest(
session, project ) );
mojoExecution.setMojoDescriptor( mojoDescriptor );
}
populateMojoExecutionConfiguration( project, mojoExecution,
MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) );
finalizeMojoConfiguration( mojoExecution );
calculateForkedExecutions( mojoExecution, session, project, new HashSet<MojoDescriptor>() );
collectDependencyRequirements( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
mojoExecution );
}
return mojoExecutions;
}
private static void collectDependencyRequirements( Collection<String> requiredDependencyResolutionScopes,
Collection<String> requiredDependencyCollectionScopes,
MojoExecution mojoExecution )
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
String requiredDependencyResolutionScope = mojoDescriptor.getDependencyResolutionRequired();
if ( StringUtils.isNotEmpty( requiredDependencyResolutionScope ) )
{
requiredDependencyResolutionScopes.add( requiredDependencyResolutionScope );
}
String requiredDependencyCollectionScope = mojoDescriptor.getDependencyCollectionRequired();
if ( StringUtils.isNotEmpty( requiredDependencyCollectionScope ) )
{
requiredDependencyCollectionScopes.add( requiredDependencyCollectionScope );
}
for ( List<MojoExecution> forkedExecutions : mojoExecution.getForkedExecutions().values() )
{
for ( MojoExecution forkedExecution : forkedExecutions )
{
collectDependencyRequirements( requiredDependencyResolutionScopes, requiredDependencyCollectionScopes,
forkedExecution );
}
}
}
private Map<String, List<MojoExecution>> calculateLifecycleMappings( MavenSession session, MavenProject project,
String lifecyclePhase )
throws LifecyclePhaseNotFoundException, PluginNotFoundException, PluginResolutionException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException
{
/*
* Determine the lifecycle that corresponds to the given phase.
*/
Lifecycle lifecycle = defaultLifeCycles.get( lifecyclePhase );
if ( lifecycle == null )
{
throw new LifecyclePhaseNotFoundException(
"Unknown lifecycle phase \"" + lifecyclePhase + "\". You must specify a valid lifecycle phase" +
" or a goal in the format <plugin-prefix>:<goal> or" +
" <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: " +
defaultLifeCycles.getLifecyclePhaseList() + ".", lifecyclePhase );
}
/*
* Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
* is interested in, i.e. all phases up to and including the specified phase.
*/
Map<String, Map<Integer, List<MojoExecution>>> mappings =
new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();
for ( String phase : lifecycle.getPhases() )
{
Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<Integer, List<MojoExecution>>();
mappings.put( phase, phaseBindings );
if ( phase.equals( lifecyclePhase ) )
{
break;
}
}
/*
* Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
* the project already contains the plugin executions induced by the project's packaging type. Remember, all
* phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
* interested in any of the executions bound to it.
*/
for ( Plugin plugin : project.getBuild().getPlugins() )
{
for ( PluginExecution execution : plugin.getExecutions() )
{
// if the phase is specified then I don't have to go fetch the plugin yet and pull it down
// to examine the phase it is associated to.
if ( execution.getPhase() != null )
{
Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
if ( phaseBindings != null )
{
for ( String goal : execution.getGoals() )
{
MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() );
mojoExecution.setLifecyclePhase( execution.getPhase() );
addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
}
}
}
// if not then i need to grab the mojo descriptor and look at the phase that is specified
else
{
for ( String goal : execution.getGoals() )
{
MojoDescriptor mojoDescriptor = pluginManager.getMojoDescriptor( plugin, goal,
DefaultRepositoryRequest.getRepositoryRequest(
session, project ) );
Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
if ( phaseBindings != null )
{
MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
mojoExecution.setLifecyclePhase( mojoDescriptor.getPhase() );
addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
}
}
}
}
}
Map<String, List<MojoExecution>> lifecycleMappings = new LinkedHashMap<String, List<MojoExecution>>();
for ( Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet() )
{
List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
for ( List<MojoExecution> executions : entry.getValue().values() )
{
mojoExecutions.addAll( executions );
}
lifecycleMappings.put( entry.getKey(), mojoExecutions );
}
return lifecycleMappings;
}
private void addMojoExecution( Map<Integer, List<MojoExecution>> phaseBindings, MojoExecution mojoExecution,
int priority )
{
List<MojoExecution> mojoExecutions = phaseBindings.get( priority );
if ( mojoExecutions == null )
{
mojoExecutions = new ArrayList<MojoExecution>();
phaseBindings.put( priority, mojoExecutions );
}
mojoExecutions.add( mojoExecution );
}
private void populateMojoExecutionConfiguration( MavenProject project, MojoExecution mojoExecution,
boolean allowPluginLevelConfig )
{
String g = mojoExecution.getGroupId();
String a = mojoExecution.getArtifactId();
Plugin plugin = findPlugin( g, a, project.getBuildPlugins() );
if ( plugin == null && project.getPluginManagement() != null )
{
plugin = findPlugin( g, a, project.getPluginManagement().getPlugins() );
}
if ( plugin != null )
{
PluginExecution pluginExecution =
findPluginExecution( mojoExecution.getExecutionId(), plugin.getExecutions() );
Xpp3Dom pomConfiguration = null;
if ( pluginExecution != null )
{
pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration();
}
else if ( allowPluginLevelConfig )
{
pomConfiguration = (Xpp3Dom) plugin.getConfiguration();
}
Xpp3Dom mojoConfiguration = ( pomConfiguration != null ) ? new Xpp3Dom( pomConfiguration ) : null;
mojoConfiguration = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration );
mojoExecution.setConfiguration( mojoConfiguration );
}
}
private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
{
for ( Plugin plugin : plugins )
{
if ( artifactId.equals( plugin.getArtifactId() ) && groupId.equals( plugin.getGroupId() ) )
{
return plugin;
}
}
return null;
}
private PluginExecution findPluginExecution( String executionId, Collection<PluginExecution> executions )
{
if ( StringUtils.isNotEmpty( executionId ) )
{
for ( PluginExecution execution : executions )
{
if ( executionId.equals( execution.getId() ) )
{
return execution;
}
}
}
return null;
}
/**
* Post-processes the effective configuration for the specified mojo execution. This step discards all parameters
* from the configuration that are not applicable to the mojo and injects the default values for any missing
* parameters.
*
* @param mojoExecution The mojo execution whose configuration should be finalized, must not be {@code null}.
*/
private void finalizeMojoConfiguration( MojoExecution mojoExecution )
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
Xpp3Dom executionConfiguration = mojoExecution.getConfiguration();
if ( executionConfiguration == null )
{
executionConfiguration = new Xpp3Dom( "configuration" );
}
Xpp3Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor );
Xpp3Dom finalConfiguration = new Xpp3Dom( "configuration" );
if ( mojoDescriptor.getParameters() != null )
{
for ( Parameter parameter : mojoDescriptor.getParameters() )
{
Xpp3Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() );
if ( parameterConfiguration == null )
{
parameterConfiguration = executionConfiguration.getChild( parameter.getAlias() );
}
Xpp3Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() );
parameterConfiguration =
Xpp3Dom.mergeXpp3Dom( parameterConfiguration, parameterDefaults, Boolean.TRUE );
if ( parameterConfiguration != null )
{
parameterConfiguration = new Xpp3Dom( parameterConfiguration, parameter.getName() );
if ( StringUtils.isEmpty( parameterConfiguration.getAttribute( "implementation" ) ) &&
StringUtils.isNotEmpty( parameter.getImplementation() ) )
{
parameterConfiguration.setAttribute( "implementation", parameter.getImplementation() );
}
finalConfiguration.addChild( parameterConfiguration );
}
}
}
mojoExecution.setConfiguration( finalConfiguration );
}
private Xpp3Dom getMojoConfiguration( MojoDescriptor mojoDescriptor )
{
return MojoDescriptorCreator.convert( mojoDescriptor );
}
private void calculateForkedExecutions( MojoExecution mojoExecution, MavenSession session, MavenProject project,
Collection<MojoDescriptor> alreadyForkedExecutions )
throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( !mojoDescriptor.isForking() )
{
return;
}
if ( !alreadyForkedExecutions.add( mojoDescriptor ) )
{
return;
}
List<MavenProject> forkedProjects =
LifecycleDependencyResolver.getProjects( project, session, mojoDescriptor.isAggregator() );
for ( MavenProject forkedProject : forkedProjects )
{
List<MojoExecution> forkedExecutions;
if ( StringUtils.isNotEmpty( mojoDescriptor.getExecutePhase() ) )
{
forkedExecutions =
calculateForkedLifecycle( mojoExecution, session, forkedProject, alreadyForkedExecutions );
}
else
{
forkedExecutions =
calculateForkedGoal( mojoExecution, session, forkedProject, alreadyForkedExecutions );
}
mojoExecution.setForkedExecutions( BuilderCommon.getKey( forkedProject ), forkedExecutions );
}
alreadyForkedExecutions.remove( mojoDescriptor );
}
private List<MojoExecution> calculateForkedLifecycle( MojoExecution mojoExecution, MavenSession session,
MavenProject project,
Collection<MojoDescriptor> alreadyForkedExecutions )
throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
String forkedPhase = mojoDescriptor.getExecutePhase();
Map<String, List<MojoExecution>> lifecycleMappings =
calculateLifecycleMappings( session, project, forkedPhase );
for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
{
for ( MojoExecution forkedExecution : forkedExecutions )
{
if ( forkedExecution.getMojoDescriptor() == null )
{
MojoDescriptor forkedMojoDescriptor =
pluginManager.getMojoDescriptor( forkedExecution.getPlugin(), forkedExecution.getGoal(),
DefaultRepositoryRequest.getRepositoryRequest( session,
project ) );
forkedExecution.setMojoDescriptor( forkedMojoDescriptor );
}
populateMojoExecutionConfiguration( project, forkedExecution, false );
}
}
injectLifecycleOverlay( lifecycleMappings, mojoExecution, session, project );
List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
for ( List<MojoExecution> forkedExecutions : lifecycleMappings.values() )
{
for ( MojoExecution forkedExecution : forkedExecutions )
{
if ( !alreadyForkedExecutions.contains( forkedExecution.getMojoDescriptor() ) )
{
finalizeMojoConfiguration( forkedExecution );
calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
mojoExecutions.add( forkedExecution );
}
}
}
return mojoExecutions;
}
private void injectLifecycleOverlay( Map<String, List<MojoExecution>> lifecycleMappings,
MojoExecution mojoExecution, MavenSession session, MavenProject project )
throws PluginDescriptorParsingException, LifecycleNotFoundException, MojoNotFoundException,
PluginNotFoundException, PluginResolutionException, NoPluginFoundForPrefixException,
InvalidPluginDescriptorException, PluginVersionResolutionException
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
String forkedLifecycle = mojoDescriptor.getExecuteLifecycle();
if ( StringUtils.isEmpty( forkedLifecycle ) )
{
return;
}
org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
try
{
lifecycleOverlay = pluginDescriptor.getLifecycleMapping( forkedLifecycle );
}
catch ( IOException e )
{
throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
}
catch ( XmlPullParserException e )
{
throw new PluginDescriptorParsingException( pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e );
}
if ( lifecycleOverlay == null )
{
throw new LifecycleNotFoundException( forkedLifecycle );
}
for ( Phase phase : lifecycleOverlay.getPhases() )
{
List<MojoExecution> forkedExecutions = lifecycleMappings.get( phase.getId() );
if ( forkedExecutions != null )
{
for ( Execution execution : phase.getExecutions() )
{
for ( String goal : execution.getGoals() )
{
MojoDescriptor forkedMojoDescriptor;
if ( goal.indexOf( ':' ) < 0 )
{
forkedMojoDescriptor = pluginDescriptor.getMojo( goal );
if ( forkedMojoDescriptor == null )
{
throw new MojoNotFoundException( goal, pluginDescriptor );
}
}
else
{
forkedMojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( goal, session, project );
}
MojoExecution forkedExecution =
new MojoExecution( forkedMojoDescriptor, mojoExecution.getExecutionId() );
Xpp3Dom forkedConfiguration = (Xpp3Dom) execution.getConfiguration();
forkedExecution.setConfiguration( forkedConfiguration );
populateMojoExecutionConfiguration( project, forkedExecution, true );
forkedExecutions.add( forkedExecution );
}
}
Xpp3Dom phaseConfiguration = (Xpp3Dom) phase.getConfiguration();
if ( phaseConfiguration != null )
{
for ( MojoExecution forkedExecution : forkedExecutions )
{
Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration();
forkedConfiguration = Xpp3Dom.mergeXpp3Dom( phaseConfiguration, forkedConfiguration );
forkedExecution.setConfiguration( forkedConfiguration );
}
}
}
}
}
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
//TODO: take repo mans into account as one may be aggregating prefixes of many
//TODO: collect at the root of the repository, read the one at the root, and fetch remote if something is missing
// or the user forces the issue
private List<MojoExecution> calculateForkedGoal( MojoExecution mojoExecution, MavenSession session,
MavenProject project,
Collection<MojoDescriptor> alreadyForkedExecutions )
throws MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
PluginDescriptorParsingException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException, PluginVersionResolutionException
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
String forkedGoal = mojoDescriptor.getExecuteGoal();
MojoDescriptor forkedMojoDescriptor = pluginDescriptor.getMojo( forkedGoal );
if ( forkedMojoDescriptor == null )
{
throw new MojoNotFoundException( forkedGoal, pluginDescriptor );
}
if ( alreadyForkedExecutions.contains( forkedMojoDescriptor ) )
{
return Collections.emptyList();
}
MojoExecution forkedExecution = new MojoExecution( forkedMojoDescriptor, forkedGoal );
populateMojoExecutionConfiguration( project, forkedExecution, true );
finalizeMojoConfiguration( forkedExecution );
calculateForkedExecutions( forkedExecution, session, project, alreadyForkedExecutions );
return Collections.singletonList( forkedExecution );
}
}

View File

@ -0,0 +1,96 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.BuildSuccess;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.DefaultLifecycleExecutor;
import org.apache.maven.lifecycle.LifecycleEventCatapult;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
/**
* Builds one or more lifecycles for a full module
*
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author Kristian Rosenvold (extracted class)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleModuleBuilder.class)
public class LifecycleModuleBuilder
{
@Requirement
private MojoExecutor mojoExecutor;
@Requirement
private BuilderCommon builderCommon;
public void buildProject( MavenSession session, ReactorContext reactorContext, MavenProject currentProject,
TaskSegment taskSegment )
{
buildProject( session, session, reactorContext, currentProject, taskSegment );
}
public void buildProject( MavenSession session, MavenSession rootSession, ReactorContext reactorContext,
MavenProject currentProject, TaskSegment taskSegment )
{
boolean isAggregating = taskSegment.isAggregating();
session.setCurrentProject( currentProject );
long buildStartTime = System.currentTimeMillis();
try
{
if ( reactorContext.getReactorBuildStatus().isHaltedOrBlacklisted( currentProject ) )
{
DefaultLifecycleExecutor.fireEvent( session, null, LifecycleEventCatapult.PROJECT_SKIPPED );
return;
}
DefaultLifecycleExecutor.fireEvent( session, null, LifecycleEventCatapult.PROJECT_STARTED );
BuilderCommon.attachToThread( currentProject );
MavenExecutionPlan executionPlan = builderCommon.resolveBuildPlan( session, currentProject, taskSegment );
DependencyContext dependencyContext = new DependencyContext( executionPlan, isAggregating );
mojoExecutor.execute( session, executionPlan.getMojoExecutions(), reactorContext.getProjectIndex(),
dependencyContext );
long buildEndTime = System.currentTimeMillis();
reactorContext.getResult().addBuildSummary(
new BuildSuccess( currentProject, buildEndTime - buildStartTime ) );
DefaultLifecycleExecutor.fireEvent( session, null, LifecycleEventCatapult.PROJECT_SUCCEEDED );
}
catch ( Exception e )
{
BuilderCommon.handleBuildError( reactorContext, rootSession, currentProject, e, buildStartTime );
}
finally
{
session.setCurrentProject( null );
Thread.currentThread().setContextClassLoader( reactorContext.getOriginalContextClassLoader() );
}
}
}

View File

@ -0,0 +1,161 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.lifecycle.DefaultLifecycles;
import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
import org.apache.maven.lifecycle.Lifecycle;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author jdcasey
* @author Kristian Rosenvold (extracted class only)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecyclePluginAnalyzerImpl.class)
public class LifecyclePluginAnalyzerImpl
implements LifeCyclePluginAnalyzer
{
@Requirement
private Map<String, LifecycleMapping> lifecycleMappings;
@Requirement
private DefaultLifecycles defaultLifeCycles;
@Requirement
private Logger logger;
public LifecyclePluginAnalyzerImpl()
{
}
// These methods deal with construction intact Plugin object that look like they come from a standard
// <plugin/> block in a Maven POM. We have to do some wiggling to pull the sources of information
// together and this really shows the problem of constructing a sensible default configuration but
// it's all encapsulated here so it appears normalized to the POM builder.
// We are going to take the project packaging and find all plugin in the default lifecycle and create
// fully populated Plugin objects, including executions with goals and default configuration taken
// from the plugin.xml inside a plugin.
//
public Set<Plugin> getPluginsBoundByDefaultToAllLifecycles( String packaging )
{
if ( logger.isDebugEnabled() )
{
logger.debug( "Looking up lifecyle mappings for packaging " + packaging + " from " +
Thread.currentThread().getContextClassLoader() );
}
LifecycleMapping lifecycleMappingForPackaging = lifecycleMappings.get( packaging );
if ( lifecycleMappingForPackaging == null )
{
return null;
}
Map<Plugin, Plugin> plugins = new LinkedHashMap<Plugin, Plugin>();
for ( Lifecycle lifecycle : defaultLifeCycles.getLifeCycles() )
{
org.apache.maven.lifecycle.mapping.Lifecycle lifecycleConfiguration =
lifecycleMappingForPackaging.getLifecycles().get( lifecycle.getId() );
Map<String, String> phaseToGoalMapping = null;
if ( lifecycleConfiguration != null )
{
phaseToGoalMapping = lifecycleConfiguration.getPhases();
}
else if ( lifecycle.getDefaultPhases() != null )
{
phaseToGoalMapping = lifecycle.getDefaultPhases();
}
if ( phaseToGoalMapping != null )
{
// These are of the form:
//
// compile -> org.apache.maven.plugins:maven-compiler-plugin:compile[,gid:aid:goal,...]
//
for ( Map.Entry<String, String> goalsForLifecyclePhase : phaseToGoalMapping.entrySet() )
{
String phase = goalsForLifecyclePhase.getKey();
String goals = goalsForLifecyclePhase.getValue();
if ( goals != null )
{
parseLifecyclePhaseDefinitions( plugins, phase, goals );
}
}
}
}
return plugins.keySet();
}
private void parseLifecyclePhaseDefinitions( Map<Plugin, Plugin> plugins, String phase, String goals )
{
String[] mojos = StringUtils.split( goals, "," );
for ( int i = 0; i < mojos.length; i++ )
{
// either <groupId>:<artifactId>:<goal> or <groupId>:<artifactId>:<version>:<goal>
String goal = mojos[i].trim();
String[] p = StringUtils.split( goal, ":" );
PluginExecution execution = new PluginExecution();
execution.setId( "default-" + p[p.length - 1] );
execution.setPhase( phase );
execution.setPriority( i - mojos.length );
execution.getGoals().add( p[p.length - 1] );
Plugin plugin = new Plugin();
plugin.setGroupId( p[0] );
plugin.setArtifactId( p[1] );
if ( p.length >= 4 )
{
plugin.setVersion( p[2] );
}
Plugin existing = plugins.get( plugin );
if ( existing != null )
{
plugin = existing;
}
else
{
plugins.put( plugin, plugin );
}
plugin.getExecutions().add( execution );
}
}
}

View File

@ -0,0 +1,86 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.plugin.version.PluginVersionResolver;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import java.util.HashMap;
import java.util.Map;
/**
* @author Benjamin Bentmann
* @author Kristian Rosenvold (Extract class)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecyclePluginResolver.class)
public class LifecyclePluginResolver
{
@Requirement
private PluginVersionResolver pluginVersionResolver;
public LifecyclePluginResolver( PluginVersionResolver pluginVersionResolver )
{
this.pluginVersionResolver = pluginVersionResolver;
}
@SuppressWarnings({"UnusedDeclaration"})
public LifecyclePluginResolver()
{
}
public void resolveMissingPluginVersions( MavenProject project, MavenSession session )
throws PluginVersionResolutionException
{
Map<String, String> versions = new HashMap<String, String>();
for ( Plugin plugin : project.getBuildPlugins() )
{
if ( plugin.getVersion() == null )
{
PluginVersionRequest request = new DefaultPluginVersionRequest( plugin, session );
plugin.setVersion( pluginVersionResolver.resolve( request ).getVersion() );
}
versions.put( plugin.getKey(), plugin.getVersion() );
}
PluginManagement pluginManagement = project.getPluginManagement();
if ( pluginManagement != null )
{
for ( Plugin plugin : pluginManagement.getPlugins() )
{
if ( plugin.getVersion() == null )
{
plugin.setVersion( versions.get( plugin.getKey() ) );
if ( plugin.getVersion() == null )
{
PluginVersionRequest request = new DefaultPluginVersionRequest( plugin, session );
plugin.setVersion( pluginVersionResolver.resolve( request ).getVersion() );
}
}
}
}
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
/**
* A task that is a lifecycle
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*
* @author Benjamin Bentmann
*/
public final class LifecycleTask
{
private final String lifecyclePhase;
public LifecycleTask( String lifecyclePhase )
{
this.lifecyclePhase = lifecyclePhase;
}
@Override
public String toString()
{
return getLifecyclePhase();
}
public String getLifecyclePhase()
{
return lifecyclePhase;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import java.util.List;
/**
* Calculates the task segments in the build
*
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author jdcasey
* @author Kristian Rosenvold (extracted interface)
* <p/>
* NOTE: This interface is not part of any public api and can be changed or deleted without prior notice.
*/
public interface LifecycleTaskSegmentCalculator
{
List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException;
public boolean requiresProject( MavenSession session );
}

View File

@ -0,0 +1,122 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import java.util.ArrayList;
import java.util.List;
/**
* Calculates the task segments in the build
*
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author jdcasey
* @author Kristian Rosenvold (extracted class)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleTaskSegmentCalculator.class)
public class LifecycleTaskSegmentCalculatorImpl
implements LifecycleTaskSegmentCalculator
{
@Requirement
private MojoDescriptorCreator mojoDescriptorCreator;
@Requirement
private LifecyclePluginResolver lifecyclePluginResolver;
public LifecycleTaskSegmentCalculatorImpl()
{
}
public List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException
{
List<TaskSegment> taskSegments = new ArrayList<TaskSegment>( tasks.size() );
TaskSegment currentSegment = null;
for ( String task : tasks )
{
if ( isGoalSpecification( task ) )
{
// "pluginPrefix:goal" or "groupId:artifactId[:version]:goal"
lifecyclePluginResolver.resolveMissingPluginVersions( session.getTopLevelProject(), session );
MojoDescriptor mojoDescriptor =
mojoDescriptorCreator.getMojoDescriptor( task, session, session.getTopLevelProject() );
boolean aggregating = mojoDescriptor.isAggregator() || !mojoDescriptor.isProjectRequired();
if ( currentSegment == null || currentSegment.isAggregating() != aggregating )
{
currentSegment = new TaskSegment( aggregating );
taskSegments.add( currentSegment );
}
currentSegment.getTasks().add( new GoalTask( task ) );
}
else
{
// lifecycle phase
if ( currentSegment == null || currentSegment.isAggregating() )
{
currentSegment = new TaskSegment( false );
taskSegments.add( currentSegment );
}
currentSegment.getTasks().add( new LifecycleTask( task ) );
}
}
return taskSegments;
}
public boolean requiresProject( MavenSession session )
{
List<String> goals = session.getGoals();
if ( goals != null )
{
for ( String goal : goals )
{
if ( !isGoalSpecification( goal ) )
{
return true;
}
}
}
return false;
}
private boolean isGoalSpecification( String task )
{
return task.indexOf( ':' ) >= 0;
}
}

View File

@ -0,0 +1,173 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
*
* @author Kristian Rosenvold
* Builds one or more lifecycles for a full module
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleThreadedBuilder.class)
public class LifecycleThreadedBuilder
{
@Requirement
private Logger logger;
@Requirement
private LifecycleModuleBuilder lifecycleModuleBuilder;
@SuppressWarnings({"UnusedDeclaration"})
public LifecycleThreadedBuilder()
{
}
public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
List<TaskSegment> currentTaskSegment, ConcurrencyDependencyGraph analyzer,
CompletionService<ProjectSegment> service )
{
// Currently disabled
ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( analyzer.getProjectBuilds(), System.out );
for ( TaskSegment taskSegment : currentTaskSegment )
{
Map<MavenProject, ProjectSegment> projectBuildMap = projectBuilds.selectSegment( taskSegment );
try
{
multiThreadedProjectTaskSegmentBuild( analyzer, reactorContext, session, service, taskSegment, projectBuildMap, muxer );
if ( reactorContext.getReactorBuildStatus().isHalted() )
{
break;
}
if ( reactorContext.getReactorBuildStatus().isHalted() )
{
break;
}
}
catch ( Exception e )
{
break; // Why are we just ignoring this exception? Are exceptions are being used for flow control
}
}
}
private void multiThreadedProjectTaskSegmentBuild( ConcurrencyDependencyGraph analyzer,
ReactorContext reactorContext, MavenSession rootSession,
CompletionService<ProjectSegment> service,
TaskSegment taskSegment, Map<MavenProject, ProjectSegment> projectBuildList,
ThreadOutputMuxer muxer )
{
// schedule independent projects
for ( MavenProject mavenProject : analyzer.getRootSchedulableBuilds() )
{
ProjectSegment projectSegment = projectBuildList.get( mavenProject );
logger.debug( "Scheduling: " + projectSegment.getProject() );
Callable<ProjectSegment> cb =
createBuildCallable( rootSession, projectSegment, reactorContext, taskSegment, muxer );
service.submit( cb );
}
// for each finished project
for ( int i = 0; i < analyzer.getNumberOfBuilds(); i++ )
{
try
{
ProjectSegment projectBuild = service.take().get();
if ( reactorContext.getReactorBuildStatus().isHalted() )
{
break;
}
final List<MavenProject> newItemsThatCanBeBuilt =
analyzer.markAsFinished( projectBuild.getProject() );
for ( MavenProject mavenProject : newItemsThatCanBeBuilt )
{
ProjectSegment scheduledDependent = projectBuildList.get( mavenProject );
logger.debug( "Scheduling: " + scheduledDependent );
Callable<ProjectSegment> cb =
createBuildCallable( rootSession, scheduledDependent, reactorContext, taskSegment, muxer );
service.submit( cb );
}
}
catch ( InterruptedException e )
{
break;
}
catch ( ExecutionException e )
{
break;
}
}
// cancel outstanding builds (if any) - this can happen if an exception is thrown in above block
Future<ProjectSegment> unprocessed;
while ( ( unprocessed = service.poll() ) != null )
{
try
{
unprocessed.get();
}
catch ( InterruptedException e )
{
throw new RuntimeException( e );
}
catch ( ExecutionException e )
{
throw new RuntimeException( e );
}
}
}
private Callable<ProjectSegment> createBuildCallable( final MavenSession rootSession,
final ProjectSegment projectBuild,
final ReactorContext reactorContext,
final TaskSegment taskSegment, final ThreadOutputMuxer muxer )
{
return new Callable<ProjectSegment>()
{
public ProjectSegment call()
{
// muxer.associateThreadWithProjectSegment( projectBuild );
lifecycleModuleBuilder.buildProject( projectBuild.getSession(), rootSession, reactorContext,
projectBuild.getProject(), taskSegment );
// muxer.setThisModuleComplete( projectBuild );
return projectBuild;
}
};
}
}

View File

@ -0,0 +1,306 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.BuildSuccess;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.*;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
* <p/>
* NOTE: Weave mode is still experimental. It may be either promoted to first class citizen
* at some later point in time, and it may also be removed entirely. Weave mode has much more aggressive
* concurrency behaviour than regular threaded mode, and as such is still under test wrt cross platform stability.
* <p/>
* To remove weave mode from m3, the following should be removed:
* ExecutionPlanItem.schedule w/setters and getters
* DefaultLifeCycles.getScheduling() and all its use
* ReactorArtifactRepository has a reference to isWeave too.
* This class and its usage
*
* @author Kristian Rosenvold
* Builds one or more lifecycles for a full module
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = LifecycleWeaveBuilder.class)
public class LifecycleWeaveBuilder
{
@Requirement
private MojoExecutor mojoExecutor;
@Requirement
private BuilderCommon builderCommon;
@Requirement
private Logger logger;
@Requirement
private LifecycleDependencyResolver lifecycleDependencyResolver;
private final Map<MavenProject, MavenExecutionPlan> executionPlans =
Collections.synchronizedMap( new HashMap<MavenProject, MavenExecutionPlan>() );
@SuppressWarnings({"UnusedDeclaration"})
public LifecycleWeaveBuilder()
{
}
public LifecycleWeaveBuilder( MojoExecutor mojoExecutor, BuilderCommon builderCommon, Logger logger,
LifecycleDependencyResolver lifecycleDependencyResolver )
{
this.mojoExecutor = mojoExecutor;
this.builderCommon = builderCommon;
this.logger = logger;
this.lifecycleDependencyResolver = lifecycleDependencyResolver;
}
public void build( ProjectBuildList projectBuilds, ReactorContext buildContext, List<TaskSegment> taskSegments,
MavenSession session, CompletionService<ProjectSegment> service, ReactorBuildStatus reactorBuildStatus )
throws ExecutionException, InterruptedException
{
ConcurrentBuildLogger concurrentBuildLogger = new ConcurrentBuildLogger();
try
{
final List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
for ( TaskSegment taskSegment : taskSegments )
{
ProjectBuildList segmentChunks = projectBuilds.getByTaskSegment( taskSegment );
ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( segmentChunks, System.out );
for ( ProjectSegment projectBuild : segmentChunks )
{
try
{
MavenExecutionPlan executionPlan =
builderCommon.resolveBuildPlan( projectBuild.getSession(), projectBuild.getProject(),
projectBuild.getTaskSegment() );
executionPlans.put( projectBuild.getProject(), executionPlan );
DependencyContext dependencyContext =
new DependencyContext( executionPlan, projectBuild.getTaskSegment().isAggregating() );
final Callable<ProjectSegment> projectBuilder =
createCallableForBuildingOneFullModule( buildContext, session, reactorBuildStatus,
executionPlan, projectBuild, muxer,
dependencyContext, concurrentBuildLogger,
projectBuilds );
futures.add( service.submit( projectBuilder ) );
}
catch ( Exception e )
{
throw new ExecutionException( e );
}
}
for ( Future<ProjectSegment> buildFuture : futures )
{
buildFuture.get(); // At this point, this build *is* finished.
// Do not leak threads past here or evil gremlins will get you!
}
futures.clear();
}
}
finally
{
projectBuilds.closeAll();
}
logger.info( concurrentBuildLogger.toString() );
}
private Callable<ProjectSegment> createCallableForBuildingOneFullModule( final ReactorContext reactorContext,
final MavenSession rootSession,
final ReactorBuildStatus reactorBuildStatus,
final MavenExecutionPlan executionPlan,
final ProjectSegment projectBuild,
final ThreadOutputMuxer muxer,
final DependencyContext dependencyContext,
final ConcurrentBuildLogger concurrentBuildLogger,
final ProjectBuildList projectBuilds )
{
return new Callable<ProjectSegment>()
{
public ProjectSegment call()
throws Exception
{
Iterator<ExecutionPlanItem> planItems = executionPlan.iterator();
ExecutionPlanItem current = planItems.hasNext() ? planItems.next() : null;
long buildStartTime = System.currentTimeMillis();
//muxer.associateThreadWithProjectSegment( projectBuild );
if ( reactorBuildStatus.isHaltedOrBlacklisted( projectBuild.getProject() ) )
{
DefaultLifecycleExecutor.fireEvent( projectBuild.getSession(), null,
LifecycleEventCatapult.PROJECT_SKIPPED );
return null;
}
DefaultLifecycleExecutor.fireEvent( projectBuild.getSession(), null,
LifecycleEventCatapult.PROJECT_STARTED );
boolean packagePhaseSeen = false;
boolean runBAbyRun = false;
try
{
while ( current != null && !reactorBuildStatus.isHalted() &&
!reactorBuildStatus.isBlackListed( projectBuild.getProject() ) )
{
final String phase = current.getMojoExecution().getMojoDescriptor().getPhase();
PhaseRecorder phaseRecorder = new PhaseRecorder( projectBuild.getProject() );
if ( !packagePhaseSeen && phase != null && phase.equals( "package" ) )
{
// Re-resolve. A bit of a kludge ATM
packagePhaseSeen = true;
lifecycleDependencyResolver.reResolveReactorArtifacts( projectBuilds, false,
projectBuild.getProject(),
projectBuild.getSession(),
executionPlan );
}
BuiltLogItem builtLogItem =
concurrentBuildLogger.createBuildLogItem( projectBuild.getProject(), current );
final Schedule schedule = current.getSchedule();
if ( schedule != null && schedule.isMojoSynchronized() )
{
synchronized ( current.getPlugin() )
{
buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
phaseRecorder );
}
}
else
{
buildExecutionPlanItem( reactorContext, current, projectBuild, dependencyContext,
phaseRecorder );
}
current.setComplete();
builtLogItem.setComplete();
ExecutionPlanItem next = planItems.hasNext() ? planItems.next() : null;
if ( next != null )
{
final Schedule scheduleOfNext = next.getSchedule();
if ( !runBAbyRun && ( scheduleOfNext == null || !scheduleOfNext.isParallel() ) )
{
for ( MavenProject upstreamProject : projectBuild.getImmediateUpstreamProjects() )
{
final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
final ExecutionPlanItem inSchedule = upstreamPlan.findLastInPhase( next );
if ( inSchedule != null )
{
long startWait = System.currentTimeMillis();
inSchedule.waitUntilDone();
builtLogItem.addWait( upstreamProject, inSchedule, startWait );
}
}
}
}
current = next;
if ( packagePhaseSeen && !runBAbyRun )
{
runBAbyRun = true;
}
}
final long wallClockTime = System.currentTimeMillis() - buildStartTime;
final BuildSuccess summary =
new BuildSuccess( projectBuild.getProject(), wallClockTime ); // - waitingTime
reactorContext.getResult().addBuildSummary( summary );
DefaultLifecycleExecutor.fireEvent( projectBuild.getSession(), null,
LifecycleEventCatapult.PROJECT_SUCCEEDED );
}
catch ( Exception e )
{
BuilderCommon.handleBuildError( reactorContext, rootSession, projectBuild.getProject(), e,
buildStartTime );
}
finally
{
if ( current != null )
{
executionPlan.forceAllComplete();
}
// muxer.setThisModuleComplete( projectBuild );
}
return null;
}
};
}
private void buildExecutionPlanItem( ReactorContext reactorContext, ExecutionPlanItem node,
ProjectSegment projectBuild, DependencyContext dependencyContext,
PhaseRecorder phaseRecorder )
throws LifecycleExecutionException
{
MavenProject currentProject = projectBuild.getProject();
long buildStartTime = System.currentTimeMillis();
MavenSession sessionForThisModule = projectBuild.getSession();
try
{
if ( reactorContext.getReactorBuildStatus().isHaltedOrBlacklisted( currentProject ) )
{
return;
}
BuilderCommon.attachToThread( currentProject );
mojoExecutor.execute( sessionForThisModule, node.getMojoExecution(), reactorContext.getProjectIndex(),
dependencyContext, phaseRecorder );
final BuildSuccess summary =
new BuildSuccess( currentProject, System.currentTimeMillis() - buildStartTime );
reactorContext.getResult().addBuildSummary( summary );
}
finally
{
Thread.currentThread().setContextClassLoader( reactorContext.getOriginalContextClassLoader() );
}
}
public static boolean isWeaveMode( MavenExecutionRequest request )
{
return "true".equals( request.getUserProperties().getProperty( "maven3.weaveMode" ) );
}
public static void setWeaveMode( Properties properties )
{
properties.setProperty( "maven3.weaveMode", "true" );
}
}

View File

@ -0,0 +1,256 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
import org.apache.maven.artifact.repository.RepositoryRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.prefix.*;
import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.plugin.version.PluginVersionResolver;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.StringTokenizer;
/**
* Resolves dependencies for the artifacts in context of the lifecycle build
*
* @author Benjamin Bentmann
* @author Jason van Zyl
* @author jdcasey
* @author Kristian Rosenvold (extracted class only)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = MojoDescriptorCreator.class)
public class MojoDescriptorCreator
{
@Requirement
private PluginVersionResolver pluginVersionResolver;
@Requirement
private BuildPluginManager pluginManager;
@Requirement
private PluginPrefixResolver pluginPrefixResolver;
@SuppressWarnings({"UnusedDeclaration"})
public MojoDescriptorCreator()
{
}
public MojoDescriptorCreator( PluginVersionResolver pluginVersionResolver, BuildPluginManager pluginManager,
PluginPrefixResolver pluginPrefixResolver )
{
this.pluginVersionResolver = pluginVersionResolver;
this.pluginManager = pluginManager;
this.pluginPrefixResolver = pluginPrefixResolver;
}
private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
{
for ( Plugin plugin : plugins )
{
if ( artifactId.equals( plugin.getArtifactId() ) && groupId.equals( plugin.getGroupId() ) )
{
return plugin;
}
}
return null;
}
public static Xpp3Dom convert( MojoDescriptor mojoDescriptor )
{
Xpp3Dom dom = new Xpp3Dom( "configuration" );
PlexusConfiguration c = mojoDescriptor.getMojoConfiguration();
PlexusConfiguration[] ces = c.getChildren();
if ( ces != null )
{
for ( PlexusConfiguration ce : ces )
{
String value = ce.getValue( null );
String defaultValue = ce.getAttribute( "default-value", null );
if ( value != null || defaultValue != null )
{
Xpp3Dom e = new Xpp3Dom( ce.getName() );
e.setValue( value );
if ( defaultValue != null )
{
e.setAttribute( "default-value", defaultValue );
}
dom.addChild( e );
}
}
}
return dom;
}
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
public MojoDescriptor getMojoDescriptor( String task, MavenSession session, MavenProject project )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException
{
String goal = null;
Plugin plugin = null;
StringTokenizer tok = new StringTokenizer( task, ":" );
int numTokens = tok.countTokens();
if ( numTokens == 4 )
{
// We have everything that we need
//
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
//
// groupId
// artifactId
// version
// goal
//
plugin = new Plugin();
plugin.setGroupId( tok.nextToken() );
plugin.setArtifactId( tok.nextToken() );
plugin.setVersion( tok.nextToken() );
goal = tok.nextToken();
}
else if ( numTokens == 3 )
{
// We have everything that we need except the version
//
// org.apache.maven.plugins:maven-remote-resources-plugin:???:process
//
// groupId
// artifactId
// ???
// goal
//
plugin = new Plugin();
plugin.setGroupId( tok.nextToken() );
plugin.setArtifactId( tok.nextToken() );
goal = tok.nextToken();
}
else if ( numTokens == 2 )
{
// We have a prefix and goal
//
// idea:idea
//
String prefix = tok.nextToken();
goal = tok.nextToken();
// This is the case where someone has executed a single goal from the command line
// of the form:
//
// mvn remote-resources:process
//
// From the metadata stored on the server which has been created as part of a standard
// Maven plugin deployment we will find the right PluginDescriptor from the remote
// repository.
plugin = findPluginForPrefix( prefix, session );
}
injectPluginDeclarationFromProject( plugin, project );
RepositoryRequest repositoryRequest = DefaultRepositoryRequest.getRepositoryRequest( session, project );
// If there is no version to be found then we need to look in the repository metadata for
// this plugin and see what's specified as the latest release.
//
if ( plugin.getVersion() == null )
{
resolvePluginVersion( plugin, repositoryRequest );
}
return pluginManager.getMojoDescriptor( plugin, goal, repositoryRequest );
}
//TODO: take repo mans into account as one may be aggregating prefixes of many
//TODO: collect at the root of the repository, read the one at the root, and fetch remote if something is missing
// or the user forces the issue
public Plugin findPluginForPrefix( String prefix, MavenSession session )
throws NoPluginFoundForPrefixException
{
// [prefix]:[goal]
PluginPrefixRequest prefixRequest = new DefaultPluginPrefixRequest( prefix, session );
PluginPrefixResult prefixResult = pluginPrefixResolver.resolve( prefixRequest );
Plugin plugin = new Plugin();
plugin.setGroupId( prefixResult.getGroupId() );
plugin.setArtifactId( prefixResult.getArtifactId() );
return plugin;
}
private void resolvePluginVersion( Plugin plugin, RepositoryRequest repositoryRequest )
throws PluginVersionResolutionException
{
PluginVersionRequest versionRequest = new DefaultPluginVersionRequest( plugin, repositoryRequest );
plugin.setVersion( pluginVersionResolver.resolve( versionRequest ).getVersion() );
}
private void injectPluginDeclarationFromProject( Plugin plugin, MavenProject project )
{
Plugin pluginInPom = findPlugin( plugin, project.getBuildPlugins() );
if ( pluginInPom == null && project.getPluginManagement() != null )
{
pluginInPom = findPlugin( plugin, project.getPluginManagement().getPlugins() );
}
if ( pluginInPom != null )
{
if ( plugin.getVersion() == null )
{
plugin.setVersion( pluginInPom.getVersion() );
}
plugin.setDependencies( new ArrayList<Dependency>( pluginInPom.getDependencies() ) );
}
}
private Plugin findPlugin( Plugin plugin, Collection<Plugin> plugins )
{
return findPlugin( plugin.getGroupId(), plugin.getArtifactId(), plugins );
}
}

View File

@ -0,0 +1,258 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.DefaultLifecycleExecutor;
import org.apache.maven.lifecycle.LifecycleEventCatapult;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.MissingProjectException;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Executes an individual mojo
*
* @author Jason van Zyl
* @author Benjamin Bentmann
* @author Kristian Rosenvold
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
@Component(role = MojoExecutor.class)
public class MojoExecutor
{
@Requirement
private BuildPluginManager pluginManager;
@Requirement
private LifecycleDependencyResolver lifeCycleDependencyResolver;
public MojoExecutor()
{
}
public void execute( MavenSession session, List<MojoExecution> mojoExecutions, ProjectIndex projectIndex,
DependencyContext dependencyContext )
throws LifecycleExecutionException
{
PhaseRecorder phaseRecorder = new PhaseRecorder( session.getCurrentProject() );
for ( MojoExecution mojoExecution : mojoExecutions )
{
execute( session, mojoExecution, projectIndex, dependencyContext, phaseRecorder );
}
}
public void execute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
DependencyContext dependencyContext, PhaseRecorder phaseRecorder )
throws LifecycleExecutionException
{
execute( session, mojoExecution, projectIndex, dependencyContext );
phaseRecorder.observeExecution( mojoExecution );
}
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
private void execute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
DependencyContext dependencyContext )
throws LifecycleExecutionException
{
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( mojoDescriptor.isProjectRequired() && !session.isUsingPOMsFromFilesystem() )
{
Throwable cause = new MissingProjectException(
"Goal requires a project to execute" + " but there is no POM in this directory (" +
session.getExecutionRootDirectory() + ")." +
" Please verify you invoked Maven from the correct directory." );
throw new LifecycleExecutionException( mojoExecution, null, cause );
}
if ( mojoDescriptor.isOnlineRequired() && session.isOffline() )
{
if ( MojoExecution.Source.CLI.equals( mojoExecution.getSource() ) )
{
Throwable cause = new IllegalStateException(
"Goal requires online mode for execution" + " but Maven is currently offline." );
throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), cause );
}
else
{
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.MOJO_SKIPPED );
return;
}
}
lifeCycleDependencyResolver.checkForUpdate( session, dependencyContext );
List<MavenProject> forkedProjects =
executeForkedExecutions( mojoExecution, session, projectIndex, dependencyContext );
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.MOJO_STARTED );
ArtifactFilter artifactFilter = getArtifactFilter( mojoDescriptor );
List<MavenProject> resolvedProjects =
LifecycleDependencyResolver.getProjects( session.getCurrentProject(), session,
mojoDescriptor.isAggregator() );
for ( MavenProject project : resolvedProjects )
{
project.setArtifactFilter( artifactFilter );
}
try
{
try
{
pluginManager.executeMojo( session, mojoExecution );
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.MOJO_SUCCEEDED );
}
catch ( MojoFailureException e )
{
throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
}
catch ( MojoExecutionException e )
{
throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
}
catch ( PluginConfigurationException e )
{
throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
}
catch ( PluginManagerException e )
{
throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
}
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.MOJO_SUCCEEDED );
}
catch ( LifecycleExecutionException e )
{
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.MOJO_FAILED );
throw e;
}
finally
{
for ( MavenProject forkedProject : forkedProjects )
{
forkedProject.setExecutionProject( null );
}
}
}
private ArtifactFilter getArtifactFilter( MojoDescriptor mojoDescriptor )
{
String scopeToResolve = mojoDescriptor.getDependencyResolutionRequired();
String scopeToCollect = mojoDescriptor.getDependencyCollectionRequired();
List<String> scopes = new ArrayList<String>( 2 );
if ( StringUtils.isNotEmpty( scopeToCollect ) )
{
scopes.add( scopeToCollect );
}
if ( StringUtils.isNotEmpty( scopeToResolve ) )
{
scopes.add( scopeToResolve );
}
if ( scopes.isEmpty() )
{
return null;
}
else
{
return new CumulativeScopeArtifactFilter( scopes );
}
}
private List<MavenProject> executeForkedExecutions( MojoExecution mojoExecution, MavenSession session,
ProjectIndex projectIndex, DependencyContext dependencyContext )
throws LifecycleExecutionException
{
List<MavenProject> forkedProjects = Collections.emptyList();
Map<String, List<MojoExecution>> forkedExecutions = mojoExecution.getForkedExecutions();
if ( !forkedExecutions.isEmpty() )
{
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.FORK_STARTED );
MavenProject project = session.getCurrentProject();
forkedProjects = new ArrayList<MavenProject>( forkedExecutions.size() );
dependencyContext = dependencyContext.clone();
try
{
for ( Map.Entry<String, List<MojoExecution>> fork : forkedExecutions.entrySet() )
{
int index = projectIndex.getIndices().get( fork.getKey() );
MavenProject forkedProject = projectIndex.getProjects().get( fork.getKey() );
forkedProjects.add( forkedProject );
MavenProject executedProject = forkedProject.clone();
forkedProject.setExecutionProject( executedProject );
try
{
session.setCurrentProject( executedProject );
session.getProjects().set( index, executedProject );
projectIndex.getProjects().put( fork.getKey(), executedProject );
execute( session, fork.getValue(), projectIndex, dependencyContext );
}
finally
{
projectIndex.getProjects().put( fork.getKey(), forkedProject );
session.getProjects().set( index, forkedProject );
session.setCurrentProject( project );
}
}
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.FORK_SUCCEEDED );
}
catch ( LifecycleExecutionException e )
{
DefaultLifecycleExecutor.fireEvent( session, mojoExecution, LifecycleEventCatapult.FORK_FAILED );
throw e;
}
}
return forkedProjects;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
/**
* @author Benjamin Bentmann
* @author Kristian Rosenvold (extrace class)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public class PhaseRecorder
{
private String lastLifecyclePhase;
private final MavenProject project;
public PhaseRecorder( MavenProject project )
{
this.project = project;
}
public void observeExecution( MojoExecution mojoExecution )
{
String lifecyclePhase = mojoExecution.getLifecyclePhase();
if ( lifecyclePhase != null )
{
if ( lastLifecyclePhase == null )
{
lastLifecyclePhase = lifecyclePhase;
}
else if ( !lifecyclePhase.equals( lastLifecyclePhase ) )
{
project.addLifecyclePhase( lastLifecyclePhase );
lastLifecyclePhase = lifecyclePhase;
}
}
if ( lastLifecyclePhase != null )
{
project.addLifecyclePhase( lastLifecyclePhase );
}
}
}

View File

@ -0,0 +1,131 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import java.util.*;
/**
* A list of project segments, ordered so that all ProjectSegments from first TaskSegment come before any
* subsequent TaskSegments.
*
* @author Kristian Rosenvold
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public class ProjectBuildList
implements Iterable<ProjectSegment>
{
private final List<ProjectSegment> items;
public ProjectBuildList( List<ProjectSegment> items )
{
this.items = Collections.unmodifiableList( items );
}
// TODO: Optimize; or maybe just rewrite the whole way aggregating mojos are being run.
/**
* Returns aProjectBuildList that contains only items for the specified taskSegment
* @param taskSegment the requested tasksegment
* @return a project build list for the supplied task segment
*/
public ProjectBuildList getByTaskSegment(TaskSegment taskSegment)
{
List<ProjectSegment> currentSegment = new ArrayList<ProjectSegment>();
for ( ProjectSegment projectBuild : items )
{
if ( taskSegment == projectBuild.getTaskSegment()){ // NOTE: There's no notion of taskSegment equality.
currentSegment.add( projectBuild );
}
}
return new ProjectBuildList( currentSegment );
}
public Map<MavenProject, ProjectSegment> selectSegment(TaskSegment taskSegment)
{
Map<MavenProject, ProjectSegment> result = new HashMap<MavenProject, ProjectSegment>( );
for ( ProjectSegment projectBuild : items )
{
if ( taskSegment == projectBuild.getTaskSegment()){ // NOTE: There's no notion of taskSegment equality.
result.put( projectBuild.getProject(), projectBuild );
}
}
return result;
}
/**
* Finds the first ProjectSegment matching the supplied project
* @param mavenProject the requested project
* @return The projectSegment or null.
*/
public ProjectSegment findByMavenProject(MavenProject mavenProject)
{
for ( ProjectSegment projectBuild : items )
{
if ( mavenProject.equals( projectBuild.getProject() )){
return projectBuild;
}
}
return null;
}
public Iterator<ProjectSegment> iterator()
{
return items.iterator();
}
public void closeAll()
{
for ( ProjectSegment item : items )
{
MavenSession sessionForThisModule = item.getSession();
sessionForThisModule.setCurrentProject( null );
}
}
public int size()
{
return items.size();
}
ProjectSegment get( int index )
{
return items.get( index );
}
public Set<String> getReactorProjectKeys()
{
Set<String> projectKeys = new HashSet<String>( items.size() * 2 );
for ( ProjectSegment projectBuild : items )
{
MavenProject project = projectBuild.getProject();
String key = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
projectKeys.add( key );
}
return projectKeys;
}
public boolean isEmpty()
{
return items.isEmpty();
}
}

View File

@ -0,0 +1,63 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.project.MavenProject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Provides the positional index of the project
*
* @author Benjamin Bentmann
* @author Kristian Rosenvold (extracted class only)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
// Todo: Kristian wonders if this class really is necessary and if it overlaps other concepts.
public final class ProjectIndex
{
private final Map<String, MavenProject> projects;
private final Map<String, Integer> indices;
public ProjectIndex( List<MavenProject> projects )
{
this.projects = new HashMap<String, MavenProject>( projects.size() * 2 );
this.indices = new HashMap<String, Integer>( projects.size() * 2 );
for ( int i = 0; i < projects.size(); i++ )
{
MavenProject project = projects.get( i );
String key = BuilderCommon.getKey( project );
this.getProjects().put( key, project );
this.getIndices().put( key, i );
}
}
public Map<String, MavenProject> getProjects()
{
return projects;
}
public Map<String, Integer> getIndices()
{
return indices;
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.project.MavenProject;
import java.util.List;
/**
* A build context that matches a mavenproject to a given tasksegment, and the session to be used.
* <p/>
* A note to the reader;
* <p/>
* There are several issues/discussions regarding how "aggregator" plugins should be handled.
* Read for instance http://docs.codehaus.org/display/MAVEN/Deterministic+Lifecycle+Planning
* <p/>
* In their current implementation they are "bolted" onto the lifecycle by separating them
* into TaskSegments. This class represents the execution context of one such task segment.
* <p/>
* Wise voices have suggested that maybe aggregators shouldn't be bound to the ordinary
* lifecycle at all, in which case we wouldn't be needing this class at all ( and
* ProjectBuildList.getByTaskSegments). Or maybe they should be introduced in the calculation
* of the execution plan instead, which seems much nicer.
* <p/>
* Additionally this class contains a clone of the MavenSession, which is *only* needed
* because it has as notion of a "current" project.
*
* @author Jason van Zyl
* @author Benjamin Bentmann
* @author Kristian Rosenvold
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public final class ProjectSegment
{
private final MavenProject project;
private final TaskSegment taskSegment;
private final MavenSession session;
public ProjectSegment( MavenProject project, TaskSegment taskSegment, MavenSession copiedSession )
{
this.project = project;
this.taskSegment = taskSegment;
this.session = copiedSession;
}
public MavenSession getSession()
{
return session;
}
public MavenProject getProject()
{
return project;
}
public TaskSegment getTaskSegment()
{
return taskSegment;
}
public List<MavenProject> getImmediateUpstreamProjects()
{
final ProjectDependencyGraph dependencyGraph = getSession().getProjectDependencyGraph();
return dependencyGraph.getUpstreamProjects( getProject(), false );
}
@Override
public String toString()
{
return getProject().getId() + " -> " + getTaskSegment();
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.project.MavenProject;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
/**
* Contains status information that is global to an entire reactor build.
*
* @author <a href="mailto:kristian.rosenvold@gmail.com">Kristian Rosenvold</a>
*/
public class ReactorBuildStatus
{
private final ProjectDependencyGraph projectDependencyGraph;
private final Collection<String> blackListedProjects = Collections.synchronizedSet( new HashSet<String>() );
private volatile boolean halted = false;
public ReactorBuildStatus( ProjectDependencyGraph projectDependencyGraph )
{
this.projectDependencyGraph = projectDependencyGraph;
}
public boolean isBlackListed( MavenProject project )
{
return blackListedProjects.contains( BuilderCommon.getKey( project ) );
}
public void blackList( MavenProject project )
{
if ( blackListedProjects.add( BuilderCommon.getKey( project ) ) && projectDependencyGraph != null )
{
for ( MavenProject downstreamProject : projectDependencyGraph.getDownstreamProjects( project, true ) )
{
blackListedProjects.add( BuilderCommon.getKey( downstreamProject ) );
}
}
}
public void halt()
{
halted = true;
}
public boolean isHalted()
{
return halted;
}
public boolean isHaltedOrBlacklisted( MavenProject mavenProject )
{
return isBlackListed( mavenProject ) || isHalted();
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenExecutionResult;
/**
* Context that is fixed for the entire reactor build.
*
* @author Jason van Zyl
* @author Kristian Rosenvold
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public class ReactorContext
{
private final MavenExecutionResult result;
private final ProjectIndex projectIndex;
private final ClassLoader originalContextClassLoader;
private final ReactorBuildStatus reactorBuildStatus;
public ReactorContext( MavenExecutionResult result, ProjectIndex projectIndex,
ClassLoader originalContextClassLoader, ReactorBuildStatus reactorBuildStatus )
{
this.result = result;
this.projectIndex = projectIndex;
this.originalContextClassLoader = originalContextClassLoader;
this.reactorBuildStatus = reactorBuildStatus;
}
public ReactorBuildStatus getReactorBuildStatus()
{
return reactorBuildStatus;
}
public MavenExecutionResult getResult()
{
return result;
}
public ProjectIndex getProjectIndex()
{
return projectIndex;
}
public ClassLoader getOriginalContextClassLoader()
{
return originalContextClassLoader;
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Describes the required task segment as provided on the maven command line; i.e. "clean jetty:run install"
*
* @author Benjamin Bentmann
* @author Kristian Rosenvold (extracted class only)
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
*/
public final class TaskSegment
{
// Can be both "LifeCycleTask" (clean/install) and "GoalTask" (org.mortbay.jetty:maven-jetty-plugin:6.1.19:run)
private final List<Object> tasks;
private final boolean aggregating;
public TaskSegment( boolean aggregating )
{
this.aggregating = aggregating;
tasks = new ArrayList<Object>();
}
public TaskSegment( boolean aggregating, Object... tasks )
{
this.aggregating = aggregating;
this.tasks = new ArrayList<Object>( Arrays.asList( tasks ) );
}
@Override
public String toString()
{
return getTasks().toString();
}
public List<Object> getTasks()
{
return tasks;
}
public boolean isAggregating()
{
return aggregating;
}
// TODO: Consider throwing UnsupprtedSomething on hashCode/equals
}

View File

@ -0,0 +1,90 @@
package org.apache.maven.lifecycle.internal;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component(role = ThreadConfigurationService.class)
public class ThreadConfigurationService
{
@Requirement
private Logger logger;
private final int cpuCores;
@SuppressWarnings({"UnusedDeclaration"})
public ThreadConfigurationService()
{
cpuCores = Runtime.getRuntime().availableProcessors();
}
public ThreadConfigurationService( Logger logger, int cpuCores )
{
this.logger = logger;
this.cpuCores = cpuCores;
}
public ExecutorService getExecutorService( String threadCountConfiguration, boolean perCoreThreadCount,
int largestBuildListSize )
{
Integer threadCount = getThreadCount( threadCountConfiguration, perCoreThreadCount, largestBuildListSize );
return getExecutorService( threadCount );
}
private ExecutorService getExecutorService( Integer threadCount )
{
if ( threadCount == null )
{
logger.info( "Building with unlimited threads" );
return Executors.newCachedThreadPool();
}
logger.info( "Building with " + threadCount + " threads" );
return Executors.newFixedThreadPool( threadCount );
}
/**
* Returns the thread count to use or null for unlimited threads.
*
* @param threadCountConfiguration The property passed from the command line.
* @param perCoreThreadCount Indicates if the threa count should be scaled per cpu core.
* @param largestBuildListSize the size of the largest module list (the number of modules)
* @return The number of threads to use or null if unlimited
*/
Integer getThreadCount( String threadCountConfiguration, boolean perCoreThreadCount, int largestBuildListSize )
{
// Default to a value that is not larger than what we can use ;)
float threadCount = Math.min( cpuCores, largestBuildListSize );
if ( threadCountConfiguration != null )
{
try
{
threadCount = Float.parseFloat( threadCountConfiguration );
}
catch ( NumberFormatException e )
{
logger.warn(
"Couldn't parse thread count, will default to " + threadCount + ": " + threadCountConfiguration );
}
}
if ( perCoreThreadCount )
{
threadCount = threadCount * cpuCores;
}
final int endResult = Math.round( threadCount );
if ( logger.isDebugEnabled() )
{
logger.debug( "Thread pool size: " + endResult );
}
return endResult;
}
}

View File

@ -0,0 +1,467 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author Kristian Rosenvold
* <p/>
* NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
* This class in particular may spontaneusly self-combust and be replaced by a plexus-compliant thread aware
* logger implementation at any time.
*/
@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})
public class ThreadOutputMuxer
{
private final Iterator<ProjectSegment> projects;
private final ThreadLocal<ProjectSegment> projectBuildThreadLocal = new ThreadLocal<ProjectSegment>();
private final Map<ProjectSegment, ByteArrayOutputStream> streams = new HashMap<ProjectSegment, ByteArrayOutputStream>();
private final Map<ProjectSegment, PrintStream> printStreams = new HashMap<ProjectSegment, PrintStream>();
private final ByteArrayOutputStream defaultOutputStreamForUnknownData = new ByteArrayOutputStream();
private final PrintStream defaultPringStream = new PrintStream( defaultOutputStreamForUnknownData );
private final Set<ProjectSegment> completedBuilds = Collections.synchronizedSet( new HashSet<ProjectSegment>() );
private volatile ProjectSegment currentBuild;
private final PrintStream originalSystemOUtStream;
private final ConsolePrinter printer;
/**
* A simple but safe solution for printing to the console.
*/
class ConsolePrinter
implements Runnable
{
public volatile boolean running;
private final ProjectBuildList projectBuildList;
ConsolePrinter( ProjectBuildList projectBuildList )
{
this.projectBuildList = projectBuildList;
}
public void run()
{
running = true;
for ( ProjectSegment projectBuild : projectBuildList )
{
final PrintStream projectStream = printStreams.get( projectBuild );
ByteArrayOutputStream projectOs = streams.get( projectBuild );
do
{
synchronized ( projectStream )
{
try
{
projectStream.wait( 100 );
}
catch ( InterruptedException e )
{
throw new RuntimeException( e );
}
try
{
projectOs.writeTo( originalSystemOUtStream );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
projectOs.reset();
}
}
while ( !completedBuilds.contains( projectBuild ) );
}
running = false;
}
/*
Wait until we are sure the print-stream thread is running.
*/
public void waitUntilRunning( boolean expect )
{
while ( !running == expect )
{
try
{
Thread.sleep( 10 );
}
catch ( InterruptedException e )
{
throw new RuntimeException( e );
}
}
}
}
public ThreadOutputMuxer( ProjectBuildList segmentChunks, PrintStream originalSystemOut )
{
projects = segmentChunks.iterator();
for ( ProjectSegment segmentChunk : segmentChunks )
{
final ByteArrayOutputStream value = new ByteArrayOutputStream();
streams.put( segmentChunk, value );
printStreams.put( segmentChunk, new PrintStream( value ) );
}
setNext();
this.originalSystemOUtStream = originalSystemOut;
System.setOut( new ThreadBoundPrintStream( this.originalSystemOUtStream ) );
printer = new ConsolePrinter( segmentChunks );
new Thread( printer ).start();
printer.waitUntilRunning( true );
}
public void close()
{
printer.waitUntilRunning( false );
System.setOut( this.originalSystemOUtStream );
}
private void setNext()
{
currentBuild = projects.hasNext() ? projects.next() : null;
}
private boolean ownsRealOutputStream( ProjectSegment projectBuild )
{
return projectBuild.equals( currentBuild );
}
private PrintStream getThreadBoundPrintStream()
{
ProjectSegment threadProject = projectBuildThreadLocal.get();
if ( threadProject == null )
{
return defaultPringStream;
}
if ( ownsRealOutputStream( threadProject ) )
{
return originalSystemOUtStream;
}
return printStreams.get( threadProject );
}
public void associateThreadWithProjectSegment( ProjectSegment projectBuild )
{
projectBuildThreadLocal.set( projectBuild );
}
public void setThisModuleComplete( ProjectSegment projectBuild )
{
completedBuilds.add( projectBuild );
PrintStream stream = printStreams.get( projectBuild );
synchronized ( stream )
{
stream.notifyAll();
}
disconnectThreadFromProject();
}
private void disconnectThreadFromProject()
{
projectBuildThreadLocal.remove();
}
private class ThreadBoundPrintStream
extends PrintStream
{
public ThreadBoundPrintStream( PrintStream systemOutStream )
{
super( systemOutStream );
}
private PrintStream getOutputStreamForCurrentThread()
{
return getThreadBoundPrintStream();
}
@Override
public void println()
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println();
currentStream.notifyAll();
}
}
@Override
public void print( char c )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( c );
currentStream.notifyAll();
}
}
@Override
public void println( char x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println( x );
currentStream.notifyAll();
}
}
@Override
public void print( double d )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( d );
currentStream.notifyAll();
}
}
@Override
public void println( double x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println( x );
currentStream.notifyAll();
}
}
@Override
public void print( float f )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( f );
currentStream.notifyAll();
}
}
@Override
public void println( float x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println( x );
currentStream.notifyAll();
}
}
@Override
public void print( int i )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( i );
currentStream.notifyAll();
}
}
@Override
public void println( int x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println( x );
currentStream.notifyAll();
}
}
@Override
public void print( long l )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( l );
currentStream.notifyAll();
}
}
@Override
public void println( long x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( x );
currentStream.notifyAll();
}
}
@Override
public void print( boolean b )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( b );
currentStream.notifyAll();
}
}
@Override
public void println( boolean x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( x );
currentStream.notifyAll();
}
}
@Override
public void print( char s[] )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( s );
currentStream.notifyAll();
}
}
@Override
public void println( char x[] )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( x );
currentStream.notifyAll();
}
}
@Override
public void print( Object obj )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( obj );
currentStream.notifyAll();
}
}
@Override
public void println( Object x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println( x );
currentStream.notifyAll();
}
}
@Override
public void print( String s )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.print( s );
currentStream.notifyAll();
}
}
@Override
public void println( String x )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.println( x );
currentStream.notifyAll();
}
}
@Override
public void write( byte b[], int off, int len )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.write( b, off, len );
currentStream.notifyAll();
}
}
@Override
public void close()
{
getOutputStreamForCurrentThread().close();
}
@Override
public void flush()
{
getOutputStreamForCurrentThread().flush();
}
@Override
public void write( int b )
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.write( b );
currentStream.notifyAll();
}
}
@Override
public void write( byte b[] )
throws IOException
{
final PrintStream currentStream = getOutputStreamForCurrentThread();
synchronized ( currentStream )
{
currentStream.write( b );
currentStream.notifyAll();
}
}
}
}

View File

@ -475,7 +475,7 @@ else if ( cause instanceof LinkageError )
}
}
private void populatePluginFields( Object mojo, MojoDescriptor mojoDescriptor, ClassRealm pluginRealm,
private synchronized void populatePluginFields( Object mojo, MojoDescriptor mojoDescriptor, ClassRealm pluginRealm,
PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator )
throws PluginConfigurationException
{

View File

@ -85,23 +85,6 @@ public class DefaultPluginManager
@Requirement
private LegacySupport legacySupport;
private RepositoryRequest getRepositoryRequest( MavenSession session, MavenProject project )
{
RepositoryRequest request = new DefaultRepositoryRequest();
request.setCache( session.getRepositoryCache() );
request.setLocalRepository( session.getLocalRepository() );
if ( project != null )
{
request.setRemoteRepositories( project.getPluginArtifactRepositories() );
}
request.setOffline( session.isOffline() );
request.setForceUpdate( session.getRequest().isUpdateSnapshots() );
request.setTransferListener( session.getRequest().getTransferListener() );
return request;
}
public void executeMojo( MavenProject project, MojoExecution execution, MavenSession session )
throws MojoExecutionException, ArtifactResolutionException, MojoFailureException, ArtifactNotFoundException,
InvalidDependencyVersionException, PluginManagerException, PluginConfigurationException
@ -117,7 +100,7 @@ public Object getPluginComponent( Plugin plugin, String role, String roleHint )
PluginDescriptor pluginDescriptor;
try
{
RepositoryRequest repositoryRequest = getRepositoryRequest( session, session.getCurrentProject() );
RepositoryRequest repositoryRequest = DefaultRepositoryRequest.getRepositoryRequest( session, session.getCurrentProject() );
pluginDescriptor = pluginManager.getPluginDescriptor( plugin, repositoryRequest );
@ -149,7 +132,7 @@ public Map getPluginComponents( Plugin plugin, String role )
PluginDescriptor pluginDescriptor;
try
{
RepositoryRequest repositoryRequest = getRepositoryRequest( session, session.getCurrentProject() );
RepositoryRequest repositoryRequest = DefaultRepositoryRequest.getRepositoryRequest( session, session.getCurrentProject() );
pluginDescriptor = pluginManager.getPluginDescriptor( plugin, repositoryRequest );

View File

@ -17,103 +17,146 @@
-->
<component-set>
<components>
<component>
<role>org.apache.maven.plugin.MavenPluginCollector</role>
<implementation>org.apache.maven.plugin.MavenPluginCollector
</implementation>
</component>
<component>
<role>org.apache.maven.lifecycle.LifecycleExecutor</role>
<implementation>org.apache.maven.lifecycle.DefaultLifecycleExecutor
</implementation>
<requirements>
<requirement>
<role>org.codehaus.plexus.logging.Logger</role>
<role-hint>default</role-hint>
<field-name>logger</field-name>
</requirement>
<requirement>
<role>org.apache.maven.plugin.BuildPluginManager</role>
</requirement>
<requirement>
<role>org.apache.maven.ProjectDependenciesResolver</role>
</requirement>
<requirement>
<role>org.apache.maven.repository.RepositorySystem</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<field-name>lifecycleMappings</field-name>
</requirement>
<requirement>
<role>org.apache.maven.plugin.version.PluginVersionResolver</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.prefix.PluginPrefixResolver</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>
</configuration>
</component>
<component>
<role>org.apache.maven.plugin.MavenPluginCollector</role>
<implementation>org.apache.maven.plugin.MavenPluginCollector
</implementation>
</component>
<!-- component>
<role>org.apache.maven.lifecycle.LifecycleExecutor</role>
<implementation>org.apache.maven.lifecycle.DefaultLifecycleExecutor
</implementation>
<requirements>
<requirement>
<role>org.apache.maven.lifecycle.LifeCyclePluginAnalyzer</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.DefaultLifecycles</role>
</requirement>
<requirement>
<role>org.codehaus.plexus.logging.Logger</role>
<role-hint>default</role-hint>
<field-name>logger</field-name>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.internal.LifecycleModuleBuilder</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.internal.LifecycleWeaveBuilder</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.internal.BuildListCalculator</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.internal.LifecycleDebugLogger</role>
</requirement>
</requirements>
</component -->
<component>
<role>org.apache.maven.lifecycle.DefaultLifecycles</role>
<implementation>org.apache.maven.lifecycle.DefaultLifecycles</implementation>
<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>
<schedules>
<scheduling>
<lifecycle>default</lifecycle>
<schedules>
<schedule>
<phase>test</phase>
<mojoSynchronized>false</mojoSynchronized>
<parallel>true</parallel>
</schedule>
<schedule>
<mojoClass>org.apache.maven.plugins:maven-assembly-plugin</mojoClass>
<mojoSynchronized>true</mojoSynchronized>
</schedule>
<!--schedule>
<mojoClass>org.codehaus.modello:modello-maven-plugin</mojoClass>
<mojoSynchronized>true</mojoSynchronized>
</schedule -->
</schedules>
</scheduling>
</schedules>
</configuration>
</component>
<component>
<role>org.apache.maven.lifecycle.LifeCyclePluginAnalyzer</role>
<implementation>org.apache.maven.lifecycle.internal.LifecyclePluginAnalyzerImpl</implementation>
<requirements>
<requirement>
<role>org.apache.maven.lifecycle.DefaultLifecycles</role>
</requirement>
<requirement>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<field-name>lifecycleMappings</field-name>
</requirement>
<requirement>
<role>org.codehaus.plexus.logging.Logger</role>
<role-hint>default</role-hint>
<field-name>logger</field-name>
</requirement>
</requirements>
</component>
<component>
<role>org.sonatype.plexus.components.sec.dispatcher.SecDispatcher

View File

@ -0,0 +1,76 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.component.annotations.Requirement;
import java.util.List;
/**
* @author Kristian Rosenvold
*/
public class DefaultLifecyclesTest
extends PlexusTestCase
{
@Requirement
private DefaultLifecycles defaultLifeCycles;
protected void setUp()
throws Exception
{
super.setUp();
defaultLifeCycles = lookup( DefaultLifecycles.class );
}
@Override
protected void tearDown()
throws Exception
{
defaultLifeCycles = null;
super.tearDown();
}
public void testLifecycle()
throws Exception
{
final List<Lifecycle> cycles = defaultLifeCycles.getLifeCycles();
assertNotNull( cycles );
final Lifecycle lifecycle = cycles.get( 0 );
assertEquals( "default", lifecycle.getId() );
assertEquals( 23, lifecycle.getPhases().size() );
}
public void testScheduling()
throws Exception
{
final List<Scheduling> schedulings = defaultLifeCycles.getSchedules();
assertNotNull( schedulings );
assertTrue( schedulings.size() > 0 );
Scheduling first = schedulings.get( 0 );
assertNotNull( first.getLifecycle() );
final List<Schedule> schedules = first.getSchedules();
assertNotNull( schedules );
// Ok so if we ever change the first schedule this test will have to change
Schedule firstSchedule = schedules.get( 0 );
assertEquals( "test", firstSchedule.getPhase() );
assertTrue( "Should be parllel", firstSchedule.isParallel() );
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import org.apache.maven.AbstractCoreMavenComponentTestCase;
import org.apache.maven.exception.ExceptionHandler;
import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver;
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.LifecycleModuleBuilder;
import org.apache.maven.lifecycle.internal.LifecyclePluginAnalyzerImpl;
import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.MojoExecutor;
import org.codehaus.plexus.component.annotations.Requirement;
/**
* Just asserts that it's able to create those components. Handy when plexus gets a nervous breakdown.
*
* @author Kristian Rosenvold
*/
public class LifecycleExecutorSubModulesTest
extends AbstractCoreMavenComponentTestCase
{
@Requirement
private DefaultLifecycles defaultLifeCycles;
@Requirement
private MojoExecutor mojoExecutor;
@Requirement
private LifecycleModuleBuilder lifeCycleBuilder;
@Requirement
private LifecycleDependencyResolver lifeCycleDependencyResolver;
@Requirement
private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
@Requirement
private LifeCyclePluginAnalyzer lifeCyclePluginAnalyzer;
@Requirement
private LifecycleTaskSegmentCalculator lifeCycleTaskSegmentCalculator;
protected void setUp()
throws Exception
{
super.setUp();
defaultLifeCycles = lookup( DefaultLifecycles.class );
mojoExecutor = lookup( MojoExecutor.class );
lifeCycleBuilder = lookup( LifecycleModuleBuilder.class );
lifeCycleDependencyResolver = lookup( LifecycleDependencyResolver.class );
lifeCycleExecutionPlanCalculator = lookup( LifecycleExecutionPlanCalculator.class );
lifeCyclePluginAnalyzer = lookup( LifecyclePluginAnalyzerImpl.class );
lifeCycleTaskSegmentCalculator = lookup( LifecycleTaskSegmentCalculator.class );
lookup( ExceptionHandler.class );
}
@Override
protected void tearDown()
throws Exception
{
defaultLifeCycles = null;
super.tearDown();
}
protected String getProjectsDirectory()
{
return "src/test/projects/lifecycle-executor";
}
public void testCrweation()
throws Exception
{
assertNotNull( defaultLifeCycles );
assertNotNull( mojoExecutor );
assertNotNull( lifeCycleBuilder );
assertNotNull( lifeCycleDependencyResolver );
assertNotNull( lifeCycleExecutionPlanCalculator );
assertNotNull( lifeCyclePluginAnalyzer );
assertNotNull( lifeCycleTaskSegmentCalculator );
}
}

View File

@ -1,30 +1,74 @@
package org.apache.maven.lifecycle;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.List;
package org.apache.maven.lifecycle;
import org.apache.maven.AbstractCoreMavenComponentTestCase;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.exception.ExceptionHandler;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculatorImpl;
import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LifecycleExecutorTest
extends AbstractCoreMavenComponentTestCase
{
@Requirement
private DefaultLifecycleExecutor lifecycleExecutor;
@Requirement
private LifecycleTaskSegmentCalculatorImpl lifeCycleTaskSegmentCalculator;
@Requirement
private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
@Requirement
private MojoDescriptorCreator mojoDescriptorCreator;
protected void setUp()
throws Exception
{
super.setUp();
lifecycleExecutor = (DefaultLifecycleExecutor) lookup( LifecycleExecutor.class );
lifeCycleTaskSegmentCalculator =
(LifecycleTaskSegmentCalculatorImpl) lookup( LifecycleTaskSegmentCalculator.class );
lifeCycleExecutionPlanCalculator = lookup( LifecycleExecutionPlanCalculator.class );
mojoDescriptorCreator = lookup( MojoDescriptorCreator.class );
lookup( ExceptionHandler.class );
}
@ -40,11 +84,11 @@ protected String getProjectsDirectory()
{
return "src/test/projects/lifecycle-executor";
}
// -----------------------------------------------------------------------------------------------
// Tests which exercise the lifecycle executor when it is dealing with default lifecycle phases.
// -----------------------------------------------------------------------------------------------
public void testCalculationOfBuildPlanWithIndividualTaskWherePluginIsSpecifiedInThePom()
throws Exception
{
@ -54,12 +98,14 @@ public void testCalculationOfBuildPlanWithIndividualTaskWherePluginIsSpecifiedIn
MavenSession session = createMavenSession( pom );
assertEquals( "project-basic", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = lifecycleExecutor.calculateExecutionPlan( session, "resources:resources" ).getExecutions();
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "resources:resources" ) );
assertEquals( 1, executionPlan.size() );
MojoExecution mojoExecution = executionPlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins", mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-resources-plugin", mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "org.apache.maven.plugins",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-resources-plugin",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
@ -72,15 +118,16 @@ public void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanLifecycle()
MavenSession session = createMavenSession( pom );
assertEquals( "project-basic", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = lifecycleExecutor.calculateExecutionPlan( session, "clean" ).getExecutions();
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "clean" ) );
assertEquals( 1, executionPlan.size() );
MojoExecution mojoExecution = executionPlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins", mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "org.apache.maven.plugins",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-clean-plugin", mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
public void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanCleanGoal()
throws Exception
{
@ -90,15 +137,26 @@ public void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanCleanGoal()
MavenSession session = createMavenSession( pom );
assertEquals( "project-basic", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = lifecycleExecutor.calculateExecutionPlan( session, "clean:clean" ).getExecutions();
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "clean:clean" ) );
assertEquals( 1, executionPlan.size() );
MojoExecution mojoExecution = executionPlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins", mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "org.apache.maven.plugins",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-clean-plugin", mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
List<MojoExecution> getExecutions( MavenExecutionPlan mavenExecutionPlan )
{
List<MojoExecution> result = new ArrayList<MojoExecution>();
for ( ExecutionPlanItem executionPlanItem : mavenExecutionPlan )
{
result.add( executionPlanItem.getMojoExecution() );
}
return result;
}
// We need to take in multiple lifecycles
public void testCalculationOfBuildPlanTasksOfTheCleanLifecycleAndTheInstallLifecycle()
throws Exception
@ -107,8 +165,8 @@ public void testCalculationOfBuildPlanTasksOfTheCleanLifecycleAndTheInstallLifec
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-additional-lifecycle-elements", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = lifecycleExecutor.calculateExecutionPlan( session, "clean", "install" ).getExecutions();
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "clean", "install" ) );
//[01] clean:clean
//[02] resources:resources
//[03] compiler:compile
@ -121,7 +179,7 @@ public void testCalculationOfBuildPlanTasksOfTheCleanLifecycleAndTheInstallLifec
//[10] install:install
//
assertEquals( 10, executionPlan.size() );
assertEquals( "clean:clean", executionPlan.get( 0 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "resources:resources", executionPlan.get( 1 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:compile", executionPlan.get( 2 ).getMojoDescriptor().getFullGoalName() );
@ -130,8 +188,8 @@ public void testCalculationOfBuildPlanTasksOfTheCleanLifecycleAndTheInstallLifec
assertEquals( "compiler:testCompile", executionPlan.get( 5 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-test-metadata", executionPlan.get( 6 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "surefire:test", executionPlan.get( 7 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executionPlan.get( 8 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "install:install", executionPlan.get( 9 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executionPlan.get( 8 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "install:install", executionPlan.get( 9 ).getMojoDescriptor().getFullGoalName() );
}
// We need to take in multiple lifecycles
@ -142,15 +200,15 @@ public void testCalculationOfBuildPlanWithMultipleExecutionsOfModello()
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-multiple-executions", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0.1", session.getCurrentProject().getVersion() );
MavenExecutionPlan plan = lifecycleExecutor.calculateExecutionPlan( session, "clean", "install" );
MavenExecutionPlan plan = calculateExecutionPlan( session, "clean", "install" );
assertTrue( plan.getRequiredResolutionScopes().contains( Artifact.SCOPE_COMPILE ) );
assertTrue( plan.getRequiredResolutionScopes().contains( Artifact.SCOPE_RUNTIME ) );
assertTrue( plan.getRequiredResolutionScopes().contains( Artifact.SCOPE_TEST ) );
List<MojoExecution> executions = plan.getExecutions();
List<MojoExecution> executions = getExecutions( plan );
//[01] clean:clean
//[02] modello:xpp3-writer
//[03] modello:java
@ -168,9 +226,9 @@ public void testCalculationOfBuildPlanWithMultipleExecutionsOfModello()
//[15] plugin:addPluginArtifactMetadata
//[16] install:install
//
assertEquals( 16, executions.size() );
assertEquals( 16, executions.size() );
assertEquals( "clean:clean", executions.get( 0 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:xpp3-writer", executions.get( 1 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:java", executions.get( 2 ).getMojoDescriptor().getFullGoalName() );
@ -184,23 +242,27 @@ public void testCalculationOfBuildPlanWithMultipleExecutionsOfModello()
assertEquals( "resources:testResources", executions.get( 10 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:testCompile", executions.get( 11 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "surefire:test", executions.get( 12 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executions.get( 13 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "plugin:addPluginArtifactMetadata", executions.get( 14 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executions.get( 13 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "plugin:addPluginArtifactMetadata", executions.get( 14 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "install:install", executions.get( 15 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "src/main/mdo/remote-resources.mdo", new MojoExecutionXPathContainer( executions.get( 1 ) ).getValue( "configuration/models[1]/model" ) );
assertEquals( "src/main/mdo/supplemental-model.mdo", new MojoExecutionXPathContainer( executions.get( 4 ) ).getValue( "configuration/models[1]/model" ) );
}
assertEquals( "src/main/mdo/remote-resources.mdo",
new MojoExecutionXPathContainer( executions.get( 1 ) ).getValue(
"configuration/models[1]/model" ) );
assertEquals( "src/main/mdo/supplemental-model.mdo",
new MojoExecutionXPathContainer( executions.get( 4 ) ).getValue(
"configuration/models[1]/model" ) );
}
public void testLifecycleQueryingUsingADefaultLifecyclePhase()
throws Exception
{
{
File pom = getProject( "project-with-additional-lifecycle-elements" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-additional-lifecycle-elements", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = lifecycleExecutor.calculateExecutionPlan( session, "package" ).getExecutions();
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "package" ) );
//[01] resources:resources
//[02] compiler:compile
//[03] it:generate-metadata
@ -211,7 +273,7 @@ public void testLifecycleQueryingUsingADefaultLifecyclePhase()
//[08] jar:jar
//
assertEquals( 8, executionPlan.size() );
assertEquals( "resources:resources", executionPlan.get( 0 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:compile", executionPlan.get( 1 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-metadata", executionPlan.get( 2 ).getMojoDescriptor().getFullGoalName() );
@ -219,48 +281,74 @@ public void testLifecycleQueryingUsingADefaultLifecyclePhase()
assertEquals( "compiler:testCompile", executionPlan.get( 4 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-test-metadata", executionPlan.get( 5 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "surefire:test", executionPlan.get( 6 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executionPlan.get( 7 ).getMojoDescriptor().getFullGoalName() );
}
assertEquals( "jar:jar", executionPlan.get( 7 ).getMojoDescriptor().getFullGoalName() );
}
public void testLifecyclePluginsRetrievalForDefaultLifecycle()
throws Exception
{
List<Plugin> plugins = new ArrayList<Plugin>( lifecycleExecutor.getPluginsBoundByDefaultToAllLifecycles( "jar" ) );
List<Plugin> plugins =
new ArrayList<Plugin>( lifecycleExecutor.getPluginsBoundByDefaultToAllLifecycles( "jar" ) );
assertEquals( 8, plugins.size() );
}
public void testPluginConfigurationCreation()
throws Exception
{
File pom = getProject( "project-with-additional-lifecycle-elements" );
MavenSession session = createMavenSession( pom );
MojoDescriptor mojoDescriptor =
lifecycleExecutor.getMojoDescriptor( "org.apache.maven.its.plugins:maven-it-plugin:0.1:java",
session, session.getCurrentProject() );
Xpp3Dom dom = lifecycleExecutor.convert( mojoDescriptor );
mojoDescriptorCreator.getMojoDescriptor( "org.apache.maven.its.plugins:maven-it-plugin:0.1:java", session,
session.getCurrentProject() );
Xpp3Dom dom = MojoDescriptorCreator.convert( mojoDescriptor );
System.out.println( dom );
}
// Todo: This method is kind of an oddity. It is only called from the LifecycleExecutorTest, hence it should
// really not exist, or at least be moved into the test class.
MavenExecutionPlan calculateExecutionPlan( MavenSession session, String... tasks )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginManagerException, LifecyclePhaseNotFoundException, LifecycleNotFoundException,
PluginVersionResolutionException
{
List<org.apache.maven.lifecycle.internal.TaskSegment> taskSegments =
lifeCycleTaskSegmentCalculator.calculateTaskSegments( session, Arrays.asList( tasks ) );
org.apache.maven.lifecycle.internal.TaskSegment mergedSegment =
new org.apache.maven.lifecycle.internal.TaskSegment( false );
for ( org.apache.maven.lifecycle.internal.TaskSegment taskSegment : taskSegments )
{
mergedSegment.getTasks().addAll( taskSegment.getTasks() );
}
return lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, session.getCurrentProject(),
mergedSegment.getTasks() );
}
public void testPluginPrefixRetrieval()
throws Exception
{
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
Plugin plugin = lifecycleExecutor.findPluginForPrefix( "resources", session );
Plugin plugin = mojoDescriptorCreator.findPluginForPrefix( "resources", session );
assertEquals( "org.apache.maven.plugins", plugin.getGroupId() );
assertEquals( "maven-resources-plugin", plugin.getArtifactId() );
}
}
// Prefixes
public void testFindingPluginPrefixforCleanClean()
throws Exception
{
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
Plugin plugin = lifecycleExecutor.findPluginForPrefix( "clean", session );
Plugin plugin = mojoDescriptorCreator.findPluginForPrefix( "clean", session );
assertNotNull( plugin );
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.
*/
package org.apache.maven.lifecycle;
import junit.framework.TestCase;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.lifecycle.internal.stub.DefaultLifecyclesStub;
import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
import java.util.Iterator;
import java.util.List;
/**
* @author Kristian Rosenvold
*/
public class MavenExecutionPlanTest
extends TestCase
{
public void testFindFirstWithMatchingSchedule()
throws Exception
{
MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan();
final List<Scheduling> cycles = DefaultLifecyclesStub.getSchedulingList();
final Schedule schedule = cycles.get( 0 ).getSchedules().get( 0 );
}
public void testForceAllComplete()
throws Exception
{
MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan();
plan.forceAllComplete();
final Iterator<ExecutionPlanItem> planItemIterator = plan.iterator();
assertFalse( planItemIterator.next().ensureComplete() );
assertFalse( planItemIterator.next().ensureComplete() );
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.internal.stub.LifecycleTaskSegmentCalculatorStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
import java.util.List;
public class BuildListCalculatorTest
extends TestCase
{
public void testCalculateProjectBuilds()
throws Exception
{
BuildListCalculator buildListCalculator = createBuildListCalculator();
final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
List<TaskSegment> taskSegments = buildListCalculator.calculateTaskSegments( session );
final ProjectBuildList buildList = buildListCalculator.calculateProjectBuilds( session, taskSegments );
final ProjectBuildList segments = buildList.getByTaskSegment( taskSegments.get( 0 ) );
assertEquals( "Stub data contains 3 segments", 3, taskSegments.size() );
assertEquals( "Stub data contains 6 items", 6, segments.size() );
final ProjectSegment build = segments.get( 0 );
assertNotNull( build );
}
public static BuildListCalculator createBuildListCalculator()
{
LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator = new LifecycleTaskSegmentCalculatorStub();
return new BuildListCalculator( lifecycleTaskSegmentCalculator );
}
}

View File

@ -0,0 +1,72 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
import org.apache.maven.lifecycle.internal.stub.LoggerStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependenciesResolverStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
/**
* @author Kristian Rosenvold
*/
public class BuilderCommonTest
extends TestCase
{
public void testResolveBuildPlan()
throws Exception
{
MavenSession original = ProjectDependencyGraphStub.getMavenSession();
final TaskSegment taskSegment1 = new TaskSegment( false );
final MavenSession session1 = original.clone();
session1.setCurrentProject( ProjectDependencyGraphStub.A );
final BuilderCommon builderCommon = getBuilderCommon();
final MavenExecutionPlan plan =
builderCommon.resolveBuildPlan( session1, ProjectDependencyGraphStub.A, taskSegment1 );
assertEquals( LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan().size(), plan.size() );
}
public void testHandleBuildError()
throws Exception
{
}
public void testAttachToThread()
throws Exception
{
}
public void testGetKey()
throws Exception
{
}
public static BuilderCommon getBuilderCommon()
{
final LifecycleDebugLogger logger = new LifecycleDebugLogger( new LoggerStub() );
final LifecycleDependencyResolver lifecycleDependencyResolver =
new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), new LoggerStub() );
return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(), lifecycleDependencyResolver );
}
}

View File

@ -0,0 +1,92 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import java.util.List;
import static org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub.*;
/**
* @author Kristian Rosenvold
*/
public class ConcurrencyDependencyGraphTest
extends junit.framework.TestCase
{
public void testConcurrencyGraphPrimaryVersion()
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
ProjectDependencyGraph dependencyGraph = new ProjectDependencyGraphStub();
final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
ConcurrencyDependencyGraph graph =
new ConcurrencyDependencyGraph( getProjectBuildList( session ), dependencyGraph );
final List<MavenProject> projectBuilds = graph.getRootSchedulableBuilds();
assertEquals( 1, projectBuilds.size() );
assertEquals( A, projectBuilds.get( 0 ) );
final List<MavenProject> subsequent = graph.markAsFinished( A );
assertEquals( 2, subsequent.size() );
assertEquals( ProjectDependencyGraphStub.B, subsequent.get( 0 ) );
assertEquals( C, subsequent.get( 1 ) );
final List<MavenProject> bDescendants = graph.markAsFinished( B );
assertEquals( 1, bDescendants.size() );
assertEquals( Y, bDescendants.get( 0 ) );
final List<MavenProject> cDescendants = graph.markAsFinished( C );
assertEquals( 2, cDescendants.size() );
assertEquals( X, cDescendants.get( 0 ) );
assertEquals( Z, cDescendants.get( 1 ) );
}
public void testConcurrencyGraphDifferentCompletionOrder()
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
ProjectDependencyGraph dependencyGraph = new ProjectDependencyGraphStub();
final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
ConcurrencyDependencyGraph graph =
new ConcurrencyDependencyGraph( getProjectBuildList( session ), dependencyGraph );
graph.markAsFinished( A );
final List<MavenProject> cDescendants = graph.markAsFinished( C );
assertEquals( 1, cDescendants.size() );
assertEquals( Z, cDescendants.get( 0 ) );
final List<MavenProject> bDescendants = graph.markAsFinished( B );
assertEquals( 2, bDescendants.size() );
assertEquals( X, bDescendants.get( 0 ) );
assertEquals( Y, bDescendants.get( 1 ) );
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.lifecycle.Schedule;
import org.apache.maven.lifecycle.internal.stub.MojoExecutorStub;
import org.apache.maven.plugin.MojoExecution;
/**
* @author Kristian Rosenvold
*/
public class ExecutionPlanItemTest
extends TestCase
{
public void testSetComplete()
throws Exception
{
ExecutionPlanItem item = createExecutionPlanItem( "testMojo", null );
item.setComplete(); // This itself is a valid test
assertFalse( item.ensureComplete() );
}
public void testWaitUntilDone()
throws Exception
{
final ExecutionPlanItem item =
createExecutionPlanItem( "testMojo", createExecutionPlanItem( "testMojo2", null ) );
new Thread( new Runnable()
{
public void run()
{
item.setComplete();
}
} ).start();
item.waitUntilDone();
}
public static ExecutionPlanItem createExecutionPlanItem( String mojoDescription, ExecutionPlanItem downStream )
{
return createExecutionPlanItem( mojoDescription, downStream, null );
}
public static ExecutionPlanItem createExecutionPlanItem( String mojoDescription, ExecutionPlanItem downStream,
Schedule schedule )
{
return new ExecutionPlanItem( new MojoExecution( MojoExecutorStub.createMojoDescriptor( mojoDescription ) ),
schedule );
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.lifecycle.internal.stub.BuildPluginManagerStub;
import org.apache.maven.lifecycle.internal.stub.DefaultLifecyclesStub;
import org.apache.maven.lifecycle.internal.stub.PluginPrefixResolverStub;
import org.apache.maven.lifecycle.internal.stub.PluginVersionResolverStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
/**
* @author Kristian Rosenvold>
*/
public class LifecycleExecutionPlanCalculatorTest
extends TestCase
{
public void testCalculateExecutionPlanWithGoalTasks()
throws Exception
{
MojoDescriptorCreator mojoDescriptorCreator = createMojoDescriptorCreator();
LifecycleExecutionPlanCalculator lifecycleExecutionPlanCalculator =
createExecutionPlaceCalculator( mojoDescriptorCreator );
final GoalTask goalTask1 = new GoalTask( "compiler:compile" );
final GoalTask goalTask2 = new GoalTask( "surefire:test" );
final TaskSegment taskSegment1 = new TaskSegment( false, goalTask1, goalTask2 );
final MavenSession session1 = ProjectDependencyGraphStub.getMavenSession( ProjectDependencyGraphStub.A );
MavenExecutionPlan executionPlan =
lifecycleExecutionPlanCalculator.calculateExecutionPlan( session1, ProjectDependencyGraphStub.A,
taskSegment1.getTasks() );
assertEquals( 2, executionPlan.size() );
final GoalTask goalTask3 = new GoalTask( "surefire:test" );
final TaskSegment taskSegment2 = new TaskSegment( false, goalTask1, goalTask2, goalTask3 );
MavenExecutionPlan executionPlan2 =
lifecycleExecutionPlanCalculator.calculateExecutionPlan( session1, ProjectDependencyGraphStub.A,
taskSegment2.getTasks() );
assertEquals( 3, executionPlan2.size() );
}
// Maybe also make one with LifeCycleTasks
private LifecycleExecutionPlanCalculator createExecutionPlaceCalculator(
MojoDescriptorCreator mojoDescriptorCreator )
{
LifecyclePluginResolver lifecyclePluginResolver =
new LifecyclePluginResolver( new PluginVersionResolverStub() );
return new LifecycleExecutionPlanCalculatorImpl( new BuildPluginManagerStub(),
DefaultLifecyclesStub.createDefaultLifeCycles(),
mojoDescriptorCreator, lifecyclePluginResolver );
}
private MojoDescriptorCreator createMojoDescriptorCreator()
{
return new MojoDescriptorCreator( new PluginVersionResolverStub(), new BuildPluginManagerStub(),
new PluginPrefixResolverStub() );
}
}

View File

@ -0,0 +1,135 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.internal.stub.CompletionServiceStub;
import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
import org.apache.maven.lifecycle.internal.stub.LoggerStub;
import org.apache.maven.lifecycle.internal.stub.MojoExecutorStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependenciesResolverStub;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Kristian Rosenvold>
*/
public class LifecycleWeaveBuilderTest
extends TestCase
{
public void testBuildProjectSynchronously()
throws Exception
{
final CompletionService<ProjectSegment> service = new CompletionServiceStub( true );
final ProjectBuildList projectBuildList = runWithCompletionService( service );
assertEquals( "Expect all tasks to be scheduled", projectBuildList.size(),
( (CompletionServiceStub) service ).size() );
}
public void testBuildProjectThreaded()
throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool( 10 );
ExecutorCompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
runWithCompletionService( service );
executor.shutdown();
}
public void testBuildProjectThreadedAggressive()
throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool( 10 );
ExecutorCompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
runWithCompletionService( service );
executor.shutdown();
}
private ProjectBuildList runWithCompletionService( CompletionService<ProjectSegment> service )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException, LifecyclePhaseNotFoundException, LifecycleNotFoundException,
ExecutionException, InterruptedException
{
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try
{
BuildListCalculator buildListCalculator = BuildListCalculatorTest.createBuildListCalculator();
final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
List<TaskSegment> taskSegments = buildListCalculator.calculateTaskSegments( session );
ProjectBuildList projectBuildList = buildListCalculator.calculateProjectBuilds( session, taskSegments );
final MojoExecutorStub mojoExecutorStub = new MojoExecutorStub();
final LifecycleWeaveBuilder builder = getWeaveBuilder( mojoExecutorStub );
final ReactorContext buildContext = createBuildContext( session );
ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
builder.build( projectBuildList, buildContext, taskSegments, session, service, reactorBuildStatus );
LifecycleExecutionPlanCalculatorStub lifecycleExecutionPlanCalculatorStub =
new LifecycleExecutionPlanCalculatorStub();
final int expected = lifecycleExecutionPlanCalculatorStub.getNumberOfExceutions( projectBuildList );
assertEquals( "All executions should be scheduled", expected, mojoExecutorStub.executions.size() );
return projectBuildList;
}
finally
{
Thread.currentThread().setContextClassLoader( loader );
}
}
private ReactorContext createBuildContext( MavenSession session )
{
MavenExecutionResult mavenExecutionResult = new DefaultMavenExecutionResult();
ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
return new ReactorContext( mavenExecutionResult, null, null, reactorBuildStatus );
}
private LifecycleWeaveBuilder getWeaveBuilder( MojoExecutor mojoExecutor )
{
final BuilderCommon builderCommon = getBuilderCommon();
final LoggerStub loggerStub = new LoggerStub();
final LifecycleDependencyResolver lifecycleDependencyResolver =
new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), loggerStub );
return new LifecycleWeaveBuilder( mojoExecutor, builderCommon, loggerStub, lifecycleDependencyResolver );
}
private BuilderCommon getBuilderCommon()
{
final LifecycleDebugLogger logger = new LifecycleDebugLogger( new LoggerStub() );
final LifecycleDependencyResolver lifecycleDependencyResolver =
new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), new LoggerStub() );
return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(), lifecycleDependencyResolver );
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
/**
* @author Kristian Rosenvold
*/
public class ProjectBuildListTest
extends TestCase
{
public void testGetByTaskSegment()
throws Exception
{
final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
ProjectBuildList projectBuildList = ProjectDependencyGraphStub.getProjectBuildList( session );
TaskSegment taskSegment = projectBuildList.get( 0 ).getTaskSegment();
assertTrue( "This test assumes there are at least 6 elements in projectBuilds", projectBuildList.size() >= 6 );
final ProjectBuildList byTaskSegment = projectBuildList.getByTaskSegment( taskSegment );
assertEquals( projectBuildList.size(),
byTaskSegment.size() ); // Todo: Make multiple segments on projectBuildList
}
}

View File

@ -0,0 +1,21 @@
package org.apache.maven.lifecycle.internal;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.maven.lifecycle.internal.stub.LoggerStub;
/**
* @author Kristian Rosenvold
*/
public class ThreadConfigurationServiceTest
extends TestCase
{
public void testGetThreadCount()
throws Exception
{
ThreadConfigurationService threadConfigurationService = new ThreadConfigurationService( new LoggerStub(), 3 );
Assert.assertEquals( 5, threadConfigurationService.getThreadCount( "1.75", true, 6 ).intValue() );
Assert.assertEquals( 6, threadConfigurationService.getThreadCount( "1.84", true, 6 ).intValue() );
}
}

View File

@ -0,0 +1,163 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal;
import junit.framework.TestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @author Kristian Rosenvold
*/
public class ThreadOutputMuxerTest
extends TestCase
{
final String paid = "Paid";
final String in = "In";
final String full = "Full";
public void testSingleThreaded()
throws Exception
{
ProjectBuildList src = getProjectBuildList();
ProjectBuildList projectBuildList =
new ProjectBuildList( Arrays.asList( src.get( 0 ), src.get( 1 ), src.get( 2 ) ) );
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream systemOut = new PrintStream( byteArrayOutputStream );
ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 0 ) );
System.out.print( paid ); // No, this does not print to system.out. It's part of the test
assertEquals( paid.length(), byteArrayOutputStream.size() );
threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 1 ) );
System.out.print( in ); // No, this does not print to system.out. It's part of the test
assertEquals( paid.length(), byteArrayOutputStream.size() );
threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 2 ) );
System.out.print( full ); // No, this does not print to system.out. It's part of the test
assertEquals( paid.length(), byteArrayOutputStream.size() );
threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 0 ) );
threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 1 ) );
threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 2 ) );
threadOutputMuxer.close();
assertEquals( ( paid + in + full ).length(), byteArrayOutputStream.size() );
}
public void testMultiThreaded()
throws Exception
{
ProjectBuildList projectBuildList = getProjectBuildList();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream systemOut = new PrintStream( byteArrayOutputStream );
final ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
final List<String> stringList =
Arrays.asList( "Thinkin", "of", "a", "master", "plan", "Cuz", "aint", "nuthin", "but", "sweat", "inside",
"my", "hand" );
Iterator<String> lyrics = stringList.iterator();
List<Outputter> outputters = new ArrayList<Outputter>();
ExecutorService executor = Executors.newFixedThreadPool( 10 );
CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
for ( ProjectSegment projectBuild : projectBuildList )
{
final Future<ProjectSegment> buildFuture =
service.submit( new Outputter( threadOutputMuxer, projectBuild, lyrics.next() ) );
futures.add( buildFuture );
}
for ( Future<ProjectSegment> future : futures )
{
future.get();
}
int expectedLength = 0;
for ( int i = 0; i < projectBuildList.size(); i++ )
{
expectedLength += stringList.get( i ).length();
}
threadOutputMuxer.close();
final byte[] bytes = byteArrayOutputStream.toByteArray();
String result = new String( bytes );
assertEquals( result, expectedLength, bytes.length );
}
class Outputter
implements Callable<ProjectSegment>
{
private final ThreadOutputMuxer threadOutputMuxer;
private final ProjectSegment item;
private final String response;
Outputter( ThreadOutputMuxer threadOutputMuxer, ProjectSegment item, String response )
{
this.threadOutputMuxer = threadOutputMuxer;
this.item = item;
this.response = response;
}
public ProjectSegment call()
throws Exception
{
threadOutputMuxer.associateThreadWithProjectSegment( item );
System.out.print( response );
threadOutputMuxer.setThisModuleComplete( item );
return item;
}
}
private ProjectBuildList getProjectBuildList()
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
return ProjectDependencyGraphStub.getProjectBuildList( session );
}
}

View File

@ -0,0 +1,36 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>About these stubs</title>
</head>
<body>
<h2>Design</h2>
These stubs can be thought of as hand-coded mock obects. They allow unit tests to test only specific
aspects of a component while ignoring others.
These stubs form an internally consistent data-set that is not expected to change. They are
used to test the individual components in the lifecycle with data that has expected characteristics
and can be asserted as desired.
You can change/extend these stubs, and tests should not be breaking too much, since most tests
assert using expected values from the stubs. Normally, when you try to use data from the stubs that
have not been properly populated, you'll get a nullpointer in your test and you then have to
identify which stub creates that specific piece of data.
The most important stubs are:
LifecycleExecutionPlanCalculatorStub
ProjectDependencyGraphStub
Since they define the primary structure of the project/build.
The stubs define three top-level targets that are defined in LifecycleTaskSegmentCalculatorStub;
clean, aggr and install. "aggr" is an aggregating task while clean and install are lifecyclephases.
There will be three items in the task list for this dataset.
The stubs also exist at different "levels", where one test might wire stubs into a specific live implementation.
In the next test that same "live implementation" will be used in a stub version instead.
Not all live services have stubs, but can be added as needed.
</body>
</html>

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.artifact.repository.RepositoryRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginConfigurationException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
/**
* @author Kristian Rosenvold
*/
public class BuildPluginManagerStub
implements BuildPluginManager
{
public PluginDescriptor loadPlugin( Plugin plugin, RepositoryRequest repositoryRequest )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
InvalidPluginDescriptorException
{
return null;
}
public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, RepositoryRequest repositoryRequest )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, InvalidPluginDescriptorException
{
return MojoExecutorStub.createMojoDescriptor( plugin.getKey() );
}
public ClassRealm getPluginRealm( MavenSession session, PluginDescriptor pluginDescriptor )
throws PluginResolutionException, PluginManagerException
{
return null;
}
public void executeMojo( MavenSession session, MojoExecution execution )
throws MojoFailureException, MojoExecutionException, PluginConfigurationException, PluginManagerException
{
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.lifecycle.internal.ProjectSegment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
/**
* @author Kristian Rosenvold
*/
public class CompletionServiceStub
implements CompletionService<ProjectSegment>
{
List<FutureTask<ProjectSegment>> projectBuildFutureTasks =
Collections.synchronizedList( new ArrayList<FutureTask<ProjectSegment>>() );
final boolean finishImmediately;
public int size()
{
return projectBuildFutureTasks.size();
}
public CompletionServiceStub( boolean finishImmediately )
{
this.finishImmediately = finishImmediately;
}
public Future<ProjectSegment> submit( Callable<ProjectSegment> task )
{
FutureTask<ProjectSegment> projectBuildFutureTask = new FutureTask<ProjectSegment>( task );
projectBuildFutureTasks.add( projectBuildFutureTask );
if ( finishImmediately )
{
projectBuildFutureTask.run();
}
return projectBuildFutureTask;
}
public Future<ProjectSegment> submit( Runnable task, ProjectSegment result )
{
FutureTask<ProjectSegment> projectBuildFutureTask = new FutureTask<ProjectSegment>( task, result );
projectBuildFutureTasks.add( projectBuildFutureTask );
if ( finishImmediately )
{
projectBuildFutureTask.run();
}
return projectBuildFutureTask;
}
public Future<ProjectSegment> take()
throws InterruptedException
{
return null;
}
public Future<ProjectSegment> poll()
{
return null;
}
public Future<ProjectSegment> poll( long timeout, TimeUnit unit )
throws InterruptedException
{
return null;
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.lifecycle.DefaultLifecycles;
import org.apache.maven.lifecycle.Lifecycle;
import org.apache.maven.lifecycle.Schedule;
import org.apache.maven.lifecycle.Scheduling;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import java.util.Arrays;
import java.util.List;
/**
* @author Kristian Rosenvold
*/
public class DefaultLifecyclesStub
{
public static DefaultLifecycles createDefaultLifeCycles()
{
final Lifecycle lifecycle1 = new Lifecycle( "abc", Arrays.asList( "compile" ), null );
final Lifecycle lifecycle2 = new Lifecycle( "abc", Arrays.asList( "test" ), null );
final List<Lifecycle> lifeCycles = Arrays.asList( lifecycle1, lifecycle2 );
final List<Scheduling> schedulingList = getSchedulingList();
final DefaultLifecycles defaultLifecycles = new DefaultLifecycles( lifeCycles, schedulingList );
try
{
defaultLifecycles.initialize();
}
catch ( InitializationException e )
{
throw new RuntimeException( e );
}
return defaultLifecycles;
}
public static List<Scheduling> getSchedulingList()
{
return Arrays.asList( new Scheduling( "default", Arrays.asList( new Schedule( "compile", false, false ),
new Schedule( "test", false, true ) ) ) );
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @author Kristian Rosenvold
*/
public class LifeCyclePluginAnalyzerStub
implements LifeCyclePluginAnalyzer
{
public Set<Plugin> getPluginsBoundByDefaultToAllLifecycles( String packaging )
{
Set<Plugin> plugins;
// NOTE: The upper-case packaging name is intentional, that's a special hinting mode used for certain tests
if ( "JAR".equals( packaging ) )
{
plugins = new LinkedHashSet<Plugin>();
plugins.add( newPlugin( "maven-compiler-plugin", "compile", "testCompile" ) );
plugins.add( newPlugin( "maven-resources-plugin", "resources", "testResources" ) );
plugins.add( newPlugin( "maven-surefire-plugin", "test" ) );
plugins.add( newPlugin( "maven-jar-plugin", "jar" ) );
plugins.add( newPlugin( "maven-install-plugin", "install" ) );
plugins.add( newPlugin( "maven-deploy-plugin", "deploy" ) );
}
else
{
plugins = Collections.emptySet();
}
return plugins;
}
private Plugin newPlugin( String artifactId, String... goals )
{
Plugin plugin = new Plugin();
plugin.setGroupId( "org.apache.maven.plugins" );
plugin.setArtifactId( artifactId );
for ( String goal : goals )
{
PluginExecution pluginExecution = new PluginExecution();
pluginExecution.setId( "default-" + goal );
pluginExecution.addGoal( goal );
plugin.addExecution( pluginExecution );
}
return plugin;
}
}

View File

@ -0,0 +1,171 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.ProjectBuildList;
import org.apache.maven.lifecycle.internal.ProjectSegment;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:kristian@zenior.no">Kristian Rosenvold</a>
*/
public class LifecycleExecutionPlanCalculatorStub
implements LifecycleExecutionPlanCalculator
{
public final static MojoDescriptor CLEAN = createMojoDescriptor( "clean" );
public final static MojoDescriptor VALIDATE = createMojoDescriptor( "validate" );
public final static MojoDescriptor TEST_COMPILE = createMojoDescriptor( "test-compile" );
public final static MojoDescriptor PROCESS_TEST_RESOURCES = createMojoDescriptor( "process-test-resources" );
public final static MojoDescriptor PROCESS_RESOURCES = createMojoDescriptor( "process-resources" );
public final static MojoDescriptor COMPILE = createMojoDescriptor( "compile" );
public final static MojoDescriptor TEST = createMojoDescriptor( "test" );
public final static MojoDescriptor PACKAGE = createMojoDescriptor( "package" );
public final static MojoDescriptor INSTALL = createMojoDescriptor( "install" );
public int getNumberOfExceutions( ProjectBuildList projectBuildList )
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
int result = 0;
for ( ProjectSegment projectBuild : projectBuildList )
{
MavenExecutionPlan plan = calculateExecutionPlan( projectBuild.getSession(), projectBuild.getProject(),
projectBuild.getTaskSegment().getTasks() );
result += plan.size();
}
return result;
}
public MavenExecutionPlan calculateExecutionPlan( MavenSession session, MavenProject project, List<Object> tasks )
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
{
if ( project.equals( ProjectDependencyGraphStub.A ) )
{
return getProjectAExceutionPlan();
}
if ( project.equals( ProjectDependencyGraphStub.B ) )
{
return getProjectBExecutionPlan();
}
// The remaining are basically "for future expansion"
List<MojoExecution> me = new ArrayList<MojoExecution>();
me.add( createMojoExecution( new Plugin(), "resources", "default-resources", PROCESS_RESOURCES ) );
me.add( createMojoExecution( new Plugin(), "compile", "default-compile", COMPILE ) );
return new MavenExecutionPlan( getScopes(), getScopes(),
DefaultLifecyclesStub.createDefaultLifeCycles().createExecutionPlanItem( project,
me ) );
}
public static MavenExecutionPlan getProjectAExceutionPlan()
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
{
List<MojoExecution> me = new ArrayList<MojoExecution>();
me.add( createMojoExecution( new Plugin(), "enforce", "enforce-versions", VALIDATE ) );
me.add( createMojoExecution( new Plugin(), "resources", "default-resources", PROCESS_RESOURCES ) );
me.add( createMojoExecution( new Plugin(), "compile", "default-compile", COMPILE ) );
me.add( createMojoExecution( new Plugin(), "testResources", "default-testResources", PROCESS_TEST_RESOURCES ) );
me.add( createMojoExecution( new Plugin(), "testCompile", "default-testCompile", TEST_COMPILE ) );
me.add( createMojoExecution( new Plugin(), "test", "default-test", TEST ) );
me.add( createMojoExecution( new Plugin(), "war", "default-war", PACKAGE ) );
me.add( createMojoExecution( new Plugin(), "install", "default-install", INSTALL ) );
final List<ExecutionPlanItem> executionPlanItem =
DefaultLifecyclesStub.createDefaultLifeCycles().createExecutionPlanItem(
ProjectDependencyGraphStub.A.getExecutionProject(), me );
return new MavenExecutionPlan( getScopes(), getScopes(), executionPlanItem );
}
public static MavenExecutionPlan getProjectBExecutionPlan()
throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
{
List<MojoExecution> me = new ArrayList<MojoExecution>();
me.add( createMojoExecution( new Plugin(), "enforce", "enforce-versions", VALIDATE ) );
me.add( createMojoExecution( new Plugin(), "resources", "default-resources", PROCESS_RESOURCES ) );
me.add( createMojoExecution( new Plugin(), "compile", "default-compile", COMPILE ) );
me.add( createMojoExecution( new Plugin(), "testResources", "default-testResources", PROCESS_TEST_RESOURCES ) );
me.add( createMojoExecution( new Plugin(), "testCompile", "default-testCompile", TEST_COMPILE ) );
me.add( createMojoExecution( new Plugin(), "test", "default-test", TEST ) );
final List<ExecutionPlanItem> planItem =
DefaultLifecyclesStub.createDefaultLifeCycles().createExecutionPlanItem(
ProjectDependencyGraphStub.B.getExecutionProject(), me );
return new MavenExecutionPlan( getScopes(), getScopes(), planItem );
}
private static MojoExecution createMojoExecution( Plugin plugin, String goal, String executionId,
MojoDescriptor mojoDescriptor )
{
MojoExecution result = new MojoExecution( plugin, goal, executionId );
result.setConfiguration( new Xpp3Dom( executionId + "-" + goal ) );
result.setMojoDescriptor( mojoDescriptor );
return result;
}
public static MojoDescriptor createMojoDescriptor( String phaseName )
{
final MojoDescriptor mojoDescriptor = new MojoDescriptor();
mojoDescriptor.setPhase( phaseName );
final PluginDescriptor descriptor = new PluginDescriptor();
descriptor.setArtifactId( "artifact." + phaseName );
mojoDescriptor.setPluginDescriptor( descriptor );
return mojoDescriptor;
}
public static Set<String> getScopes()
{
return new HashSet<String>( Arrays.asList( "compile" ) );
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.internal.GoalTask;
import org.apache.maven.lifecycle.internal.LifecycleTask;
import org.apache.maven.lifecycle.internal.LifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.TaskSegment;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Kristian Rosenvold
*/
public class LifecycleTaskSegmentCalculatorStub
implements LifecycleTaskSegmentCalculator
{
public static final String clean = "clean";
public static final String aggr = "aggr";
public static final String install = "install";
public List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException
{
List<TaskSegment> taskSegments = new ArrayList<TaskSegment>( tasks.size() );
TaskSegment currentSegment = null;
for ( String task : tasks )
{
if ( aggr.equals( task ) )
{
boolean aggregating = true;
if ( currentSegment == null || currentSegment.isAggregating() != aggregating )
{
currentSegment = new TaskSegment( aggregating );
taskSegments.add( currentSegment );
}
currentSegment.getTasks().add( new GoalTask( task ) );
}
else
{
// lifecycle phase
if ( currentSegment == null || currentSegment.isAggregating() )
{
currentSegment = new TaskSegment( false );
taskSegments.add( currentSegment );
}
currentSegment.getTasks().add( new LifecycleTask( task ) );
}
}
return taskSegments;
}
public boolean requiresProject( MavenSession session )
{
return true;
}
}

View File

@ -0,0 +1,110 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.codehaus.plexus.logging.Logger;
/**
* @author Kristian Rosenvold
*/
public class LoggerStub
implements Logger
{
public void debug( String s )
{
}
public void debug( String s, Throwable throwable )
{
}
public boolean isDebugEnabled()
{
return true;
}
public void info( String s )
{
}
public void info( String s, Throwable throwable )
{
}
public boolean isInfoEnabled()
{
return true;
}
public void warn( String s )
{
}
public void warn( String s, Throwable throwable )
{
}
public boolean isWarnEnabled()
{
return true;
}
public void error( String s )
{
}
public void error( String s, Throwable throwable )
{
}
public boolean isErrorEnabled()
{
return true;
}
public void fatalError( String s )
{
}
public void fatalError( String s, Throwable throwable )
{
}
public boolean isFatalErrorEnabled()
{
return true;
}
public Logger getChildLogger( String s )
{
return null;
}
public int getThreshold()
{
return 0;
}
public void setThreshold( int i )
{
}
public String getName()
{
return "StubLogger";
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.internal.DependencyContext;
import org.apache.maven.lifecycle.internal.MojoExecutor;
import org.apache.maven.lifecycle.internal.PhaseRecorder;
import org.apache.maven.lifecycle.internal.ProjectIndex;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Kristian Rosenvold
*/
public class MojoExecutorStub
extends MojoExecutor
{ // This is being lazy instead of making interface
public List<MojoExecution> executions = Collections.synchronizedList( new ArrayList<MojoExecution>() );
@Override
public void execute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
DependencyContext dependencyContext, PhaseRecorder phaseRecorder )
throws LifecycleExecutionException
{
executions.add( mojoExecution );
}
@Override
public void execute( MavenSession session, List<MojoExecution> mojoExecutions, ProjectIndex projectIndex,
DependencyContext dependencyContext )
throws LifecycleExecutionException
{
for ( MojoExecution mojoExecution : mojoExecutions )
{
executions.add( mojoExecution );
}
}
public static MojoDescriptor createMojoDescriptor( String mojoDescription )
{
final PluginDescriptor descriptor = new PluginDescriptor();
descriptor.setArtifactId( mojoDescription );
final MojoDescriptor mojoDescriptor = new MojoDescriptor();
mojoDescriptor.setDescription( mojoDescription );
mojoDescriptor.setPluginDescriptor( descriptor );
return mojoDescriptor;
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.prefix.PluginPrefixRequest;
import org.apache.maven.plugin.prefix.PluginPrefixResolver;
import org.apache.maven.plugin.prefix.PluginPrefixResult;
/**
* @author Kristian Rosenvold
*/
public class PluginPrefixResolverStub
implements PluginPrefixResolver
{
public PluginPrefixResult resolve( PluginPrefixRequest request )
throws NoPluginFoundForPrefixException
{
return new PluginPrefixResult()
{
public String getGroupId()
{
return "com.foobar";
}
public String getArtifactId()
{
return "bazbaz";
}
public ArtifactRepository getRepository()
{
return null;
}
};
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.plugin.version.PluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.plugin.version.PluginVersionResolver;
import org.apache.maven.plugin.version.PluginVersionResult;
/**
* @author Kristian Rosenvold
*/
public class PluginVersionResolverStub
implements PluginVersionResolver
{
public PluginVersionResult resolve( PluginVersionRequest request )
throws PluginVersionResolutionException
{
return new PluginVersionResult()
{
public String getVersion()
{
return "0.42";
}
public ArtifactRepository getRepository()
{
return null;
}
};
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.ProjectDependenciesResolver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* @author Kristian Rosenvold
*/
public class ProjectDependenciesResolverStub
implements ProjectDependenciesResolver
{
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToResolve, MavenSession session )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return new HashSet<Artifact>();
}
public Set<Artifact> resolve( MavenProject project, Collection<String> scopesToCollect,
Collection<String> scopesToResolve, MavenSession session )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return new HashSet<Artifact>();
}
public Set<Artifact> resolve( Collection<? extends MavenProject> projects, Collection<String> scopes,
MavenSession session )
throws ArtifactResolutionException, ArtifactNotFoundException
{
return new HashSet<Artifact>();
}
}

View File

@ -0,0 +1,226 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import org.apache.maven.execution.AbstractExecutionListener;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.lifecycle.LifecycleNotFoundException;
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
import org.apache.maven.lifecycle.internal.GoalTask;
import org.apache.maven.lifecycle.internal.ProjectBuildList;
import org.apache.maven.lifecycle.internal.ProjectSegment;
import org.apache.maven.lifecycle.internal.TaskSegment;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A stub dependency graph that is custom made for testing concurrent build graph evaluations.
* <p/>
* Implements a graph as follows:
* A has no dependencies
* B depends on A
* C depends on A
* X depends on B & C
* Y depends on B
* Z depends on C
*
* @author Kristian Rosenvold
*/
public class ProjectDependencyGraphStub
implements ProjectDependencyGraph
{
public static final MavenProject A = new MavenProject();
public static final MavenProject B = new MavenProject();
public static final MavenProject C = new MavenProject();
public static final MavenProject X = new MavenProject();
public static final MavenProject Y = new MavenProject();
public static final MavenProject Z = new MavenProject();
public static final MavenProject UNKNOWN = new MavenProject();
static
{
A.setArtifactId( "A" );
B.setArtifactId( "B" );
C.setArtifactId( "C" );
X.setArtifactId( "X" );
Y.setArtifactId( "Y" );
Z.setArtifactId( "Z" );
}
// This should probably be moved to a separate stub
public static ProjectBuildList getProjectBuildList( MavenSession session )
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
final List<ProjectSegment> list = getProjectBuilds( session );
return new ProjectBuildList( list );
}
public static List<ProjectSegment> getProjectBuilds( MavenSession session )
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, PluginNotFoundException, MojoNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
List<ProjectSegment> projectBuilds = new ArrayList<ProjectSegment>();
TaskSegment segment = createTaskSegment();
projectBuilds.add( createProjectBuild( A, session, segment ) );
projectBuilds.add( createProjectBuild( B, session, segment ) );
projectBuilds.add( createProjectBuild( C, session, segment ) );
projectBuilds.add( createProjectBuild( X, session, segment ) );
projectBuilds.add( createProjectBuild( Y, session, segment ) );
projectBuilds.add( createProjectBuild( Z, session, segment ) );
return projectBuilds;
}
private static ProjectSegment createProjectBuild( MavenProject project, MavenSession session,
TaskSegment taskSegment )
throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
LifecyclePhaseNotFoundException, LifecycleNotFoundException
{
final MavenSession session1 = session.clone();
return new ProjectSegment( project, taskSegment, session1 );
}
private static TaskSegment createTaskSegment()
{
TaskSegment result = new TaskSegment( false );
result.getTasks().add( new GoalTask( "t1" ) );
result.getTasks().add( new GoalTask( "t2" ) );
return result;
}
class Dependency
{
MavenProject dependant;
MavenProject dependency;
Dependency( MavenProject dependant, MavenProject dependency )
{
this.dependant = dependant;
this.dependency = dependency;
}
void addIfDownstream( MavenProject mavenProject, List<MavenProject> result )
{
if ( dependency == mavenProject )
{
result.add( dependant );
}
}
void addIfUpstreamOf( MavenProject mavenProject, List<MavenProject> result )
{
if ( dependant == mavenProject )
{
result.add( dependency ); // All projects are the statics from this class
}
}
}
private List<Dependency> getDependencies()
{
List<Dependency> dependencies = new ArrayList<Dependency>();
dependencies.add( new Dependency( B, A ) );
dependencies.add( new Dependency( C, A ) );
dependencies.add( new Dependency( X, B ) );
dependencies.add( new Dependency( X, C ) );
dependencies.add( new Dependency( Y, B ) );
dependencies.add( new Dependency( Z, C ) );
return dependencies;
}
public List<MavenProject> getSortedProjects()
{
return Arrays.asList( A, B, C, X, Y, Z ); // I'm not entirely sure about the order but this shold do...
}
public List<MavenProject> getDownstreamProjects( MavenProject project, boolean transitive )
{
if ( transitive )
{
throw new RuntimeException( "Not implemented yet" );
}
List<MavenProject> result = new ArrayList<MavenProject>();
for ( Dependency dependency : getDependencies() )
{
dependency.addIfDownstream( project, result );
}
return result;
}
public List<MavenProject> getUpstreamProjects( MavenProject project, boolean transitive )
{
if ( transitive )
{
throw new RuntimeException( "Not implemented yet" );
}
List<MavenProject> result = new ArrayList<MavenProject>();
final List<Dependency> dependencies = getDependencies();
for ( Dependency dependency : dependencies )
{
dependency.addIfUpstreamOf( project, result );
}
return result;
}
public static MavenSession getMavenSession( MavenProject mavenProject )
{
final MavenSession session = getMavenSession();
session.setCurrentProject( mavenProject );
return session;
}
public static MavenSession getMavenSession()
{
final DefaultMavenExecutionResult defaultMavenExecutionResult = new DefaultMavenExecutionResult();
MavenExecutionRequest mavenExecutionRequest = new DefaultMavenExecutionRequest();
mavenExecutionRequest.setExecutionListener( new AbstractExecutionListener() );
mavenExecutionRequest.setGoals( Arrays.asList( "clean", "aggr", "install" ) );
final MavenSession session = new MavenSession( null, mavenExecutionRequest, defaultMavenExecutionResult );
final ProjectDependencyGraphStub dependencyGraphStub = new ProjectDependencyGraphStub();
session.setProjectDependencyGraph( dependencyGraphStub );
session.setProjects( dependencyGraphStub.getSortedProjects() );
return session;
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.
*/
package org.apache.maven.lifecycle.internal.stub;
import junit.framework.TestCase;
import org.apache.maven.project.MavenProject;
import java.util.List;
/**
* Tests the stub. Yeah, I know.
*
* @author Kristian Rosenvold
*/
public class ProjectDependencyGraphStubTest
extends TestCase
{
public void testADependencies()
{
ProjectDependencyGraphStub stub = new ProjectDependencyGraphStub();
final List<MavenProject> mavenProjects = stub.getUpstreamProjects( ProjectDependencyGraphStub.A, false );
assertEquals( 0, mavenProjects.size() );
}
public void testBDepenencies( ProjectDependencyGraphStub stub )
{
final List<MavenProject> bProjects = stub.getUpstreamProjects( ProjectDependencyGraphStub.B, false );
assertEquals( 1, bProjects.size() );
assertTrue( bProjects.contains( ProjectDependencyGraphStub.A ) );
}
public void testCDepenencies( ProjectDependencyGraphStub stub )
{
final List<MavenProject> cProjects = stub.getUpstreamProjects( ProjectDependencyGraphStub.C, false );
assertEquals( 1, cProjects.size() );
assertTrue( cProjects.contains( ProjectDependencyGraphStub.C ) );
}
public void testXDepenencies( ProjectDependencyGraphStub stub )
{
final List<MavenProject> cProjects = stub.getUpstreamProjects( ProjectDependencyGraphStub.X, false );
assertEquals( 2, cProjects.size() );
assertTrue( cProjects.contains( ProjectDependencyGraphStub.C ) );
assertTrue( cProjects.contains( ProjectDependencyGraphStub.B ) );
}
}

View File

@ -55,7 +55,7 @@ public MavenExecutionPlan calculateExecutionPlan( MavenSession session, String..
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException
{
return new MavenExecutionPlan( Collections.<MojoExecution> emptyList(), null, null );
return new MavenExecutionPlan(null, null, null );
}
public void execute( MavenSession session )

View File

@ -98,6 +98,8 @@ public class CLIManager
public static final String ENCRYPT_PASSWORD = "ep";
public static final String THREADS = "T";
private Options options;
@SuppressWarnings("static-access")
@ -136,7 +138,8 @@ public CLIManager()
options.addOption( OptionBuilder.withLongOpt( "show-version" ).withDescription( "Display version information WITHOUT stopping build" ).create( SHOW_VERSION ) );
options.addOption( OptionBuilder.withLongOpt( "encrypt-master-password" ).hasArg().withDescription( "Encrypt master security password" ).create( ENCRYPT_MASTER_PASSWORD ) );
options.addOption( OptionBuilder.withLongOpt( "encrypt-password" ).hasArg().withDescription( "Encrypt server password" ).create( ENCRYPT_PASSWORD ) );
options.addOption( OptionBuilder.withLongOpt( "threads" ).hasArg().withDescription( "Thread count, for instance 2.0C where C is core multiplied" ).create( THREADS ) );
// Adding this back in for compatibility with the verifier that hard codes this option.
options.addOption( OptionBuilder.withLongOpt( "no-plugin-registry" ).withDescription( "Ineffective, only kept for backward compatibility" ).create( "npr" ) );

View File

@ -202,7 +202,9 @@ private void logStats( MavenSession session )
long time = finish.getTime() - session.getRequest().getStartTime().getTime();
logger.info( "Total time: " + getFormattedTime( time ) );
String wallClock = session.getRequest().isThreadConfigurationPresent() ? " (Wall Clock)" : "";
logger.info( "Total time: " + getFormattedTime( time ) + wallClock);
logger.info( "Finished at: " + finish );

View File

@ -37,6 +37,7 @@
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.internal.LifecycleWeaveBuilder;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.project.MavenProject;
import org.apache.maven.properties.internal.EnvironmentUtils;
@ -69,6 +70,8 @@ public class MavenCli
{
public static final String LOCAL_REPO_PROPERTY = "maven.repo.local";
public static final String THREADS_DEPRECATED = "maven.threads.experimental";
public static final String userHome = System.getProperty( "user.home" );
public static final File userMavenConfigurationHome = new File( userHome, ".m2" );
@ -863,6 +866,21 @@ else if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption
request.setLocalRepositoryPath( localRepoProperty );
}
final String threadConfiguration = commandLine.hasOption( CLIManager.THREADS ) ?
commandLine.getOptionValue( CLIManager.THREADS) :
request.getSystemProperties().getProperty(MavenCli.THREADS_DEPRECATED); // TODO: Remove this setting. Note that the int-tests use it
if (threadConfiguration != null){
request.setPerCoreThreadCount( threadConfiguration.contains("C"));
if (threadConfiguration.contains("W"))
{
LifecycleWeaveBuilder.setWeaveMode(request.getUserProperties());
}
request.setThreadCount(threadConfiguration.replace("C", "").replace("W", "").replace("auto", ""));
}
return request;
}