mirror of https://github.com/apache/maven.git
[MNG-7160] Ability to customize core extensions classloaders (#616)
This commit is contained in:
parent
df38f1c079
commit
415eaf31de
|
@ -29,7 +29,7 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
|
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
|
||||||
import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
|
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
|
* @author Jason van Zyl
|
||||||
|
@ -50,10 +50,10 @@ public class DefaultArtifactFilterManager
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DefaultArtifactFilterManager( List<ArtifactFilterManagerDelegate> delegates,
|
public DefaultArtifactFilterManager( List<ArtifactFilterManagerDelegate> delegates,
|
||||||
CoreExportsProvider coreExports )
|
CoreExports coreExports )
|
||||||
{
|
{
|
||||||
this.delegates = delegates;
|
this.delegates = delegates;
|
||||||
this.coreArtifacts = coreExports.get().getExportedArtifacts();
|
this.coreArtifacts = coreExports.getExportedArtifacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized Set<String> getExcludedArtifacts()
|
private synchronized Set<String> getExcludedArtifacts()
|
||||||
|
|
|
@ -37,7 +37,7 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.maven.artifact.ArtifactUtils;
|
import org.apache.maven.artifact.ArtifactUtils;
|
||||||
import org.apache.maven.classrealm.ClassRealmRequest.RealmType;
|
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.Model;
|
||||||
import org.apache.maven.model.Plugin;
|
import org.apache.maven.model.Plugin;
|
||||||
import org.codehaus.plexus.MutablePlexusContainer;
|
import org.codehaus.plexus.MutablePlexusContainer;
|
||||||
|
@ -94,19 +94,19 @@ public class DefaultClassRealmManager
|
||||||
@Inject
|
@Inject
|
||||||
public DefaultClassRealmManager( PlexusContainer container,
|
public DefaultClassRealmManager( PlexusContainer container,
|
||||||
List<ClassRealmManagerDelegate> delegates,
|
List<ClassRealmManagerDelegate> delegates,
|
||||||
CoreExportsProvider exports )
|
CoreExports exports )
|
||||||
{
|
{
|
||||||
this.world = ( (MutablePlexusContainer) container ).getClassWorld();
|
this.world = ( (MutablePlexusContainer) container ).getClassWorld();
|
||||||
this.containerRealm = container.getContainerRealm();
|
this.containerRealm = container.getContainerRealm();
|
||||||
this.delegates = delegates;
|
this.delegates = delegates;
|
||||||
|
|
||||||
Map<String, ClassLoader> foreignImports = exports.get().getExportedPackages();
|
Map<String, ClassLoader> foreignImports = exports.getExportedPackages();
|
||||||
|
|
||||||
this.mavenApiRealm =
|
this.mavenApiRealm =
|
||||||
createRealm( API_REALMID, RealmType.Core, null /* parent */, null /* parentImports */,
|
createRealm( API_REALMID, RealmType.Core, null /* parent */, null /* parentImports */,
|
||||||
foreignImports, null /* artifacts */ );
|
foreignImports, null /* artifacts */ );
|
||||||
|
|
||||||
this.providedArtifacts = exports.get().getExportedArtifacts();
|
this.providedArtifacts = exports.getExportedArtifacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClassRealm newRealm( String id )
|
private ClassRealm newRealm( String id )
|
||||||
|
|
|
@ -19,34 +19,34 @@ package org.apache.maven.extension.internal;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.codehaus.plexus.PlexusContainer;
|
import org.codehaus.plexus.PlexusContainer;
|
||||||
import org.eclipse.sisu.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CoreExportsProvider
|
* CoreExportsProvider
|
||||||
*/
|
*/
|
||||||
@Named
|
@Named
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CoreExportsProvider
|
public class CoreExportsProvider implements Provider<CoreExports>
|
||||||
{
|
{
|
||||||
|
|
||||||
private final CoreExports exports;
|
private final CoreExports exports;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CoreExportsProvider( PlexusContainer container, @Nullable CoreExports exports )
|
public CoreExportsProvider( PlexusContainer container )
|
||||||
{
|
{
|
||||||
if ( exports == null )
|
this( new CoreExports( CoreExtensionEntry.discoverFrom( container.getContainerRealm() ) ) );
|
||||||
{
|
|
||||||
this.exports = new CoreExports( CoreExtensionEntry.discoverFrom( container.getContainerRealm() ) );
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
public CoreExportsProvider( CoreExports exports )
|
||||||
{
|
{
|
||||||
this.exports = exports;
|
this.exports = Objects.requireNonNull( exports );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoreExports get()
|
public CoreExports get()
|
||||||
|
|
|
@ -175,7 +175,7 @@ under the License.
|
||||||
<groupId>org.codehaus.modello</groupId>
|
<groupId>org.codehaus.modello</groupId>
|
||||||
<artifactId>modello-maven-plugin</artifactId>
|
<artifactId>modello-maven-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
<models>
|
<models>
|
||||||
<model>src/main/mdo/core-extensions.mdo</model>
|
<model>src/main/mdo/core-extensions.mdo</model>
|
||||||
</models>
|
</models>
|
||||||
|
|
|
@ -31,6 +31,7 @@ import javax.inject.Named;
|
||||||
import org.apache.maven.RepositoryUtils;
|
import org.apache.maven.RepositoryUtils;
|
||||||
import org.apache.maven.cli.internal.extension.model.CoreExtension;
|
import org.apache.maven.cli.internal.extension.model.CoreExtension;
|
||||||
import org.apache.maven.execution.MavenExecutionRequest;
|
import org.apache.maven.execution.MavenExecutionRequest;
|
||||||
|
import org.apache.maven.extension.internal.CoreExports;
|
||||||
import org.apache.maven.extension.internal.CoreExtensionEntry;
|
import org.apache.maven.extension.internal.CoreExtensionEntry;
|
||||||
import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
|
import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
|
||||||
import org.apache.maven.model.Plugin;
|
import org.apache.maven.model.Plugin;
|
||||||
|
@ -60,12 +61,18 @@ import org.slf4j.LoggerFactory;
|
||||||
@Named
|
@Named
|
||||||
public class BootstrapCoreExtensionManager
|
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 = LoggerFactory.getLogger( getClass() );
|
private final Logger log = LoggerFactory.getLogger( getClass() );
|
||||||
|
|
||||||
private final DefaultPluginDependenciesResolver pluginDependenciesResolver;
|
private final DefaultPluginDependenciesResolver pluginDependenciesResolver;
|
||||||
|
|
||||||
private final DefaultRepositorySystemSessionFactory repositorySystemSessionFactory;
|
private final DefaultRepositorySystemSessionFactory repositorySystemSessionFactory;
|
||||||
|
|
||||||
|
private final CoreExports coreExports;
|
||||||
|
|
||||||
private final ClassWorld classWorld;
|
private final ClassWorld classWorld;
|
||||||
|
|
||||||
private final ClassRealm parentRealm;
|
private final ClassRealm parentRealm;
|
||||||
|
@ -73,10 +80,12 @@ public class BootstrapCoreExtensionManager
|
||||||
@Inject
|
@Inject
|
||||||
public BootstrapCoreExtensionManager( DefaultPluginDependenciesResolver pluginDependenciesResolver,
|
public BootstrapCoreExtensionManager( DefaultPluginDependenciesResolver pluginDependenciesResolver,
|
||||||
DefaultRepositorySystemSessionFactory repositorySystemSessionFactory,
|
DefaultRepositorySystemSessionFactory repositorySystemSessionFactory,
|
||||||
|
CoreExports coreExports,
|
||||||
PlexusContainer container )
|
PlexusContainer container )
|
||||||
{
|
{
|
||||||
this.pluginDependenciesResolver = pluginDependenciesResolver;
|
this.pluginDependenciesResolver = pluginDependenciesResolver;
|
||||||
this.repositorySystemSessionFactory = repositorySystemSessionFactory;
|
this.repositorySystemSessionFactory = repositorySystemSessionFactory;
|
||||||
|
this.coreExports = coreExports;
|
||||||
this.classWorld = ( (DefaultPlexusContainer) container ).getClassWorld();
|
this.classWorld = ( (DefaultPlexusContainer) container ).getClassWorld();
|
||||||
this.parentRealm = container.getContainerRealm();
|
this.parentRealm = container.getContainerRealm();
|
||||||
}
|
}
|
||||||
|
@ -121,15 +130,43 @@ public class BootstrapCoreExtensionManager
|
||||||
{
|
{
|
||||||
String realmId =
|
String realmId =
|
||||||
"coreExtension>" + extension.getGroupId() + ":" + extension.getArtifactId() + ":" + extension.getVersion();
|
"coreExtension>" + extension.getGroupId() + ":" + extension.getArtifactId() + ":" + extension.getVersion();
|
||||||
ClassRealm realm = classWorld.newRealm( realmId, null );
|
final ClassRealm realm = classWorld.newRealm( realmId, null );
|
||||||
log.debug( "Populating class realm " + realm.getId() );
|
Set<String> 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 );
|
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() );
|
||||||
for ( Artifact artifact : artifacts )
|
for ( Artifact artifact : artifacts )
|
||||||
|
{
|
||||||
|
String id = artifact.getGroupId() + ":" + artifact.getArtifactId();
|
||||||
|
if ( providedArtifacts.contains( id ) )
|
||||||
|
{
|
||||||
|
log.debug( " Excluded {}", id );
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
File file = artifact.getFile();
|
File file = artifact.getFile();
|
||||||
log.debug( " Included " + file );
|
log.debug( " Included {} located at {}", id, file );
|
||||||
realm.addURL( file.toURI().toURL() );
|
realm.addURL( file.toURI().toURL() );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return CoreExtensionEntry.discoverFrom( realm, Collections.singleton( artifacts.get( 0 ).getFile() ) );
|
return CoreExtensionEntry.discoverFrom( realm, Collections.singleton( artifacts.get( 0 ).getFile() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,14 @@
|
||||||
<required>true</required>
|
<required>true</required>
|
||||||
<type>String</type>
|
<type>String</type>
|
||||||
</field>
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>classLoadingStrategy</name>
|
||||||
|
<description>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).</description>
|
||||||
|
<version>1.1.0+</version>
|
||||||
|
<defaultValue>self-first</defaultValue>
|
||||||
|
<required>false</required>
|
||||||
|
<type>String</type>
|
||||||
|
</field>
|
||||||
</fields>
|
</fields>
|
||||||
<codeSegments>
|
<codeSegments>
|
||||||
<codeSegment>
|
<codeSegment>
|
||||||
|
|
Loading…
Reference in New Issue