mirror of https://github.com/apache/maven.git
[MNG-4642] Extended MojoDescriptor with threadSafe attribute
Added support for detecting @threadSafe annotation and a nice noisy, warning message. git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@938443 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f46dc2a538
commit
1a7361596b
|
@ -14,10 +14,7 @@
|
|||
*/
|
||||
package org.apache.maven.lifecycle;
|
||||
|
||||
import org.apache.maven.execution.ExecutionEvent;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.execution.*;
|
||||
import org.apache.maven.lifecycle.internal.BuildListCalculator;
|
||||
import org.apache.maven.lifecycle.internal.ConcurrencyDependencyGraph;
|
||||
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
|
||||
|
|
|
@ -20,16 +20,10 @@ package org.apache.maven.lifecycle;
|
|||
*/
|
||||
|
||||
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
//TODO: lifecycles being executed
|
||||
//TODO: what runs in each phase
|
||||
|
@ -196,6 +190,21 @@ public class MavenExecutionPlan
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
public Set<Plugin> getNonThreadSafePlugins()
|
||||
{
|
||||
Set<Plugin> plugins = new HashSet<Plugin>();
|
||||
for ( ExecutionPlanItem executionPlanItem : planItem )
|
||||
{
|
||||
final MojoExecution mojoExecution = executionPlanItem.getMojoExecution();
|
||||
if ( !mojoExecution.getMojoDescriptor().isThreadSafe() )
|
||||
{
|
||||
plugins.add( mojoExecution.getPlugin() );
|
||||
}
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
// Used by m2e but will be removed, really.
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
|
|
|
@ -24,13 +24,19 @@ import org.apache.maven.lifecycle.LifecycleExecutionException;
|
|||
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.model.Plugin;
|
||||
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 org.codehaus.plexus.classworlds.realm.ClassRealm;
|
||||
import org.codehaus.plexus.component.annotations.Component;
|
||||
import org.codehaus.plexus.component.annotations.Requirement;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -56,18 +62,24 @@ public class BuilderCommon
|
|||
@Requirement
|
||||
private ExecutionEventCatapult eventCatapult;
|
||||
|
||||
@Requirement
|
||||
private Logger logger;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public BuilderCommon()
|
||||
{
|
||||
}
|
||||
|
||||
public BuilderCommon( LifecycleDebugLogger lifecycleDebugLogger,
|
||||
LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator,
|
||||
LifecycleDependencyResolver lifecycleDependencyResolver )
|
||||
public BuilderCommon(LifecycleDebugLogger lifecycleDebugLogger,
|
||||
LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator,
|
||||
LifecycleDependencyResolver lifecycleDependencyResolver, Logger logger)
|
||||
{
|
||||
this.lifecycleDebugLogger = lifecycleDebugLogger;
|
||||
this.lifeCycleExecutionPlanCalculator = lifeCycleExecutionPlanCalculator;
|
||||
this.lifecycleDependencyResolver = lifecycleDependencyResolver;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject project, TaskSegment taskSegment,
|
||||
|
@ -81,6 +93,29 @@ public class BuilderCommon
|
|||
lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, project, taskSegment.getTasks() );
|
||||
lifecycleDebugLogger.debugProjectPlan( project, executionPlan );
|
||||
|
||||
if ( session.getRequest().isThreadConfigurationPresent() )
|
||||
{
|
||||
final Set<Plugin> unsafePlugins = executionPlan.getNonThreadSafePlugins();
|
||||
if ( !unsafePlugins.isEmpty() )
|
||||
{
|
||||
logger.warn( "*****************************************************************" );
|
||||
logger.warn( "* Your build is requesting parallel execution, but project *" );
|
||||
logger.warn( "* contains the following plugin(s) that are not marked as *" );
|
||||
logger.warn( "* @threadSafe to support parallel building. *" );
|
||||
logger.warn( "* While this /may/ work fine, please look for plugin updates *" );
|
||||
logger.warn( "* and/or request plugins be made thread-safe. *" );
|
||||
logger.warn( "* If reporting an issue, report it against the plugin in *" );
|
||||
logger.warn( "* question, not against maven-core *" );
|
||||
logger.warn( "*****************************************************************" );
|
||||
logger.warn( "The following plugins are not marked @threadSafe in " + project.getName() + ":" );
|
||||
for ( Plugin unsafePlugin : unsafePlugins )
|
||||
{
|
||||
logger.warn( unsafePlugin.getId() );
|
||||
}
|
||||
logger.warn( "*****************************************************************" );
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -19,9 +19,11 @@ 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 org.apache.maven.model.Plugin;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Kristian Rosenvold
|
||||
|
@ -34,7 +36,7 @@ public class MavenExecutionPlanTest
|
|||
{
|
||||
final List<Scheduling> cycles = DefaultLifecyclesStub.getSchedulingList();
|
||||
final Schedule schedule = cycles.get( 0 ).getSchedules().get( 0 );
|
||||
assertNotNull( schedule);
|
||||
assertNotNull( schedule );
|
||||
|
||||
}
|
||||
|
||||
|
@ -59,13 +61,25 @@ public class MavenExecutionPlanTest
|
|||
assertNotNull( expected );
|
||||
}
|
||||
|
||||
public void testThreadSafeMojos()
|
||||
throws Exception
|
||||
{
|
||||
MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan();
|
||||
final Set<Plugin> unSafePlugins = plan.getNonThreadSafePlugins();
|
||||
// There is only a single threadsafe plugin here...
|
||||
assertEquals( plan.size() - 1, unSafePlugins.size() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testFindLastWhenFirst()
|
||||
throws Exception
|
||||
{
|
||||
MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan();
|
||||
|
||||
ExecutionPlanItem beerPhase = plan.findLastInPhase( LifecycleExecutionPlanCalculatorStub.VALIDATE.getPhase()); // Beer comes straight after package in stub
|
||||
assertNull ( beerPhase);
|
||||
ExecutionPlanItem beerPhase = plan.findLastInPhase(
|
||||
LifecycleExecutionPlanCalculatorStub.VALIDATE.getPhase() ); // Beer comes straight after package in stub
|
||||
assertNull( beerPhase );
|
||||
}
|
||||
|
||||
public void testFindLastInPhaseMisc()
|
||||
|
@ -73,8 +87,8 @@ public class MavenExecutionPlanTest
|
|||
{
|
||||
MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan();
|
||||
|
||||
assertNull( plan.findLastInPhase( "pacXkage" ));
|
||||
// Beer comes straight after package in stub, much like real life.
|
||||
assertNotNull( plan.findLastInPhase( LifecycleExecutionPlanCalculatorStub.INITIALIZE.getPhase()));
|
||||
assertNull( plan.findLastInPhase( "pacXkage" ) );
|
||||
// Beer comes straight after package in stub, much like real life.
|
||||
assertNotNull( plan.findLastInPhase( LifecycleExecutionPlanCalculatorStub.INITIALIZE.getPhase() ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,8 @@ public class BuilderCommonTest
|
|||
final LifecycleDebugLogger logger = new LifecycleDebugLogger( new LoggerStub() );
|
||||
final LifecycleDependencyResolver lifecycleDependencyResolver =
|
||||
new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), new LoggerStub() );
|
||||
return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(), lifecycleDependencyResolver );
|
||||
return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(), lifecycleDependencyResolver,
|
||||
new LoggerStub() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,14 @@ 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.*;
|
||||
import org.apache.maven.lifecycle.internal.stub.CompletionServiceStub;
|
||||
import org.apache.maven.lifecycle.internal.stub.ExecutionEventCatapultStub;
|
||||
import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
|
||||
import org.apache.maven.lifecycle.internal.stub.LifecycleTaskSegmentCalculatorStub;
|
||||
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;
|
||||
|
@ -127,6 +134,7 @@ public class LifecycleWeaveBuilderTest
|
|||
final LifecycleDebugLogger logger = new LifecycleDebugLogger( new LoggerStub() );
|
||||
final LifecycleDependencyResolver lifecycleDependencyResolver =
|
||||
new LifecycleDependencyResolver( new ProjectDependenciesResolverStub(), new LoggerStub() );
|
||||
return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(), lifecycleDependencyResolver );
|
||||
return new BuilderCommon( logger, new LifecycleExecutionPlanCalculatorStub(), lifecycleDependencyResolver,
|
||||
new LoggerStub() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,22 +50,26 @@ public class LifecycleExecutionPlanCalculatorStub
|
|||
implements LifecycleExecutionPlanCalculator
|
||||
{
|
||||
// clean
|
||||
|
||||
public final static MojoDescriptor PRE_CLEAN = createMojoDescriptor( "pre-clean" );
|
||||
|
||||
public final static MojoDescriptor CLEAN = createMojoDescriptor( "clean" );
|
||||
|
||||
public final static MojoDescriptor POST_CLEAN = createMojoDescriptor( "post-clean" );
|
||||
|
||||
// default (or at least some of them)
|
||||
|
||||
public final static MojoDescriptor VALIDATE = createMojoDescriptor( "validate" );
|
||||
|
||||
public final static MojoDescriptor INITIALIZE = createMojoDescriptor( "initialize" );
|
||||
|
||||
|
||||
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 COMPILE = createMojoDescriptor( "compile", true );
|
||||
|
||||
public final static MojoDescriptor TEST = createMojoDescriptor( "test" );
|
||||
|
||||
|
@ -73,13 +77,15 @@ public class LifecycleExecutionPlanCalculatorStub
|
|||
|
||||
public final static MojoDescriptor INSTALL = createMojoDescriptor( "install" );
|
||||
|
||||
|
||||
// site
|
||||
public final static MojoDescriptor PRE_SITE = createMojoDescriptor( "pre-site" );
|
||||
public final static MojoDescriptor SITE = createMojoDescriptor( "site" );
|
||||
public final static MojoDescriptor POST_SITE = createMojoDescriptor( "post-site" );
|
||||
public final static MojoDescriptor SITE_DEPLOY = createMojoDescriptor( "site-deploy" );
|
||||
|
||||
public final static MojoDescriptor PRE_SITE = createMojoDescriptor( "pre-site" );
|
||||
|
||||
public final static MojoDescriptor SITE = createMojoDescriptor( "site" );
|
||||
|
||||
public final static MojoDescriptor POST_SITE = createMojoDescriptor( "post-site" );
|
||||
|
||||
public final static MojoDescriptor SITE_DEPLOY = createMojoDescriptor( "site-deploy" );
|
||||
|
||||
|
||||
public int getNumberOfExceutions( ProjectBuildList projectBuildList )
|
||||
|
@ -112,8 +118,8 @@ public class LifecycleExecutionPlanCalculatorStub
|
|||
}
|
||||
// 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 ) );
|
||||
me.add( createMojoExecution( "resources", "default-resources", PROCESS_RESOURCES ) );
|
||||
me.add( createMojoExecution( "compile", "default-compile", COMPILE ) );
|
||||
return createExecutionPlan( project, me );
|
||||
}
|
||||
|
||||
|
@ -123,30 +129,29 @@ public class LifecycleExecutionPlanCalculatorStub
|
|||
NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException
|
||||
{
|
||||
List<MojoExecution> me = new ArrayList<MojoExecution>();
|
||||
me.add( createMojoExecution( new Plugin(), "initialize", "default-initialize", INITIALIZE ) );
|
||||
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 ) );
|
||||
me.add( createMojoExecution( "initialize", "default-initialize", INITIALIZE ) );
|
||||
me.add( createMojoExecution( "resources", "default-resources", PROCESS_RESOURCES ) );
|
||||
me.add( createMojoExecution( "compile", "default-compile", COMPILE ) );
|
||||
me.add( createMojoExecution( "testResources", "default-testResources", PROCESS_TEST_RESOURCES ) );
|
||||
me.add( createMojoExecution( "testCompile", "default-testCompile", TEST_COMPILE ) );
|
||||
me.add( createMojoExecution( "test", "default-test", TEST ) );
|
||||
me.add( createMojoExecution( "war", "default-war", PACKAGE ) );
|
||||
me.add( createMojoExecution( "install", "default-install", INSTALL ) );
|
||||
return createExecutionPlan( ProjectDependencyGraphStub.A.getExecutionProject(), me );
|
||||
}
|
||||
|
||||
|
||||
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 ) );
|
||||
me.add( createMojoExecution( "enforce", "enforce-versions", VALIDATE ) );
|
||||
me.add( createMojoExecution( "resources", "default-resources", PROCESS_RESOURCES ) );
|
||||
me.add( createMojoExecution( "compile", "default-compile", COMPILE ) );
|
||||
me.add( createMojoExecution( "testResources", "default-testResources", PROCESS_TEST_RESOURCES ) );
|
||||
me.add( createMojoExecution( "testCompile", "default-testCompile", TEST_COMPILE ) );
|
||||
me.add( createMojoExecution( "test", "default-test", TEST ) );
|
||||
return createExecutionPlan( ProjectDependencyGraphStub.B.getExecutionProject(), me );
|
||||
}
|
||||
|
||||
|
@ -162,24 +167,35 @@ public class LifecycleExecutionPlanCalculatorStub
|
|||
DefaultLifecyclesStub.createDefaultLifecycles() );
|
||||
}
|
||||
|
||||
private static MojoExecution createMojoExecution( Plugin plugin, String goal, String executionId,
|
||||
MojoDescriptor mojoDescriptor )
|
||||
private static MojoExecution createMojoExecution( String goal, String executionId, MojoDescriptor mojoDescriptor )
|
||||
{
|
||||
final Plugin plugin = mojoDescriptor.getPluginDescriptor().getPlugin();
|
||||
MojoExecution result = new MojoExecution( plugin, goal, executionId );
|
||||
result.setConfiguration( new Xpp3Dom( executionId + "-" + goal ) );
|
||||
result.setMojoDescriptor( mojoDescriptor );
|
||||
result.setLifecyclePhase( mojoDescriptor.getPhase() );
|
||||
result.setLifecyclePhase( mojoDescriptor.getPhase() );
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public static MojoDescriptor createMojoDescriptor( String phaseName )
|
||||
{
|
||||
return createMojoDescriptor( phaseName, false );
|
||||
}
|
||||
|
||||
public static MojoDescriptor createMojoDescriptor( String phaseName, boolean threadSafe )
|
||||
{
|
||||
final MojoDescriptor mojoDescriptor = new MojoDescriptor();
|
||||
mojoDescriptor.setPhase( phaseName );
|
||||
final PluginDescriptor descriptor = new PluginDescriptor();
|
||||
Plugin plugin = new Plugin();
|
||||
plugin.setArtifactId( "org.apache.maven.test.MavenExecutionPlan" );
|
||||
plugin.setGroupId( "stub-plugin-" + phaseName );
|
||||
descriptor.setPlugin( plugin );
|
||||
descriptor.setArtifactId( "artifact." + phaseName );
|
||||
mojoDescriptor.setPluginDescriptor( descriptor );
|
||||
mojoDescriptor.setThreadSafe( threadSafe );
|
||||
return mojoDescriptor;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,9 @@ public class MojoDescriptor
|
|||
/** By default, the Mojo don't need reports to run */
|
||||
private boolean requiresReports = false;
|
||||
|
||||
/** By default, mojos are not threadsafe */
|
||||
private boolean threadSafe = false;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
|
@ -642,6 +645,23 @@ public class MojoDescriptor
|
|||
return executeGoal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return True if the <code>Mojo</code> is thread-safe and can be run safely in parallel
|
||||
*/
|
||||
public boolean isThreadSafe()
|
||||
{
|
||||
return threadSafe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param threadSafe indicates that the mojo is thread-safe and can be run safely in parallel
|
||||
*/
|
||||
public void setThreadSafe( boolean threadSafe )
|
||||
{
|
||||
this.threadSafe = threadSafe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if this mojo forks either a goal or the lifecycle, {@code false} otherwise.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue