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 0545b7eca9..138f49c8fb 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -17,6 +17,7 @@ package org.apache.maven; */ +import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; @@ -41,6 +42,7 @@ import org.apache.maven.monitor.event.EventDispatcher; import org.apache.maven.monitor.event.MavenEvents; import org.apache.maven.profiles.DefaultProfileManager; import org.apache.maven.profiles.ProfileManager; +import org.apache.maven.profiles.activation.CustomActivatorAdvice; import org.apache.maven.profiles.activation.ProfileActivationException; import org.apache.maven.project.DuplicateProjectException; import org.apache.maven.project.MavenProject; @@ -381,83 +383,101 @@ public class DefaultMaven ProfileManager globalProfileManager ) throws MavenExecutionException { - MavenProject superProject; + // setup the CustomActivatorAdvice to fail quietly while we discover extensions...then, we'll + // reset it. + CustomActivatorAdvice activatorAdvice = CustomActivatorAdvice.getCustomActivatorAdvice( buildContextManager ); + activatorAdvice.setFailQuietly( true ); + activatorAdvice.store( buildContextManager ); + 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; + MavenProject superProject; try { - lineage = modelLineageBuilder.buildModelLineage( pom, request.getLocalRepository(), originalRemoteRepositories, globalProfileManager, cache ); + superProject = projectBuilder.buildStandaloneSuperProject( request.getLocalRepository(), + globalProfileManager ); } catch ( ProjectBuildingException e ) { - throw new MavenExecutionException( "Error building model lineage in order to pre-scan for extensions: " + e.getMessage(), e ); + throw new MavenExecutionException( "Error building super-POM for retrieving the default remote repository list: " + e.getMessage(), e ); } - for ( ModelLineageIterator lineageIterator = lineage.lineageIterator(); lineageIterator.hasNext(); ) + List originalRemoteRepositories = superProject.getRemoteArtifactRepositories(); + Map cache = new HashMap(); + + for ( Iterator it = files.iterator(); it.hasNext(); ) { - Model model = (Model) lineageIterator.next(); + File pom = (File) it.next(); - Build build = model.getBuild(); - - if ( build != null ) + ModelLineage lineage; + try { - List extensions = build.getExtensions(); + getLogger().debug( "Building model-lineage for: " + pom + " to pre-scan for extensions." ); - if ( extensions != null && !extensions.isEmpty() ) + 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 remoteRepositories = lineageIterator.getArtifactRepositories(); + List extensions = build.getExtensions(); - // 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(); ) + if ( extensions != null && !extensions.isEmpty() ) { - Extension extension = (Extension) extensionIterator.next(); + List remoteRepositories = lineageIterator.getArtifactRepositories(); - try + // 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(); ) { - 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 ); + Extension extension = (Extension) extensionIterator.next(); + + getLogger().debug( "Adding extension: " + ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() ) + " from model: " + model.getId() ); + + 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(); + } + finally + { + activatorAdvice.reset(); + activatorAdvice.store( buildContextManager ); } - - extensionManager.registerWagons(); } private void logReactorSummaryLine( String name, diff --git a/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivator.java b/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivator.java index 94cfb1a6f2..1d98bc571a 100644 --- a/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivator.java +++ b/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivator.java @@ -1,5 +1,6 @@ package org.apache.maven.profiles.activation; +import org.apache.maven.context.BuildContextManager; import org.apache.maven.model.Activation; import org.apache.maven.model.ActivationCustom; import org.apache.maven.model.Profile; @@ -49,7 +50,10 @@ public class CustomActivator private Logger logger; + private BuildContextManager buildContextManager; + public boolean canDetermineActivation( Profile profile ) + throws ProfileActivationException { Activation activation = profile.getActivation(); @@ -60,8 +64,11 @@ public class CustomActivator if ( custom != null ) { ProfileActivator activator = loadProfileActivator( custom ); - - return activator.canDetermineActivation( profile ); + + if ( activator != null ) + { + return activator.canDetermineActivation( profile ); + } } } @@ -69,10 +76,14 @@ public class CustomActivator } private ProfileActivator loadProfileActivator( ActivationCustom custom ) + throws ProfileActivationException { + CustomActivatorAdvice advice = CustomActivatorAdvice.getCustomActivatorAdvice( buildContextManager ); + String type = custom.getType(); - ProfileActivator activator; + ProfileActivator activator = null; + try { activator = (ProfileActivator) container.lookup( ProfileActivator.ROLE, type ); @@ -81,8 +92,11 @@ public class CustomActivator { getLogger().debug( "Failed to lookup ProfileActivator \'" + type + "\'", e ); - throw new IllegalArgumentException( "Cannot find ProfileActivator with role-hint: " + type - + ". \nPerhaps you're missing a build extension? \nSee debug output for more information." ); + if ( !advice.failQuietly() ) + { + throw new ProfileActivationException( "Cannot find ProfileActivator with role-hint: " + type + + ". \nPerhaps you're missing a build extension?", e ); + } } PlexusConfiguration configuration = new XmlPlexusConfiguration( (Xpp3Dom) custom.getConfiguration() ); @@ -97,14 +111,18 @@ public class CustomActivator { getLogger().debug( "Failed to configure ProfileActivator \'" + type + "\'", e ); - throw new IllegalArgumentException( "Failed to configure ProfileActivator with role-hint: " + type - + ". Turn on debug mode for more information." ); + if ( !advice.failQuietly() ) + { + throw new ProfileActivationException( "Failed to configure ProfileActivator with role-hint: " + type + + ".", e ); + } } return activator; } public boolean isActive( Profile profile ) + throws ProfileActivationException { ActivationCustom custom = profile.getActivation().getCustom(); diff --git a/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivatorAdvice.java b/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivatorAdvice.java new file mode 100644 index 0000000000..4300ddc537 --- /dev/null +++ b/maven-project/src/main/java/org/apache/maven/profiles/activation/CustomActivatorAdvice.java @@ -0,0 +1,80 @@ +package org.apache.maven.profiles.activation; + +import org.apache.maven.context.BuildContext; +import org.apache.maven.context.BuildContextManager; +import org.apache.maven.context.ManagedBuildData; + +/** + * Advice for the custom profile activator, which tells how to handle cases where custom activators + * cannot be found or configured. This is used to suppress missing activators when pre-scanning for + * build extensions (which may contain the custom activator). + * + * @author jdcasey + */ +public class CustomActivatorAdvice + implements ManagedBuildData +{ + + public static final String BUILD_CONTEXT_KEY = CustomActivatorAdvice.class.getName(); + + private static final boolean DEFAULT_FAIL_QUIETLY = true; + + /** + * If set to false, this tells the CustomProfileActivator to fail quietly when the specified + * custom profile activator cannot be found or configured correctly. Default behavior is to throw + * a new ProfileActivationException. + */ + private boolean failQuietly = DEFAULT_FAIL_QUIETLY; + + public void reset() + { + failQuietly = DEFAULT_FAIL_QUIETLY; + } + + public void setFailQuietly( boolean ignoreMissingActivator ) + { + this.failQuietly = ignoreMissingActivator; + } + + public boolean failQuietly() + { + return failQuietly; + } + + public String getStorageKey() + { + return BUILD_CONTEXT_KEY; + } + + /** + * Read the custom profile activator advice from the build context. If missing or the build + * context has not been initialized, create a new instance of the advice and return that. + */ + public static CustomActivatorAdvice getCustomActivatorAdvice( BuildContextManager buildContextManager ) + { + BuildContext buildContext = buildContextManager.readBuildContext( false ); + + CustomActivatorAdvice advice = null; + + if ( buildContext != null ) + { + advice = (CustomActivatorAdvice) buildContext.get( BUILD_CONTEXT_KEY ); + } + + if ( advice == null ) + { + advice = new CustomActivatorAdvice(); + } + + return advice; + } + + public void store( BuildContextManager buildContextManager ) + { + BuildContext buildContext = buildContextManager.readBuildContext( true ); + + buildContext.put( this ); + + buildContextManager.storeBuildContext( buildContext ); + } +} diff --git a/maven-project/src/main/java/org/apache/maven/profiles/activation/ProfileActivator.java b/maven-project/src/main/java/org/apache/maven/profiles/activation/ProfileActivator.java index 973f27957e..053d07f338 100644 --- a/maven-project/src/main/java/org/apache/maven/profiles/activation/ProfileActivator.java +++ b/maven-project/src/main/java/org/apache/maven/profiles/activation/ProfileActivator.java @@ -22,8 +22,8 @@ public interface ProfileActivator { static final String ROLE = ProfileActivator.class.getName(); - boolean canDetermineActivation( Profile profile ); + boolean canDetermineActivation( Profile profile ) throws ProfileActivationException; - boolean isActive( Profile profile ); + boolean isActive( Profile profile ) throws ProfileActivationException; } diff --git a/maven-project/src/main/resources/META-INF/plexus/components.xml b/maven-project/src/main/resources/META-INF/plexus/components.xml index 195ff5a184..a5dce6e39a 100644 --- a/maven-project/src/main/resources/META-INF/plexus/components.xml +++ b/maven-project/src/main/resources/META-INF/plexus/components.xml @@ -205,6 +205,12 @@ org.apache.maven.profiles.activation.ProfileActivator custom org.apache.maven.profiles.activation.CustomActivator + + + org.apache.maven.context.BuildContextManager + default + +