diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java index bca8b3fa1d..fe43b52ef3 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManager.java @@ -20,6 +20,7 @@ package org.apache.maven.classrealm; */ import java.util.List; +import java.util.Map; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; @@ -43,6 +44,13 @@ public interface ClassRealmManager */ ClassRealm getCoreRealm(); + /** + * Gets the class realm exposing the Maven API. This is basically a restricted view on the Maven core realm. + * + * @return The class realm exposing the Maven API, never {@code null}. + */ + ClassRealm getMavenApiRealm(); + /** * Creates a new class realm for the specified project and its build extensions. * @@ -67,12 +75,14 @@ public interface ClassRealmManager * Creates a new class realm for the specified plugin. * * @param plugin The plugin for which to create a realm, must not be {@code null}. - * @param parent The parent realm for the new realm, may be {@code null} to use the Maven core realm. - * @param imports The packages/types to import from the parent realm, may be {@code null}. + * @param parent The parent realm for the new realm, may be {@code null}. + * @param parentImports The packages/types to import from the parent realm, may be {@code null}. + * @param foreignImports The packages/types to import from foreign realms, may be {@code null}. * @param artifacts The artifacts to add to the class realm, may be {@code null}. Unresolved artifacts (i.e. with a * missing file) will automatically be excluded from the realm. * @return The new plugin realm, never {@code null}. */ - ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List imports, List artifacts ); + ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List parentImports, + Map foreignImports, List artifacts ); } diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java index 24e5ce6c50..24f3819e69 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmRequest.java @@ -20,6 +20,7 @@ package org.apache.maven.classrealm; */ import java.util.List; +import java.util.Map; /** * Describes the requirements for a new class realm. @@ -65,16 +66,29 @@ public interface ClassRealmRequest /** * Gets the parent class realm (if any). * - * @return The parent class realm or {@code null} if using the Maven core realm as parent. + * @return The parent class realm or {@code null} if using the default parent. */ ClassLoader getParent(); + /** + * @deprecated Use {@link #getParentImports()} instead. + */ + @Deprecated + List getImports(); + /** * Gets the packages/types to import from the parent realm. * * @return The modifiable list of packages/types to import from the parent realm, never {@code null}. */ - List getImports(); + List getParentImports(); + + /** + * Gets the packages/types to import from foreign realms. + * + * @return The modifiable map of packages/types to import from foreign realms, never {@code null}. + */ + Map getForeignImports(); /** * Gets the constituents for the class realm. diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java index 9d86c9cceb..39fe46353e 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmManager.java @@ -23,10 +23,13 @@ import java.io.File; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.TreeMap; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.classrealm.ClassRealmRequest.RealmType; @@ -100,48 +103,116 @@ public class DefaultClassRealmManager } } - private synchronized ClassRealm getMavenRealm() + public synchronized ClassRealm getMavenApiRealm() { if ( mavenRealm == null ) { mavenRealm = newRealm( "maven.api" ); - importMavenApi( mavenRealm ); + List constituents = new ArrayList(); - mavenRealm.setParentClassLoader( ClassLoader.getSystemClassLoader() ); + List parentImports = new ArrayList(); - List delegates = getDelegates(); - if ( !delegates.isEmpty() ) - { - List constituents = new ArrayList(); + Map foreignImports = new HashMap(); + importMavenApi( foreignImports ); - ClassRealmRequest request = - new DefaultClassRealmRequest( RealmType.Core, null, new ArrayList(), constituents ); + callDelegates( mavenRealm, RealmType.Core, mavenRealm.getParentClassLoader(), parentImports, + foreignImports, constituents ); - for ( ClassRealmManagerDelegate delegate : delegates ) - { - delegate.setupRealm( mavenRealm, request ); - } + wireRealm( mavenRealm, parentImports, foreignImports ); - populateRealm( mavenRealm, constituents ); - } + populateRealm( mavenRealm, constituents ); } + return mavenRealm; } + private void importMavenApi( Map imports ) + { + ClassRealm coreRealm = getCoreRealm(); + + // maven-* + imports.put( "org.apache.maven.*", coreRealm ); + imports.put( "org.apache.maven.artifact", coreRealm ); + imports.put( "org.apache.maven.classrealm", coreRealm ); + imports.put( "org.apache.maven.cli", coreRealm ); + imports.put( "org.apache.maven.configuration", coreRealm ); + imports.put( "org.apache.maven.exception", coreRealm ); + imports.put( "org.apache.maven.execution", coreRealm ); + imports.put( "org.apache.maven.lifecycle", coreRealm ); + imports.put( "org.apache.maven.model", coreRealm ); + imports.put( "org.apache.maven.monitor", coreRealm ); + imports.put( "org.apache.maven.plugin", coreRealm ); + imports.put( "org.apache.maven.profiles", coreRealm ); + imports.put( "org.apache.maven.project", coreRealm ); + imports.put( "org.apache.maven.reporting", coreRealm ); + imports.put( "org.apache.maven.repository", coreRealm ); + imports.put( "org.apache.maven.settings", coreRealm ); + imports.put( "org.apache.maven.toolchain", coreRealm ); + imports.put( "org.apache.maven.usability", coreRealm ); + + // wagon-api + imports.put( "org.apache.maven.wagon.*", coreRealm ); + imports.put( "org.apache.maven.wagon.authentication", coreRealm ); + imports.put( "org.apache.maven.wagon.authorization", coreRealm ); + imports.put( "org.apache.maven.wagon.events", coreRealm ); + imports.put( "org.apache.maven.wagon.observers", coreRealm ); + imports.put( "org.apache.maven.wagon.proxy", coreRealm ); + imports.put( "org.apache.maven.wagon.repository", coreRealm ); + imports.put( "org.apache.maven.wagon.resource", coreRealm ); + + // aether-api, aether-spi, aether-impl + imports.put( "org.sonatype.aether.*", coreRealm ); + imports.put( "org.sonatype.aether.artifact", coreRealm ); + imports.put( "org.sonatype.aether.collection", coreRealm ); + imports.put( "org.sonatype.aether.deployment", coreRealm ); + imports.put( "org.sonatype.aether.graph", coreRealm ); + imports.put( "org.sonatype.aether.impl", coreRealm ); + imports.put( "org.sonatype.aether.installation", coreRealm ); + imports.put( "org.sonatype.aether.metadata", coreRealm ); + imports.put( "org.sonatype.aether.repository", coreRealm ); + imports.put( "org.sonatype.aether.resolution", coreRealm ); + imports.put( "org.sonatype.aether.spi", coreRealm ); + imports.put( "org.sonatype.aether.transfer", coreRealm ); + imports.put( "org.sonatype.aether.version", coreRealm ); + + // plexus-classworlds + imports.put( "org.codehaus.plexus.classworlds", coreRealm ); + + // classworlds (for legacy code) + imports.put( "org.codehaus.classworlds", coreRealm ); + + // plexus-container, plexus-component-annotations + imports.put( "org.codehaus.plexus.*", coreRealm ); + imports.put( "org.codehaus.plexus.component", coreRealm ); + imports.put( "org.codehaus.plexus.configuration", coreRealm ); + imports.put( "org.codehaus.plexus.container", coreRealm ); + imports.put( "org.codehaus.plexus.context", coreRealm ); + imports.put( "org.codehaus.plexus.lifecycle", coreRealm ); + imports.put( "org.codehaus.plexus.logging", coreRealm ); + imports.put( "org.codehaus.plexus.personality", coreRealm ); + + // plexus-utils (for maven-model) + imports.put( "org.codehaus.plexus.util.xml.Xpp3Dom", coreRealm ); + imports.put( "org.codehaus.plexus.util.xml.pull.XmlPullParser", coreRealm ); + imports.put( "org.codehaus.plexus.util.xml.pull.XmlPullParserException", coreRealm ); + imports.put( "org.codehaus.plexus.util.xml.pull.XmlSerializer", coreRealm ); + } + /** * Creates a new class realm with the specified parent and imports. * * @param baseRealmId The base id to use for the new realm, must not be {@code null}. * @param type The type of the class realm, must not be {@code null}. - * @param parent The parent realm for the new realm, may be {@code null} to use the Maven core realm. - * @param imports The packages/types to import from the parent realm, may be {@code null}. + * @param parent The parent realm for the new realm, may be {@code null}. + * @param parentImports The packages/types to import from the parent realm, may be {@code null}. + * @param foreignImports The packages/types to import from foreign realms, may be {@code null}. * @param artifacts The artifacts to add to the realm, may be {@code null}. Unresolved artifacts (i.e. with a * missing file) will automatically be excluded from the realm. * @return The created class realm, never {@code null}. */ - private ClassRealm createRealm( String baseRealmId, RealmType type, ClassLoader parent, List imports, - boolean importXpp3Dom, List artifacts ) + private ClassRealm createRealm( String baseRealmId, RealmType type, ClassLoader parent, List parentImports, + Map foreignImports, List artifacts ) { Set artifactIds = new LinkedHashSet(); @@ -159,13 +230,22 @@ public class DefaultClassRealmManager } } - if ( imports != null ) + if ( parentImports != null ) { - imports = new ArrayList( imports ); + parentImports = new ArrayList( parentImports ); } else { - imports = new ArrayList(); + parentImports = new ArrayList(); + } + + if ( foreignImports != null ) + { + foreignImports = new TreeMap( foreignImports ); + } + else + { + foreignImports = new TreeMap(); } ClassRealm classRealm = newRealm( baseRealmId ); @@ -174,46 +254,10 @@ public class DefaultClassRealmManager { classRealm.setParentClassLoader( parent ); } - else - { - classRealm.setParentRealm( getMavenRealm() ); - } - List delegates = getDelegates(); - if ( !delegates.isEmpty() ) - { - ClassRealmRequest request = new DefaultClassRealmRequest( type, parent, imports, constituents ); + callDelegates( classRealm, type, parent, parentImports, foreignImports, constituents ); - for ( ClassRealmManagerDelegate delegate : delegates ) - { - delegate.setupRealm( classRealm, request ); - } - } - - if ( importXpp3Dom ) - { - importXpp3Dom( classRealm ); - } - - if ( !imports.isEmpty() ) - { - ClassLoader importedRealm = classRealm.getParentClassLoader(); - - if ( logger.isDebugEnabled() ) - { - logger.debug( "Importing packages into class realm " + classRealm.getId() ); - } - - for ( String imp : imports ) - { - if ( logger.isDebugEnabled() ) - { - logger.debug( " Imported: " + imp ); - } - - classRealm.importFrom( importedRealm, imp ); - } - } + wireRealm( classRealm, parentImports, foreignImports ); Set includedIds = populateRealm( classRealm, constituents ); @@ -230,64 +274,6 @@ public class DefaultClassRealmManager return classRealm; } - /** - * Imports Xpp3Dom and associated types into the specified realm. Unlike the other archives that constitute the API - * realm, plexus-utils is not excluded from the plugin/project realm, yet we must ensure this class is loaded from - * the API realm and not from the plugin/project realm. - * - * @param importingRealm The realm into which to import Xpp3Dom, must not be {@code null}. - */ - private void importXpp3Dom( ClassRealm importingRealm ) - { - ClassRealm coreRealm = getCoreRealm(); - - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.util.xml.Xpp3Dom" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.util.xml.pull.XmlPullParser" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.util.xml.pull.XmlPullParserException" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.util.xml.pull.XmlSerializer" ); - } - - /** - * Imports the classes/resources constituting the Maven API into the specified realm. - * - * @param importingRealm The realm into which to import the Maven API, must not be {@code null}. - */ - private void importMavenApi( ClassRealm importingRealm ) - { - ClassRealm coreRealm = getCoreRealm(); - - // maven-* - importingRealm.importFrom( coreRealm, "org.apache.maven" ); - - // aether - importingRealm.importFrom( coreRealm, "org.sonatype.aether" ); - - // plexus-classworlds - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.classworlds" ); - - // classworlds (for legacy code) - importingRealm.importFrom( coreRealm, "org.codehaus.classworlds" ); - - // plexus-container, plexus-component-annotations - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.component" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.configuration" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.container" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.context" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.lifecycle" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.logging" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.personality" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.ComponentRegistry" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.ContainerConfiguration" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.DefaultComponentRegistry" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.DefaultContainerConfiguration" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.DefaultPlexusContainer" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.DuplicateChildContainerException" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.MutablePlexusContainer" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.PlexusConstants" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.PlexusContainer" ); - importingRealm.importFrom( coreRealm, "org.codehaus.plexus.PlexusContainerException" ); - } - public ClassRealm getCoreRealm() { return container.getContainerRealm(); @@ -300,7 +286,9 @@ public class DefaultClassRealmManager throw new IllegalArgumentException( "model missing" ); } - return createRealm( getKey( model ), RealmType.Project, null, null, false, artifacts ); + ClassLoader parent = getMavenApiRealm(); + + return createRealm( getKey( model ), RealmType.Project, parent, null, null, artifacts ); } private static String getKey( Model model ) @@ -315,18 +303,28 @@ public class DefaultClassRealmManager throw new IllegalArgumentException( "extension plugin missing" ); } - return createRealm( getKey( plugin, true ), RealmType.Extension, null, null, true, artifacts ); + ClassLoader parent = ClassLoader.getSystemClassLoader(); + + Map foreignImports = + Collections. singletonMap( "", getMavenApiRealm() ); + + return createRealm( getKey( plugin, true ), RealmType.Extension, parent, null, foreignImports, artifacts ); } - public ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List imports, - List artifacts ) + public ClassRealm createPluginRealm( Plugin plugin, ClassLoader parent, List parentImports, + Map foreignImports, List artifacts ) { if ( plugin == null ) { throw new IllegalArgumentException( "plugin missing" ); } - return createRealm( getKey( plugin, false ), RealmType.Plugin, parent, imports, true, artifacts ); + if ( parent == null ) + { + parent = ClassLoader.getSystemClassLoader(); + } + + return createRealm( getKey( plugin, false ), RealmType.Plugin, parent, parentImports, foreignImports, artifacts ); } private static String getKey( Plugin plugin, boolean extension ) @@ -338,8 +336,8 @@ public class DefaultClassRealmManager private static String getId( Artifact artifact ) { - return getId( artifact.getGroupId(), artifact.getArtifactId(), artifact.getExtension(), artifact.getClassifier(), - artifact.getBaseVersion() ); + return getId( artifact.getGroupId(), artifact.getArtifactId(), artifact.getExtension(), + artifact.getClassifier(), artifact.getBaseVersion() ); } private static String getId( ClassRealmConstituent constituent ) @@ -367,6 +365,31 @@ public class DefaultClassRealmManager } } + private void callDelegates( ClassRealm classRealm, RealmType type, ClassLoader parent, List parentImports, + Map foreignImports, List constituents ) + { + List delegates = getDelegates(); + + if ( !delegates.isEmpty() ) + { + ClassRealmRequest request = + new DefaultClassRealmRequest( type, parent, parentImports, foreignImports, constituents ); + + for ( ClassRealmManagerDelegate delegate : delegates ) + { + try + { + delegate.setupRealm( classRealm, request ); + } + catch ( Exception e ) + { + logger.error( delegate.getClass().getName() + " failed to setup class realm " + classRealm + ": " + + e.getMessage(), e ); + } + } + } + } + private Set populateRealm( ClassRealm classRealm, List constituents ) { Set includedIds = new LinkedHashSet(); @@ -402,4 +425,55 @@ public class DefaultClassRealmManager return includedIds; } + private void wireRealm( ClassRealm classRealm, List parentImports, Map foreignImports ) + { + if ( foreignImports != null && !foreignImports.isEmpty() ) + { + if ( logger.isDebugEnabled() ) + { + logger.debug( "Importing foreign packages into class realm " + classRealm.getId() ); + } + + for ( Map.Entry entry : foreignImports.entrySet() ) + { + ClassLoader importedRealm = entry.getValue(); + String imp = entry.getKey(); + + if ( logger.isDebugEnabled() ) + { + logger.debug( " Imported: " + imp + " < " + getId( importedRealm ) ); + } + + classRealm.importFrom( importedRealm, imp ); + } + } + + if ( parentImports != null && !parentImports.isEmpty() ) + { + if ( logger.isDebugEnabled() ) + { + logger.debug( "Importing parent packages into class realm " + classRealm.getId() ); + } + + for ( String imp : parentImports ) + { + if ( logger.isDebugEnabled() ) + { + logger.debug( " Imported: " + imp + " < " + getId( classRealm.getParentClassLoader() ) ); + } + + classRealm.importFromParent( imp ); + } + } + } + + private String getId( ClassLoader classLoader ) + { + if ( classLoader instanceof ClassRealm ) + { + return ( (ClassRealm) classLoader ).getId(); + } + return String.valueOf( classLoader ); + } + } diff --git a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java index e2917af9e5..062b2cf336 100644 --- a/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java +++ b/maven-core/src/main/java/org/apache/maven/classrealm/DefaultClassRealmRequest.java @@ -20,6 +20,7 @@ package org.apache.maven.classrealm; */ import java.util.List; +import java.util.Map; /** * @author Benjamin Bentmann @@ -32,16 +33,19 @@ class DefaultClassRealmRequest private final ClassLoader parent; - private final List imports; + private final List parentImports; + + private final Map foreignImports; private final List constituents; - public DefaultClassRealmRequest( RealmType type, ClassLoader parent, List imports, - List constituents ) + public DefaultClassRealmRequest( RealmType type, ClassLoader parent, List parentImports, + Map foreignImports, List constituents ) { this.type = type; this.parent = parent; - this.imports = imports; + this.parentImports = parentImports; + this.foreignImports = foreignImports; this.constituents = constituents; } @@ -57,7 +61,17 @@ class DefaultClassRealmRequest public List getImports() { - return imports; + return getParentImports(); + } + + public List getParentImports() + { + return parentImports; + } + + public Map getForeignImports() + { + return foreignImports; } public List getConstituents() diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index 3939d75a65..371f94cc56 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -183,8 +183,7 @@ public class DefaultBuildPluginManager return pluginRealm; } - mavenPluginManager.setupPluginRealm( pluginDescriptor, session, session.getCurrentProject().getClassRealm(), - null, null ); + mavenPluginManager.setupPluginRealm( pluginDescriptor, session, null, null, null ); return pluginDescriptor.getClassRealm(); } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 34b6707752..ee8b75b9de 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -30,6 +30,7 @@ import java.io.Reader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -334,7 +335,10 @@ public class DefaultMavenPluginManager List pluginArtifacts = nlg.getArtifacts( true ); - ClassRealm pluginRealm = classRealmManager.createPluginRealm( plugin, parent, imports, pluginArtifacts ); + Map foreignImports = calcImports( project, parent, imports ); + + ClassRealm pluginRealm = + classRealmManager.createPluginRealm( plugin, parent, null, foreignImports, pluginArtifacts ); pluginDescriptor.setClassRealm( pluginRealm ); pluginDescriptor.setArtifacts( exposedPluginArtifacts ); @@ -361,6 +365,31 @@ public class DefaultMavenPluginManager } } + private Map calcImports( MavenProject project, ClassLoader parent, List imports ) + { + Map foreignImports = new HashMap(); + + ClassLoader projectRealm = project.getClassRealm(); + if ( projectRealm != null ) + { + foreignImports.put( "", projectRealm ); + } + else + { + foreignImports.put( "", classRealmManager.getMavenApiRealm() ); + } + + if ( parent != null && imports != null ) + { + for ( String parentImport : imports ) + { + foreignImports.put( parentImport, parent ); + } + } + + return foreignImports; + } + public T getConfiguredMojo( Class mojoInterface, MavenSession session, MojoExecution mojoExecution ) throws PluginConfigurationException, PluginContainerException { diff --git a/pom.xml b/pom.xml index be9e987137..cc9fc384ab 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2001 - 2.2.3 + 2.4 1.2 1.2_Java1.3 3.8.2