From 115febf29b9520eed6e94a65212e00e88806a860 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 15 Jun 2022 10:43:17 +0200 Subject: [PATCH] [MNG-7160] Ability to customize core extensions classloaders (#616) --- .../maven/DefaultArtifactFilterManager.java | 6 +-- .../classrealm/DefaultClassRealmManager.java | 8 ++-- .../internal/CoreExportsProvider.java | 22 ++++----- maven-embedder/pom.xml | 2 +- .../BootstrapCoreExtensionManager.java | 47 +++++++++++++++++-- .../src/main/mdo/core-extensions.mdo | 8 ++++ 6 files changed, 69 insertions(+), 24 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java b/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java index a746846a8b..810baaef38 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultArtifactFilterManager.java @@ -29,7 +29,7 @@ import javax.inject.Singleton; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter; -import org.apache.maven.extension.internal.CoreExportsProvider; +import org.apache.maven.extension.internal.CoreExports; /** * @author Jason van Zyl @@ -50,10 +50,10 @@ public class DefaultArtifactFilterManager @Inject public DefaultArtifactFilterManager( List delegates, - CoreExportsProvider coreExports ) + CoreExports coreExports ) { this.delegates = delegates; - this.coreArtifacts = coreExports.get().getExportedArtifacts(); + this.coreArtifacts = coreExports.getExportedArtifacts(); } private synchronized Set getExcludedArtifacts() 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 a4835fdd47..996eb193dc 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 @@ -37,7 +37,7 @@ import javax.inject.Singleton; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.classrealm.ClassRealmRequest.RealmType; -import org.apache.maven.extension.internal.CoreExportsProvider; +import org.apache.maven.extension.internal.CoreExports; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.codehaus.plexus.MutablePlexusContainer; @@ -92,20 +92,20 @@ public class DefaultClassRealmManager @Inject public DefaultClassRealmManager( Logger logger, PlexusContainer container, - List delegates, CoreExportsProvider exports ) + List delegates, CoreExports exports ) { this.logger = logger; this.world = ( (MutablePlexusContainer) container ).getClassWorld(); this.containerRealm = container.getContainerRealm(); this.delegates = delegates; - Map foreignImports = exports.get().getExportedPackages(); + Map foreignImports = exports.getExportedPackages(); this.mavenApiRealm = createRealm( API_REALMID, RealmType.Core, null /* parent */, null /* parentImports */, foreignImports, null /* artifacts */ ); - this.providedArtifacts = exports.get().getExportedArtifacts(); + this.providedArtifacts = exports.getExportedArtifacts(); } private ClassRealm newRealm( String id ) diff --git a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java index 3e6f9f7b67..b1a30fe3c3 100644 --- a/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java +++ b/maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java @@ -19,34 +19,34 @@ package org.apache.maven.extension.internal; * under the License. */ +import java.util.Objects; + import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Provider; import javax.inject.Singleton; import org.codehaus.plexus.PlexusContainer; -import org.eclipse.sisu.Nullable; /** * CoreExportsProvider */ @Named @Singleton -public class CoreExportsProvider +public class CoreExportsProvider implements Provider { private final CoreExports exports; @Inject - public CoreExportsProvider( PlexusContainer container, @Nullable CoreExports exports ) + public CoreExportsProvider( PlexusContainer container ) { - if ( exports == null ) - { - this.exports = new CoreExports( CoreExtensionEntry.discoverFrom( container.getContainerRealm() ) ); - } - else - { - this.exports = exports; - } + this( new CoreExports( CoreExtensionEntry.discoverFrom( container.getContainerRealm() ) ) ); + } + + public CoreExportsProvider( CoreExports exports ) + { + this.exports = Objects.requireNonNull( exports ); } public CoreExports get() diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml index 6792e6219b..9142dfaaa6 100644 --- a/maven-embedder/pom.xml +++ b/maven-embedder/pom.xml @@ -188,7 +188,7 @@ under the License. org.codehaus.modello modello-maven-plugin - 1.0.0 + 1.1.0 src/main/mdo/core-extensions.mdo diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java index 4f9faaea6b..89c9bed4db 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java @@ -31,6 +31,7 @@ import javax.inject.Named; import org.apache.maven.RepositoryUtils; import org.apache.maven.cli.internal.extension.model.CoreExtension; import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.extension.internal.CoreExports; import org.apache.maven.extension.internal.CoreExtensionEntry; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; import org.apache.maven.model.Plugin; @@ -59,12 +60,18 @@ import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator; @Named public class BootstrapCoreExtensionManager { + public static final String STRATEGY_PARENT_FIRST = "parent-first"; + public static final String STRATEGY_PLUGIN = "plugin"; + public static final String STRATEGY_SELF_FIRST = "self-first"; + private final Logger log; private final DefaultPluginDependenciesResolver pluginDependenciesResolver; private final DefaultRepositorySystemSessionFactory repositorySystemSessionFactory; + private final CoreExports coreExports; + private final ClassWorld classWorld; private final ClassRealm parentRealm; @@ -72,11 +79,13 @@ public class BootstrapCoreExtensionManager @Inject public BootstrapCoreExtensionManager( Logger log, DefaultPluginDependenciesResolver pluginDependenciesResolver, DefaultRepositorySystemSessionFactory repositorySystemSessionFactory, + CoreExports coreExports, PlexusContainer container ) { this.log = log; this.pluginDependenciesResolver = pluginDependenciesResolver; this.repositorySystemSessionFactory = repositorySystemSessionFactory; + this.coreExports = coreExports; this.classWorld = ( (DefaultPlexusContainer) container ).getClassWorld(); this.parentRealm = container.getContainerRealm(); } @@ -121,14 +130,42 @@ public class BootstrapCoreExtensionManager { String realmId = "coreExtension>" + extension.getGroupId() + ":" + extension.getArtifactId() + ":" + extension.getVersion(); - ClassRealm realm = classWorld.newRealm( realmId, null ); + final ClassRealm realm = classWorld.newRealm( realmId, null ); + Set providedArtifacts = Collections.emptySet(); + String classLoadingStrategy = extension.getClassLoadingStrategy(); + if ( STRATEGY_PARENT_FIRST.equals( classLoadingStrategy ) ) + { + realm.importFrom( parentRealm, "" ); + } + else if ( STRATEGY_PLUGIN.equals( classLoadingStrategy ) ) + { + coreExports.getExportedPackages().forEach( ( p, cl ) -> realm.importFrom( cl, p ) ); + providedArtifacts = coreExports.getExportedArtifacts(); + } + else if ( STRATEGY_SELF_FIRST.equals( classLoadingStrategy ) ) + { + realm.setParentRealm( parentRealm ); + } + else + { + throw new IllegalArgumentException( "Unsupported class-loading strategy '" + + classLoadingStrategy + "'. Supported values are: " + STRATEGY_PARENT_FIRST + + ", " + STRATEGY_PLUGIN + " and " + STRATEGY_SELF_FIRST ); + } log.debug( "Populating class realm " + realm.getId() ); - realm.setParentRealm( parentRealm ); for ( Artifact artifact : artifacts ) { - File file = artifact.getFile(); - log.debug( " Included " + file ); - realm.addURL( file.toURI().toURL() ); + String id = artifact.getGroupId() + ":" + artifact.getArtifactId(); + if ( providedArtifacts.contains( id ) ) + { + log.debug( " Excluded " + id ); + } + else + { + File file = artifact.getFile(); + log.debug( " Included " + id + " located at " + file ); + realm.addURL( file.toURI().toURL() ); + } } return CoreExtensionEntry.discoverFrom( realm, Collections.singleton( artifacts.get( 0 ).getFile() ) ); } diff --git a/maven-embedder/src/main/mdo/core-extensions.mdo b/maven-embedder/src/main/mdo/core-extensions.mdo index 8a74aabb58..968258d21d 100644 --- a/maven-embedder/src/main/mdo/core-extensions.mdo +++ b/maven-embedder/src/main/mdo/core-extensions.mdo @@ -82,6 +82,14 @@ true String + + classLoadingStrategy + The class loading strategy: 'self-first' (the default), 'parent-first' (loads classes from the parent, then from the extension) or 'plugin' (follows the rules from extensions defined as plugins). + 1.1.0+ + self-first + false + String +