diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index 85919fcf27..0545b7eca9 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -18,6 +18,7 @@ package org.apache.maven; import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.context.BuildContextManager; @@ -30,7 +31,11 @@ import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.ReactorManager; import org.apache.maven.execution.RuntimeInformation; +import org.apache.maven.extension.ExtensionManager; import org.apache.maven.lifecycle.LifecycleExecutor; +import org.apache.maven.model.Build; +import org.apache.maven.model.Extension; +import org.apache.maven.model.Model; import org.apache.maven.monitor.event.DefaultEventDispatcher; import org.apache.maven.monitor.event.EventDispatcher; import org.apache.maven.monitor.event.MavenEvents; @@ -41,11 +46,15 @@ import org.apache.maven.project.DuplicateProjectException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.build.model.ModelLineage; +import org.apache.maven.project.build.model.ModelLineageBuilder; +import org.apache.maven.project.build.model.ModelLineageIterator; import org.apache.maven.reactor.MavenExecutionException; import org.apache.maven.settings.Settings; import org.apache.maven.usability.diagnostics.ErrorDiagnostics; import org.codehaus.plexus.PlexusConstants; import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.PlexusContainerException; import org.codehaus.plexus.context.Context; import org.codehaus.plexus.context.ContextException; import org.codehaus.plexus.logging.AbstractLogEnabled; @@ -60,8 +69,10 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.TimeZone; /** @@ -77,6 +88,10 @@ public class DefaultMaven // Components // ---------------------------------------------------------------------- + protected ExtensionManager extensionManager; + + protected ModelLineageBuilder modelLineageBuilder; + protected BuildContextManager buildContextManager; protected MavenProjectBuilder projectBuilder; @@ -337,6 +352,8 @@ public class DefaultMaven throw new MavenExecutionException( "Error selecting project files for the reactor: " + e.getMessage(), e ); } + scanProjectsForExtensions( files, request, globalProfileManager ); + try { projects = collectProjects( files, request.getLocalRepository(), request.isRecursive(), @@ -358,6 +375,91 @@ public class DefaultMaven return projects; } + // TODO: We should probably do this discovery just-in-time, if we can move to building project + // instances just-in-time. + private void scanProjectsForExtensions( List files, MavenExecutionRequest request, + ProfileManager globalProfileManager ) + throws MavenExecutionException + { + MavenProject superProject; + try + { + superProject = projectBuilder.buildStandaloneSuperProject( request.getLocalRepository(), + globalProfileManager ); + } + catch ( ProjectBuildingException e ) + { + throw new MavenExecutionException( "Error building super-POM for retrieving the default remote repository list: " + e.getMessage(), e ); + } + + List originalRemoteRepositories = superProject.getRemoteArtifactRepositories(); + Map cache = new HashMap(); + + for ( Iterator it = files.iterator(); it.hasNext(); ) + { + File pom = (File) it.next(); + + ModelLineage lineage; + try + { + lineage = modelLineageBuilder.buildModelLineage( pom, request.getLocalRepository(), originalRemoteRepositories, globalProfileManager, cache ); + } + catch ( ProjectBuildingException e ) + { + throw new MavenExecutionException( "Error building model lineage in order to pre-scan for extensions: " + e.getMessage(), e ); + } + + for ( ModelLineageIterator lineageIterator = lineage.lineageIterator(); lineageIterator.hasNext(); ) + { + Model model = (Model) lineageIterator.next(); + + Build build = model.getBuild(); + + if ( build != null ) + { + List extensions = build.getExtensions(); + + if ( extensions != null && !extensions.isEmpty() ) + { + List remoteRepositories = lineageIterator.getArtifactRepositories(); + + // thankfully, we don't have to deal with dependencyManagement here, yet. + // TODO Revisit if/when extensions are made to use the info in dependencyManagement + for ( Iterator extensionIterator = extensions.iterator(); extensionIterator.hasNext(); ) + { + Extension extension = (Extension) extensionIterator.next(); + + try + { + extensionManager.addExtension( extension, model, remoteRepositories, request.getLocalRepository() ); + } + catch ( ArtifactResolutionException e ) + { + throw new MavenExecutionException( "Cannot resolve pre-scanned extension artifact: " + + extension.getGroupId() + ":" + extension.getArtifactId() + ": " + e.getMessage(), + e ); + } + catch ( ArtifactNotFoundException e ) + { + throw new MavenExecutionException( "Cannot find pre-scanned extension artifact: " + + extension.getGroupId() + ":" + extension.getArtifactId() + ": " + e.getMessage(), + e ); + } + catch ( PlexusContainerException e ) + { + throw new MavenExecutionException( "Failed to add pre-scanned extension: " + + extension.getGroupId() + ":" + extension.getArtifactId() + ": " + e.getMessage(), + e ); + } + } + } + } + } + } + + extensionManager.registerWagons(); + } + private void logReactorSummaryLine( String name, String status ) { diff --git a/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java b/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java index b12caea314..dc47fa037b 100644 --- a/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java +++ b/maven-core/src/main/java/org/apache/maven/extension/DefaultExtensionManager.java @@ -19,6 +19,7 @@ package org.apache.maven.extension; import org.apache.maven.ArtifactFilterManager; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.ArtifactUtils; +import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.manager.WagonManager; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; @@ -28,6 +29,8 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.model.Extension; +import org.apache.maven.model.Model; +import org.apache.maven.model.Parent; import org.apache.maven.project.MavenProject; import org.apache.maven.wagon.Wagon; import org.codehaus.plexus.PlexusConstants; @@ -41,6 +44,7 @@ import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map; /** @@ -55,6 +59,8 @@ public class DefaultExtensionManager implements ExtensionManager, Contextualizable { + private ArtifactFactory artifactFactory; + private ArtifactResolver artifactResolver; private ArtifactMetadataSource artifactMetadataSource; @@ -65,6 +71,33 @@ public class DefaultExtensionManager private WagonManager wagonManager; + public void addExtension( Extension extension, Model originatingModel, List remoteRepositories, + ArtifactRepository localRepository ) + throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException + { + Artifact extensionArtifact = artifactFactory.createBuildArtifact( extension.getGroupId(), extension.getArtifactId(), extension.getVersion(), "jar" ); + + Parent originatingParent = originatingModel.getParent(); + + String groupId = originatingModel.getGroupId(); + if ( groupId == null && originatingParent != null ) + { + groupId = originatingParent.getGroupId(); + } + + String artifactId = originatingModel.getArtifactId(); + + String version = originatingModel.getVersion(); + if ( version == null && originatingParent != null ) + { + version = originatingParent.getVersion(); + } + + Artifact projectArtifact = artifactFactory.createProjectArtifact( groupId, artifactId, version ); + + addExtension( extensionArtifact, projectArtifact, remoteRepositories, localRepository, null ); + } + public void addExtension( Extension extension, MavenProject project, ArtifactRepository localRepository ) throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException { @@ -73,22 +106,33 @@ public class DefaultExtensionManager getLogger().debug( "Initialising extension: " + extensionId ); Artifact artifact = (Artifact) project.getExtensionArtifactMap().get( extensionId ); - - if ( artifact != null ) + + addExtension( artifact, project.getArtifact(), project.getRemoteArtifactRepositories(), localRepository, + new ActiveArtifactResolver( project ) ); + } + + private void addExtension( Artifact extensionArtifact, Artifact projectArtifact, List remoteRepositories, + ArtifactRepository localRepository, ActiveArtifactResolver activeArtifactResolver ) + throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException + { + if ( extensionArtifact != null ) { - ArtifactFilter filter = new ProjectArtifactExceptionFilter( artifactFilterManager.getArtifactFilter(), project.getArtifact() ); + ArtifactFilter filter = new ProjectArtifactExceptionFilter( artifactFilterManager.getArtifactFilter(), projectArtifact ); - ArtifactResolutionResult result = artifactResolver.resolveTransitively( Collections.singleton( artifact ), - project.getArtifact(), + ArtifactResolutionResult result = artifactResolver.resolveTransitively( Collections.singleton( extensionArtifact ), + projectArtifact, localRepository, - project.getRemoteArtifactRepositories(), + remoteRepositories, artifactMetadataSource, filter ); for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); ) { Artifact a = (Artifact) i.next(); - a = project.replaceWithActiveArtifact( a ); + if ( activeArtifactResolver != null ) + { + a = activeArtifactResolver.replaceWithActiveArtifact( a ); + } getLogger().debug( "Adding to extension classpath: " + a.getFile() ); @@ -116,6 +160,21 @@ public class DefaultExtensionManager { this.container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); } + + private static final class ActiveArtifactResolver + { + private MavenProject project; + + ActiveArtifactResolver( MavenProject project ) + { + this.project = project; + } + + Artifact replaceWithActiveArtifact( Artifact artifact ) + { + return project.replaceWithActiveArtifact( artifact ); + } + } private static final class ProjectArtifactExceptionFilter implements ArtifactFilter @@ -137,4 +196,5 @@ public class DefaultExtensionManager return projectDependencyConflictId.equals( depConflictId ) || passThroughFilter.include( artifact ); } } + } diff --git a/maven-core/src/main/java/org/apache/maven/extension/ExtensionManager.java b/maven-core/src/main/java/org/apache/maven/extension/ExtensionManager.java index cc4d6ec383..b875c2e290 100644 --- a/maven-core/src/main/java/org/apache/maven/extension/ExtensionManager.java +++ b/maven-core/src/main/java/org/apache/maven/extension/ExtensionManager.java @@ -20,9 +20,12 @@ import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.model.Extension; +import org.apache.maven.model.Model; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.PlexusContainerException; +import java.util.List; + /** * Used to locate extensions. * @@ -35,4 +38,8 @@ public interface ExtensionManager throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException; void registerWagons(); + + void addExtension( Extension extension, Model originatingModel, List remoteRepositories, + ArtifactRepository localRepository ) + throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException; } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java index 5189172e2a..2de388fd26 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java @@ -24,9 +24,7 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.ReactorManager; -import org.apache.maven.extension.ExtensionManager; import org.apache.maven.lifecycle.mapping.LifecycleMapping; -import org.apache.maven.model.Extension; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.apache.maven.model.ReportPlugin; @@ -51,7 +49,6 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.project.artifact.InvalidDependencyVersionException; import org.apache.maven.reporting.MavenReport; import org.apache.maven.settings.Settings; -import org.codehaus.plexus.PlexusContainerException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.util.StringUtils; @@ -85,8 +82,6 @@ public class DefaultLifecycleExecutor private PluginManager pluginManager; - private ExtensionManager extensionManager; - private List lifecycles; private ArtifactHandlerManager artifactHandlerManager; @@ -134,54 +129,20 @@ public class DefaultLifecycleExecutor List taskSegments = segmentTaskListByAggregationNeeds( goals, session, rootProject ); // TODO: probably don't want to do all this up front - findExtensions( session ); + try + { + Map handlers = findArtifactTypeHandlers( session ); + + artifactHandlerManager.addHandlers( handlers ); + } + catch ( PluginNotFoundException e ) + { + throw new LifecycleExecutionException( e.getMessage(), e ); + } executeTaskSegments( taskSegments, rm, session, rootProject, dispatcher ); } - private void findExtensions( MavenSession session ) - throws LifecycleExecutionException - { - for ( Iterator i = session.getSortedProjects().iterator(); i.hasNext(); ) - { - MavenProject project = (MavenProject) i.next(); - - for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); ) - { - Extension extension = (Extension) j.next(); - try - { - extensionManager.addExtension( extension, project, session.getLocalRepository() ); - } - catch ( PlexusContainerException e ) - { - throw new LifecycleExecutionException( "Unable to initialise extensions", e ); - } - catch ( ArtifactResolutionException e ) - { - throw new LifecycleExecutionException( e.getMessage(), e ); - } - catch ( ArtifactNotFoundException e ) - { - throw new LifecycleExecutionException( e.getMessage(), e ); - } - } - - extensionManager.registerWagons(); - - try - { - Map handlers = findArtifactTypeHandlers( project, session ); - - artifactHandlerManager.addHandlers( handlers ); - } - catch ( PluginNotFoundException e ) - { - throw new LifecycleExecutionException( e.getMessage(), e ); - } - } - } - private void executeTaskSegments( List taskSegments, ReactorManager rm, MavenSession session, MavenProject rootProject, EventDispatcher dispatcher ) throws LifecycleExecutionException, BuildFailureException @@ -1154,42 +1115,49 @@ public class DefaultLifecycleExecutor /** * @todo Not particularly happy about this. Would like WagonManager and ArtifactTypeHandlerManager to be able to * lookup directly, or have them passed in + * + * @todo Move this sort of thing to the tail end of the project-building process */ - private Map findArtifactTypeHandlers( MavenProject project, MavenSession session ) + private Map findArtifactTypeHandlers( MavenSession session ) throws LifecycleExecutionException, PluginNotFoundException { Map map = new HashMap(); - for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); ) + for ( Iterator projectIterator = session.getSortedProjects().iterator(); projectIterator.hasNext(); ) { - Plugin plugin = (Plugin) i.next(); - - if ( plugin.isExtensions() ) + MavenProject project = (MavenProject) projectIterator.next(); + + for ( Iterator i = project.getBuildPlugins().iterator(); i.hasNext(); ) { - verifyPlugin( plugin, project, session ); + Plugin plugin = (Plugin) i.next(); - // TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly - try + if ( plugin.isExtensions() ) { - Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE ); - map.putAll( components ); - } - catch ( ComponentLookupException e ) - { - getLogger().debug( "Unable to find the lifecycle component in the extension", e ); - } - catch ( PluginManagerException e ) - { - throw new LifecycleExecutionException( "Error looking up available components from plugin '" + - plugin.getKey() + "': " + e.getMessage(), e ); - } + verifyPlugin( plugin, project, session ); - // shudder... - for ( Iterator j = map.values().iterator(); j.hasNext(); ) - { - ArtifactHandler handler = (ArtifactHandler) j.next(); - if ( project.getPackaging().equals( handler.getPackaging() ) ) + // TODO: if moved to the plugin manager we already have the descriptor from above and so do can lookup the container directly + try { - project.getArtifact().setArtifactHandler( handler ); + Map components = pluginManager.getPluginComponents( plugin, ArtifactHandler.ROLE ); + map.putAll( components ); + } + catch ( ComponentLookupException e ) + { + getLogger().debug( "Unable to find the lifecycle component in the extension", e ); + } + catch ( PluginManagerException e ) + { + throw new LifecycleExecutionException( "Error looking up available components from plugin '" + + plugin.getKey() + "': " + e.getMessage(), e ); + } + + // shudder... + for ( Iterator j = map.values().iterator(); j.hasNext(); ) + { + ArtifactHandler handler = (ArtifactHandler) j.next(); + if ( project.getPackaging().equals( handler.getPackaging() ) ) + { + project.getArtifact().setArtifactHandler( handler ); + } } } } diff --git a/maven-core/src/main/resources/META-INF/plexus/components.xml b/maven-core/src/main/resources/META-INF/plexus/components.xml index 93dca1de8f..164bb880cf 100644 --- a/maven-core/src/main/resources/META-INF/plexus/components.xml +++ b/maven-core/src/main/resources/META-INF/plexus/components.xml @@ -48,6 +48,9 @@ org.apache.maven.ArtifactFilterManager + + org.apache.maven.artifact.factory.ArtifactFactory + org.apache.maven.artifact.resolver.ArtifactResolver @@ -80,6 +83,13 @@ org.apache.maven.Maven org.apache.maven.DefaultMaven + + org.apache.maven.extension.ExtensionManager + + + org.apache.maven.project.build.model.ModelLineageBuilder + default + org.apache.maven.context.BuildContextManager default @@ -206,9 +216,6 @@ org.apache.maven.plugin.PluginManager - - org.apache.maven.extension.ExtensionManager - org.apache.maven.artifact.handler.manager.ArtifactHandlerManager