public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProject project, Model model,
ProjectBuildingRequest request )
throws PluginResolutionException, PluginVersionResolutionException
{
ClassRealm projectRealm = null;
List<Plugin> extensionPlugins = new ArrayList<Plugin>();
Build build = model.getBuild();
if ( build != null )
{
for ( Extension extension : build.getExtensions() )
{
Plugin plugin = new Plugin();
plugin.setGroupId( extension.getGroupId() );
plugin.setArtifactId( extension.getArtifactId() );
plugin.setVersion( extension.getVersion() );
extensionPlugins.add( plugin );
}
for ( Plugin plugin : build.getPlugins() )
{
if ( plugin.isExtensions() )
{
extensionPlugins.add( plugin );
}
}
}
if ( extensionPlugins.isEmpty() )
{
if ( logger.isDebugEnabled() )
{
logger.debug( "Extension realms for project " + model.getId() + ": (none)" );
}
return new ProjectRealmCache.CacheRecord( null, null );
}
List<ClassRealm> extensionRealms = new ArrayList<ClassRealm>();
Map<ClassRealm, List<String>> exportedPackages = new HashMap<ClassRealm, List<String>>();
Map<ClassRealm, List<String>> exportedArtifacts = new HashMap<ClassRealm, List<String>>();
List<Artifact> publicArtifacts = new ArrayList<Artifact>();
for ( Plugin plugin : extensionPlugins )
{
if ( plugin.getVersion() == null )
{
PluginVersionRequest versionRequest =
new DefaultPluginVersionRequest( plugin, request.getRepositorySession(),
project.getRemotePluginRepositories() );
plugin.setVersion( pluginVersionResolver.resolve( versionRequest ).getVersion() );
}
List<Artifact> artifacts;
PluginArtifactsCache.Key cacheKey =
pluginArtifactsCache.createKey( plugin, null, project.getRemotePluginRepositories(),
request.getRepositorySession() );
PluginArtifactsCache.CacheRecord recordArtifacts = pluginArtifactsCache.get( cacheKey );
if ( recordArtifacts != null )
{
artifacts = recordArtifacts.artifacts;
}
else
{
artifacts = resolveExtensionArtifacts( plugin, project.getRemotePluginRepositories(), request );
recordArtifacts = pluginArtifactsCache.put( cacheKey, artifacts );
}
pluginArtifactsCache.register( project, recordArtifacts );
ClassRealm extensionRealm;
ExtensionDescriptor extensionDescriptor = null;
ExtensionRealmCache.CacheRecord recordRealm = extensionRealmCache.get( artifacts );
if ( recordRealm != null )
{
extensionRealm = recordRealm.realm;
extensionDescriptor = recordRealm.desciptor;
}
else
{
extensionRealm = classRealmManager.createExtensionRealm( plugin, artifacts );
try
{
container.discoverComponents( extensionRealm );
}
catch ( Exception e )
{
throw new IllegalStateException( "Failed to discover components in extension realm "
+ extensionRealm.getId(), e );
}
Artifact extensionArtifact = artifacts.get( 0 );
try
{
extensionDescriptor = extensionDescriptorBuilder.build( extensionArtifact.getFile() );
}
catch ( IOException e )
{
String message = "Invalid extension descriptor for " + plugin.getId() + ": " + e.getMessage();
if ( logger.isDebugEnabled() )
{
logger.error( message, e );
}
else
{
logger.error( message );
}
}
recordRealm = extensionRealmCache.put( artifacts, extensionRealm, extensionDescriptor );
}
extensionRealmCache.register( project, recordRealm );
extensionRealms.add( extensionRealm );
if ( extensionDescriptor != null )
{
exportedPackages.put( extensionRealm, extensionDescriptor.getExportedPackages() );
exportedArtifacts.put( extensionRealm, extensionDescriptor.getExportedArtifacts() );
}
if ( !plugin.isExtensions() && artifacts.size() == 2 && artifacts.get( 0 ).getFile() != null
&& "plexus-utils".equals( artifacts.get( 1 ).getArtifactId() ) )
{
/*
* This is purely for backward-compat with 2.x where <extensions> consisting of a single artifact where
* loaded into the core and hence available to plugins, in contrast to bigger extensions that were
* loaded into a dedicated realm which is invisible to plugins (MNG-2749).
*/
publicArtifacts.add( artifacts.get( 0 ) );
}
}
if ( logger.isDebugEnabled() )
{
logger.debug( "Extension realms for project " + model.getId() + ": " + extensionRealms );
}
ProjectRealmCache.CacheRecord record = projectRealmCache.get( extensionRealms );
if ( record == null )
{
projectRealm = classRealmManager.createProjectRealm( model, publicArtifacts );
Set<String> exclusions = new LinkedHashSet<String>();
for ( ClassRealm extensionRealm : extensionRealms )
{
List<String> excludes = exportedArtifacts.get( extensionRealm );
if ( excludes != null )
{
exclusions.addAll( excludes );
}
List<String> exports = exportedPackages.get( extensionRealm );
if ( exports == null || exports.isEmpty() )
{
/*
* Most existing extensions don't define exported packages, i.e. no classes are to be exposed to
* plugins, yet the components provided by the extension (e.g. artifact handlers) must be
* accessible, i.e. we still must import the extension realm into the project realm.
*/
exports = Arrays.asList( extensionRealm.getId() );
}
for ( String export : exports )
{
projectRealm.importFrom( extensionRealm, export );