o moving version resolution when not specified to the lifecycle executor, what goes into the plugin manager will be completely

and entirely resolved.


git-svn-id: https://svn.apache.org/repos/asf/maven/components/branches/MNG-2766@776494 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jason van Zyl 2009-05-19 23:07:08 +00:00
parent e0298b7c97
commit 3a65c9fd76
7 changed files with 455 additions and 192 deletions

View File

@ -2,6 +2,7 @@ package org.apache.maven.exception;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.lifecycle.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.CycleDetectedInPluginGraphException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@ -81,6 +82,10 @@ public class DefaultExceptionHandler
{
message = exception.getMessage();
}
else if ( exception instanceof NoPluginFoundForPrefixException )
{
message = exception.getMessage();
}
// Project dependency downloading problems.
else if ( exception instanceof ArtifactNotFoundException )

View File

@ -16,6 +16,9 @@ package org.apache.maven.lifecycle;
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -28,6 +31,9 @@ import java.util.StringTokenizer;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.RepositoryMetadataReadException;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
@ -52,6 +58,8 @@ import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.TransferFailedException;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
@ -59,8 +67,11 @@ import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
//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.
@ -141,7 +152,7 @@ public class DefaultLifecycleExecutor
try
{
lifecyclePlan = calculateLifecyclePlan( goal, session );
lifecyclePlan = calculateBuildPlan( goal, session );
}
catch ( Exception e )
{
@ -221,17 +232,31 @@ public class DefaultLifecycleExecutor
// 3. Find the mojos associated with the lifecycle given the project packaging (jar lifecycle mapping for the default lifecycle)
// 4. Bind those mojos found in the lifecycle mapping for the packaging to the lifecycle
// 5. Bind mojos specified in the project itself to the lifecycle
public List<MojoExecution> calculateLifecyclePlan( String lifecyclePhase, MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException
public List<MojoExecution> calculateBuildPlan( String task, MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException
{
// Extract the project from the session
MavenProject project = session.getCurrentProject();
List<String> phasesWithMojosToExecute = new ArrayList<String>();
List<MojoExecution> lifecyclePlan = new ArrayList<MojoExecution>();
if ( task.indexOf( ":" ) > 0 )
{
MojoDescriptor mojoDescriptor = getMojoDescriptor( task, session );
MojoExecution mojoExecution = getMojoExecution( project, mojoDescriptor );
lifecyclePlan.add( mojoExecution );
}
else
{
// 1.
//
// Based on the lifecycle phase we are given, let's find the corresponding lifecycle.
//
Lifecycle lifecycle = phaseToLifecycleMap.get( lifecyclePhase );
Lifecycle lifecycle = phaseToLifecycleMap.get( task );
// 2.
//
@ -244,11 +269,11 @@ public class DefaultLifecycleExecutor
Map<String, String> lifecyclePhasesForPackaging;
if ( lifecyclePhase.equals( "clean" ) )
if ( task.equals( "clean" ) )
{
lifecyclePhasesForPackaging = new HashMap<String,String>();
lifecyclePhasesForPackaging = new HashMap<String, String>();
for( String phase : lifecycle.getDefaultPhases() )
for ( String phase : lifecycle.getDefaultPhases() )
{
lifecyclePhasesForPackaging.put( "clean", "org.apache.maven.plugins:maven-clean-plugin:clean" );
}
@ -266,7 +291,7 @@ public class DefaultLifecycleExecutor
//
// Create an ordered Map of the phases in the lifecycle to a list of mojos to execute.
Map<String,List<String>> phaseToMojoMapping = new LinkedHashMap<String,List<String>>();
Map<String, List<String>> phaseToMojoMapping = new LinkedHashMap<String, List<String>>();
// 4.
@ -288,15 +313,15 @@ public class DefaultLifecycleExecutor
//
// This will be useful for having the complete build plan and then we can filter/optimize later.
//
for( Plugin plugin : project.getBuild().getPlugins() )
for ( Plugin plugin : project.getBuild().getPlugins() )
{
for( PluginExecution execution : plugin.getExecutions() )
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 )
{
for( String goal : execution.getGoals() )
for ( String goal : execution.getGoals() )
{
String s = plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + plugin.getVersion() + ":" + goal;
@ -315,7 +340,7 @@ public class DefaultLifecycleExecutor
// if not then i need to grab the mojo descriptor and look at the phase that is specified
else
{
for( String goal : execution.getGoals() )
for ( String goal : execution.getGoals() )
{
String s = plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + plugin.getVersion() + ":" + goal;
MojoDescriptor mojoDescriptor = pluginManager.getMojoDescriptor( plugin, goal, session.getLocalRepository(), project.getRemoteArtifactRepositories() );
@ -335,24 +360,19 @@ public class DefaultLifecycleExecutor
// lifecycle we are not interested in goals -- like "generate-sources -- that belong to the default lifecycle.
//
List<String> phasesWithMojosToExecute = new ArrayList<String>();
for( String phase : phaseToMojoMapping.keySet() )
for ( String phase : phaseToMojoMapping.keySet() )
{
phasesWithMojosToExecute.addAll( phaseToMojoMapping.get( phase ) );
if ( phase.equals( lifecyclePhase ) )
if ( phase.equals( task ) )
{
break;
}
}
// 7. Now we create the correct configuration for the mojo to execute.
//TODO: this needs to go to the model builder.
List<MojoExecution> lifecyclePlan = new ArrayList<MojoExecution>();
for ( String mojo : phasesWithMojosToExecute )
{
// These are bits that look like this:
@ -360,10 +380,11 @@ public class DefaultLifecycleExecutor
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
//
String[] s = StringUtils.split( mojo, ":" );
MojoDescriptor mojoDescriptor = getMojoDescriptor( mojo, session );
MojoExecution mojoExecution = getMojoExecution( project, mojoDescriptor );
/*
MojoExecution mojoExecution = new MojoExecution( mojoDescriptor );
String g = mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId();
@ -386,13 +407,44 @@ public class DefaultLifecycleExecutor
}
}
}
*/
lifecyclePlan.add( mojoExecution );
}
}
return lifecyclePlan;
}
private MojoExecution getMojoExecution( MavenProject project, MojoDescriptor mojoDescriptor )
{
MojoExecution mojoExecution = new MojoExecution( mojoDescriptor );
String g = mojoDescriptor.getPluginDescriptor().getGroupId();
String a = mojoDescriptor.getPluginDescriptor().getArtifactId();
Plugin p = project.getPlugin( g + ":" + a );
for ( PluginExecution e : p.getExecutions() )
{
for ( String goal : e.getGoals() )
{
if ( mojoDescriptor.getGoal().equals( goal ) )
{
Xpp3Dom executionConfiguration = (Xpp3Dom) e.getConfiguration();
Xpp3Dom mojoConfiguration = extractMojoConfiguration( executionConfiguration, mojoDescriptor );
mojoExecution.setConfiguration( mojoConfiguration );
}
}
}
return mojoExecution;
}
/**
* Extracts the configuration for a single mojo from the specified execution configuration by discarding any
* non-applicable parameters. This is necessary because a plugin execution can have multiple goals with different
@ -424,7 +476,7 @@ public class DefaultLifecycleExecutor
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
MojoDescriptor getMojoDescriptor( String task, MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException
{
MavenProject project = session.getCurrentProject();
@ -465,6 +517,68 @@ public class DefaultLifecycleExecutor
goal = tok.nextToken();
}
if ( plugin.getVersion() == null )
{
// We need to get it from the POM first before anything else
//
for ( Plugin pluginInPom : project.getBuildPlugins() )
{
if ( pluginInPom.getArtifactId().equals( plugin.getArtifactId() ) )
{
plugin.setVersion( pluginInPom.getVersion() );
break;
}
}
// 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 )
{
for ( ArtifactRepository repository : session.getCurrentProject().getRemoteArtifactRepositories() )
{
String localPath = plugin.getGroupId().replace( '.', '/' ) + "/" + plugin.getArtifactId() + "/maven-metadata-" + repository.getId() + ".xml";
File destination = new File( session.getLocalRepository().getBasedir(), localPath );
if ( !destination.exists() )
{
try
{
String remotePath = plugin.getGroupId().replace( '.', '/' ) + "/" + plugin.getArtifactId() + "/maven-metadata.xml";
repositorySystem.retrieve( repository, destination, remotePath, session.getRequest().getTransferListener() );
}
catch ( TransferFailedException e )
{
continue;
}
catch ( ResourceDoesNotExistException e )
{
continue;
}
}
// We have retrieved the metadata
try
{
Metadata pluginMetadata = readMetadata( destination );
String release = pluginMetadata.getVersioning().getRelease();
if ( release != null )
{
plugin.setVersion( release );
}
}
catch ( RepositoryMetadataReadException e )
{
logger.warn( "Error reading plugin metadata: ", e );
}
}
}
}
return pluginManager.getMojoDescriptor( plugin, goal, session.getLocalRepository(), project.getRemoteArtifactRepositories() );
}
@ -716,6 +830,141 @@ public class DefaultLifecycleExecutor
return mojoExecution.getConfiguration();
}
private void downloadProjectDependencies( MavenSession session, String scope )
throws ArtifactResolutionException, ArtifactNotFoundException
{
MavenProject project = session.getCurrentProject();
Artifact artifact =
repositorySystem.createProjectArtifact( project.getGroupId(), project.getArtifactId(), project.getVersion() );
artifact.setFile( project.getFile() );
ArtifactFilter filter = new ScopeArtifactFilter( scope );
ArtifactResolutionRequest request = new ArtifactResolutionRequest()
.setArtifact( artifact )
.setResolveRoot( false )
.setResolveTransitively( true )
.setLocalRepository( session.getLocalRepository() )
.setRemoteRepostories( project.getRemoteArtifactRepositories() )
.setManagedVersionMap( project.getManagedVersionMap() )
.setFilter( filter );
ArtifactResolutionResult result = repositorySystem.resolve( request );
resolutionErrorHandler.throwErrors( request, result );
project.setArtifacts( result.getArtifacts() );
}
private Map<String,Plugin> pluginPrefixes = new HashMap<String,Plugin>();
public Plugin findPluginForPrefix( String prefix, MavenSession session )
throws NoPluginFoundForPrefixException
{
// [prefix]:[goal]
Plugin plugin = pluginPrefixes.get( prefix );
if ( plugin != null )
{
return plugin;
}
for ( ArtifactRepository repository : session.getCurrentProject().getRemoteArtifactRepositories() )
{
for ( String pluginGroup : session.getPluginGroups() )
{
// org.apache.maven.plugins
// org/apache/maven/plugins/maven-metadata.xml
String localPath = pluginGroup.replace( '.', '/' ) + "/" + "maven-metadata-" + repository.getId() + ".xml";
File destination = new File( session.getLocalRepository().getBasedir(), localPath );
if ( !destination.exists() )
{
try
{
String remotePath = pluginGroup.replace( '.', '/' ) + "/" + "maven-metadata.xml";
repositorySystem.retrieve( repository, destination, remotePath, session.getRequest().getTransferListener() );
}
catch ( TransferFailedException e )
{
continue;
}
catch ( ResourceDoesNotExistException e )
{
continue;
}
}
// We have retrieved the metadata
try
{
Metadata pluginGroupMetadata = readMetadata( destination );
List<org.apache.maven.artifact.repository.metadata.Plugin> plugins = pluginGroupMetadata.getPlugins();
if ( plugins != null )
{
for ( org.apache.maven.artifact.repository.metadata.Plugin metadataPlugin : plugins )
{
Plugin p = new Plugin();
p.setGroupId( pluginGroup );
p.setArtifactId( metadataPlugin.getArtifactId() );
pluginPrefixes.put( metadataPlugin.getPrefix(), p );
}
}
}
catch ( RepositoryMetadataReadException e )
{
logger.warn( "Error reading plugin group metadata: ", e );
}
}
}
plugin = pluginPrefixes.get( prefix );
if ( plugin != null )
{
return plugin;
}
throw new NoPluginFoundForPrefixException( prefix );
}
protected Metadata readMetadata( File mappingFile )
throws RepositoryMetadataReadException
{
Metadata result;
Reader reader = null;
try
{
reader = ReaderFactory.newXmlReader( mappingFile );
MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
result = mappingReader.read( reader, false );
}
catch ( FileNotFoundException e )
{
throw new RepositoryMetadataReadException( "Cannot read metadata from '" + mappingFile + "'", e );
}
catch ( IOException e )
{
throw new RepositoryMetadataReadException( "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
}
catch ( XmlPullParserException e )
{
throw new RepositoryMetadataReadException( "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
}
finally
{
IOUtil.close( reader );
}
return result;
}
// These are checks that should be available in real time to IDEs
@ -913,41 +1162,4 @@ public class DefaultLifecycleExecutor
}
*/
private void downloadProjectDependencies( MavenSession session, String scope )
throws ArtifactResolutionException, ArtifactNotFoundException
{
MavenProject project = session.getCurrentProject();
Artifact artifact =
repositorySystem.createProjectArtifact( project.getGroupId(), project.getArtifactId(), project.getVersion() );
artifact.setFile( project.getFile() );
ArtifactFilter filter = new ScopeArtifactFilter( scope );
ArtifactResolutionRequest request = new ArtifactResolutionRequest()
.setArtifact( artifact )
.setResolveRoot( false )
.setResolveTransitively( true )
.setLocalRepository( session.getLocalRepository() )
.setRemoteRepostories( project.getRemoteArtifactRepositories() )
.setManagedVersionMap( project.getManagedVersionMap() )
.setFilter( filter );
ArtifactResolutionResult result = repositorySystem.resolve( request );
resolutionErrorHandler.throwErrors( request, result );
project.setArtifacts( result.getArtifacts() );
}
// This would ideally be kept up
public Plugin findPluginForPrefix( String prefix, MavenSession session )
{
// [prefix]:[goal]
//
// eclipse:eclipse
// idea:idea
return null;
//return getByPrefix( prefix, session.getPluginGroups(), project.getRemoteArtifactRepositories(), session.getLocalRepository() );
}
}

View File

@ -52,8 +52,8 @@ public interface LifecycleExecutor
* @return
* @throws LifecycleExecutionException
*/
List<MojoExecution> calculateLifecyclePlan( String lifecyclePhase, MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException;
List<MojoExecution> calculateBuildPlan( String lifecyclePhase, MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException, NoPluginFoundForPrefixException;
// 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

View File

@ -0,0 +1,12 @@
package org.apache.maven.lifecycle;
public class NoPluginFoundForPrefixException
extends Exception
{
private String prefix;
public NoPluginFoundForPrefixException( String prefix )
{
super( "No plugin found for prefix '" + prefix + "'" );
}
}

View File

@ -28,7 +28,9 @@ public class LifecycleExecutorTest
}
@Override
protected void tearDown() throws Exception {
protected void tearDown()
throws Exception
{
lifecycleExecutor = null;
super.tearDown();
}
@ -51,6 +53,24 @@ public class LifecycleExecutorTest
// Tests which exercise the lifecycle executor when it is dealing with default lifecycle phases.
// -----------------------------------------------------------------------------------------------
public void testCalculationOfBuildPlanWithIndividualTaskWherePluginIsSpecifiedInThePom()
throws Exception
{
// We are doing something like "mvn resources:resources" where no version is specified but this
// project we are working on has the version specified in the POM so the version should come from there.
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> lifecyclePlan = lifecycleExecutor.calculateBuildPlan( "resources:resources", session );
assertEquals( 1, lifecyclePlan.size() );
MojoExecution mojoExecution = lifecyclePlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins", mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-resources-plugin", mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "2.3", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
public void testLifecycleQueryingUsingADefaultLifecyclePhase()
throws Exception
{
@ -58,7 +78,7 @@ public class LifecycleExecutorTest
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-additional-lifecycle-elements", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> lifecyclePlan = lifecycleExecutor.calculateLifecyclePlan( "package", session );
List<MojoExecution> lifecyclePlan = lifecycleExecutor.calculateBuildPlan( "package", session );
// resources:resources
// compiler:compile
@ -97,4 +117,13 @@ public class LifecycleExecutorTest
System.out.println( dom );
}
public void testPluginPrefixRetrieval()
throws Exception
{
File pom = getProject( "project-with-additional-lifecycle-elements" );
MavenSession session = createMavenSession( pom );
Plugin plugin = lifecycleExecutor.findPluginForPrefix( "resources", session );
assertEquals( "org.apache.maven.plugins", plugin.getGroupId() );
assertEquals( "maven-resources-plugin", plugin.getArtifactId() );
}
}

View File

@ -49,7 +49,7 @@ public class EmptyLifecycleExecutor
implements LifecycleExecutor
{
public List<MojoExecution> calculateLifecyclePlan( String lifecyclePhase, MavenSession session )
public List<MojoExecution> calculateBuildPlan( String lifecyclePhase, MavenSession session )
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, CycleDetectedInPluginGraphException, MojoNotFoundException
{
return Collections.emptyList();

View File

@ -30,6 +30,11 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
</plugin>
</plugins>
</build>
</project>