cleaning up NPE in the realm manager, and adding clear() method calls to the embedder to cleanup the realm manager after it's used, to try to keep the number of open realms to a minimum...

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@592222 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2007-11-06 01:34:38 +00:00
parent d206986023
commit a1f995029a
8 changed files with 392 additions and 252 deletions

View File

@ -37,7 +37,6 @@ import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException; import org.codehaus.plexus.context.ContextException;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream;
import java.util.Iterator; import java.util.Iterator;
import java.util.Collection; import java.util.Collection;
import java.util.Set; import java.util.Set;
@ -129,6 +128,8 @@ public privileged aspect Maven20xCompatAspect
&& this( mgr ) && this( mgr )
&& notHere(); && notHere();
// We use the same hack here to make sure that plexus 1.1 is available for extensions that do
// not declare plexus-utils but need it. MNG-2900
Set around( DefaultExtensionManager mgr ): extDepArtifactsResolved( mgr ) Set around( DefaultExtensionManager mgr ): extDepArtifactsResolved( mgr )
{ {
Set result = proceed( mgr ); Set result = proceed( mgr );

View File

@ -22,16 +22,18 @@ import java.net.MalformedURLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class DefaultMavenRealmManager public class DefaultMavenRealmManager
implements MavenRealmManager implements MavenRealmManager
{ {
private Map extensionComponents = new HashMap();
private Map pluginArtifacts = new HashMap(); private Map pluginArtifacts = new HashMap();
private Set managedRealmIds = new HashSet();
private final ClassWorld world; private final ClassWorld world;
private final PlexusContainer container; private final PlexusContainer container;
@ -47,8 +49,27 @@ public class DefaultMavenRealmManager
public void clear() public void clear()
{ {
extensionComponents.clear(); Collection realms = new HashSet( world.getRealms() );
pluginArtifacts.clear(); for ( Iterator it = realms.iterator(); it.hasNext(); )
{
ClassRealm realm = (ClassRealm) it.next();
String id = realm.getId();
if ( managedRealmIds.contains( id ) )
{
try
{
world.disposeRealm( id );
}
catch ( NoSuchRealmException e )
{
// cannot happen.
}
}
}
managedRealmIds.clear();
// pluginArtifacts.clear();
} }
public boolean hasExtensionRealm( Artifact extensionArtifact ) public boolean hasExtensionRealm( Artifact extensionArtifact )
@ -73,6 +94,7 @@ public class DefaultMavenRealmManager
try try
{ {
realm = container.getContainerRealm().createChildRealm( id ); realm = container.getContainerRealm().createChildRealm( id );
managedRealmIds.add( id );
} }
catch ( DuplicateRealmException e ) catch ( DuplicateRealmException e )
{ {
@ -92,18 +114,30 @@ public class DefaultMavenRealmManager
throws RealmManagementException throws RealmManagementException
{ {
String extensionRealmId = RealmUtils.createExtensionRealmId( extensionArtifact ); String extensionRealmId = RealmUtils.createExtensionRealmId( extensionArtifact );
List componentSetDescriptors = (List) extensionComponents.get( extensionRealmId );
// don't re-discover components once this is done once. if ( extensionArtifact.getFile() == null )
if ( componentSetDescriptors == null )
{ {
throw new RealmManagementException( extensionRealmId, "Cannot import project extensions; extension artifact has no associated file that can be scanned for extension components (extension: " + extensionArtifact.getId() + ")" );
}
ClassWorld discoveryWorld = new ClassWorld(); ClassWorld discoveryWorld = new ClassWorld();
List componentSetDescriptors;
try try
{ {
// Create an entire new ClassWorld, ClassRealm for discovering // Create an entire new ClassWorld, ClassRealm for discovering
// the immediate components of the extension artifact, so we don't pollute the // the immediate components of the extension artifact, so we don't pollute the
// container with component descriptors or realms that don't have any meaning beyond discovery. // container with component descriptors or realms that don't have any meaning beyond discovery.
ClassRealm discoveryRealm = new ClassRealm( discoveryWorld, "discovery" ); ClassRealm discoveryRealm;
try
{
discoveryRealm = discoveryWorld.newRealm( "discovery: " + extensionRealmId );
}
catch ( DuplicateRealmException e )
{
throw new RealmManagementException( extensionRealmId, "Unable to create temporary ClassRealm for local-component discovery.", e );
}
try try
{ {
discoveryRealm.addURL( extensionArtifact.getFile().toURL() ); discoveryRealm.addURL( extensionArtifact.getFile().toURL() );
@ -122,29 +156,11 @@ public class DefaultMavenRealmManager
// artifact...this prevents us from adding plexus-archiver components to the mix, for instance, // artifact...this prevents us from adding plexus-archiver components to the mix, for instance,
// when the extension uses that dependency. // when the extension uses that dependency.
componentSetDescriptors = discoverer.findComponents( container.getContext(), discoveryRealm ); componentSetDescriptors = discoverer.findComponents( container.getContext(), discoveryRealm );
extensionComponents.put( extensionRealmId, componentSetDescriptors );
} }
catch ( PlexusConfigurationException e ) catch ( PlexusConfigurationException e )
{ {
throw new RealmManagementException( extensionRealmId, "Unable to discover components in extension artifact: " + extensionArtifact.getId(), e ); throw new RealmManagementException( extensionRealmId, "Unable to discover components in extension artifact: " + extensionArtifact.getId(), e );
} }
}
finally
{
Collection realms = discoveryWorld.getRealms();
for ( Iterator it = realms.iterator(); it.hasNext(); )
{
ClassRealm realm = (ClassRealm) it.next();
try
{
discoveryWorld.disposeRealm( realm.getId() );
}
catch ( NoSuchRealmException e )
{
}
}
}
}
ClassRealm realm = getProjectRealm( projectGroupId, projectArtifactId, projectVersion, true ); ClassRealm realm = getProjectRealm( projectGroupId, projectArtifactId, projectVersion, true );
@ -188,6 +204,23 @@ public class DefaultMavenRealmManager
} }
} }
} }
finally
{
Collection realms = discoveryWorld.getRealms();
for ( Iterator it = realms.iterator(); it.hasNext(); )
{
ClassRealm realm = (ClassRealm) it.next();
try
{
discoveryWorld.disposeRealm( realm.getId() );
}
catch ( NoSuchRealmException e )
{
}
}
}
}
public ClassRealm getProjectRealm( String projectGroupId, String projectArtifactId, String projectVersion ) public ClassRealm getProjectRealm( String projectGroupId, String projectArtifactId, String projectVersion )
{ {
@ -210,6 +243,7 @@ public class DefaultMavenRealmManager
try try
{ {
realm = container.getContainerRealm().createChildRealm( id ); realm = container.getContainerRealm().createChildRealm( id );
managedRealmIds.add( id );
} }
catch ( DuplicateRealmException duplicateError ) catch ( DuplicateRealmException duplicateError )
{ {
@ -286,6 +320,7 @@ public class DefaultMavenRealmManager
try try
{ {
realm = world.newRealm( id ); realm = world.newRealm( id );
// managedRealmIds.add( id );
} }
catch ( DuplicateRealmException e ) catch ( DuplicateRealmException e )
{ {

View File

@ -56,6 +56,12 @@ public class RealmManagementException
this.realmId = realmId; this.realmId = realmId;
} }
public RealmManagementException( String realmId, String message )
{
super( message );
this.realmId = realmId;
}
public String getRealmId() public String getRealmId()
{ {
return realmId; return realmId;

View File

@ -193,8 +193,6 @@ public class DefaultExtensionManager
// skip it. // skip it.
if ( ( pluginArtifact != null ) if ( ( pluginArtifact != null )
&& coreFilter.include( pluginArtifact ) ) && coreFilter.include( pluginArtifact ) )
{
if ( !realmManager.hasExtensionRealm( pluginArtifact ) )
{ {
MavenProject dummyProject = new MavenProject( originatingModel ); MavenProject dummyProject = new MavenProject( originatingModel );
EventDispatcher dispatcher = new DefaultEventDispatcher( request.getEventMonitors() ); EventDispatcher dispatcher = new DefaultEventDispatcher( request.getEventMonitors() );
@ -235,6 +233,8 @@ public class DefaultExtensionManager
throw new ExtensionManagerException( "Failed to resolve extension plugin: " + pluginArtifact, pluginArtifact, groupId, artifactId, version, e ); throw new ExtensionManagerException( "Failed to resolve extension plugin: " + pluginArtifact, pluginArtifact, groupId, artifactId, version, e );
} }
if ( !realmManager.hasExtensionRealm( pluginArtifact ) )
{
try try
{ {
realmManager.createExtensionRealm( pluginArtifact, pd.getArtifacts() ); realmManager.createExtensionRealm( pluginArtifact, pd.getArtifacts() );
@ -299,8 +299,6 @@ public class DefaultExtensionManager
// skip it. // skip it.
if ( ( extensionArtifact != null ) if ( ( extensionArtifact != null )
&& coreFilter.include( extensionArtifact ) ) && coreFilter.include( extensionArtifact ) )
{
if ( !realmManager.hasExtensionRealm( extensionArtifact ) )
{ {
ArtifactFilter filter = ArtifactFilter filter =
new ProjectArtifactExceptionFilter( coreFilter, projectArtifact ); new ProjectArtifactExceptionFilter( coreFilter, projectArtifact );
@ -319,10 +317,6 @@ public class DefaultExtensionManager
extensionArtifact.getId() + "': " + e.getMessage(), extensionArtifact, projectGroupId, projectArtifactId, projectVersion, e ); extensionArtifact.getId() + "': " + e.getMessage(), extensionArtifact, projectGroupId, projectArtifactId, projectVersion, e );
} }
// We use the same hack here to make sure that plexus 1.1 is available for extensions that do
// not declare plexus-utils but need it. MNG-2900
// DefaultPluginManager.checkPlexusUtils( resolutionGroup, artifactFactory );
Set dependencies = new LinkedHashSet(); Set dependencies = new LinkedHashSet();
dependencies.add( extensionArtifact ); dependencies.add( extensionArtifact );
@ -365,6 +359,8 @@ public class DefaultExtensionManager
throw new ExtensionManagerException( "Extension artifact was not resolved, or has no file associated with it.", extensionArtifact, projectGroupId, projectArtifactId, projectVersion ); throw new ExtensionManagerException( "Extension artifact was not resolved, or has no file associated with it.", extensionArtifact, projectGroupId, projectArtifactId, projectVersion );
} }
if ( !realmManager.hasExtensionRealm( extensionArtifact ) )
{
try try
{ {
realmManager.createExtensionRealm( extensionArtifact, resultArtifacts ); realmManager.createExtensionRealm( extensionArtifact, resultArtifacts );

View File

@ -0,0 +1,81 @@
package org.apache.maven.execution;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
import java.io.File;
import java.net.URL;
import java.util.Collections;
public class DefaultMavenRealmManagerTest
extends PlexusTestCase
{
private ArtifactFactory factory;
protected void setUp() throws Exception
{
super.setUp();
factory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
}
public void test_ReuseSingleExtensionRealmFromMultipleProjectRealms_UsingTwoManagerInstances()
throws RealmManagementException, ComponentLookupException
{
ClassLoader cloader = Thread.currentThread().getContextClassLoader();
URL jarResource = cloader.getResource( "org/apache/maven/execution/test-extension-1.jar" );
Artifact ext1 = factory.createBuildArtifact( "org.group", "artifact-ext", "1", "jar" );
Artifact ext2 = factory.createBuildArtifact( "org.group", "artifact-ext", "1", "jar" );
assertNotSame( ext1, ext2 );
ext1.setFile( new File( jarResource.getPath() ) );
ext1.setResolved( true );
ext2.setFile( new File( jarResource.getPath() ) );
ext2.setResolved( true );
Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );
DefaultMavenRealmManager mgr1 = new DefaultMavenRealmManager( getContainer(), logger );
assertFalse( mgr1.hasExtensionRealm( ext1 ) );
mgr1.createExtensionRealm( ext1, Collections.EMPTY_SET );
assertTrue( mgr1.hasExtensionRealm( ext1 ) );
String pAid1 = "artifact-project1";
String pAid2 = "artifact-project1";
assertNotNull( ext1.getFile() );
mgr1.importExtensionsIntoProjectRealm( "org.group", pAid1, "2", ext1 );
String targetClass = ArtifactFactory.ROLE;
Object result1 = getContainer().lookup( targetClass, "test", mgr1.getProjectRealm( "org.group", pAid1, "2" ) );
assertNotNull( result1 );
DefaultMavenRealmManager mgr2 = new DefaultMavenRealmManager( getContainer(), logger );
assertNotNull( ext2.getFile() );
assertTrue( mgr2.hasExtensionRealm( ext2 ) );
// ext2 doesn't have a file associated with it, but it SHOULD succeed anyway.
mgr2.importExtensionsIntoProjectRealm( "org.group", pAid2, "2", ext2 );
Object result2 = getContainer().lookup( targetClass, "test", mgr2.getProjectRealm( "org.group", pAid2, "2" ) );
assertNotNull( result2 );
assertEquals( result1.getClass().getName(), result2.getClass().getName() );
}
}

View File

@ -170,7 +170,7 @@ under the License.
--> -->
<id>tycho</id> <id>tycho</id>
<properties> <properties>
<bundleVersion>2.1.0.v20070901-1427</bundleVersion> <bundleVersion>2.1.0.v20071105-1933</bundleVersion>
</properties> </properties>
<build> <build>
<resources> <resources>

View File

@ -329,6 +329,19 @@ public class MavenEmbedder
public MavenProject readProject( File mavenProject ) public MavenProject readProject( File mavenProject )
throws ProjectBuildingException, ExtensionScanningException throws ProjectBuildingException, ExtensionScanningException
{
try
{
return readProject( mavenProject, request );
}
finally
{
request.getRealmManager().clear();
}
}
private MavenProject readProject( File mavenProject, MavenExecutionRequest request )
throws ProjectBuildingException, ExtensionScanningException
{ {
getLogger().info( "Scanning for extensions: " + mavenProject ); getLogger().info( "Scanning for extensions: " + mavenProject );
@ -348,6 +361,8 @@ public class MavenEmbedder
{ {
MavenExecutionResult result = new DefaultMavenExecutionResult(); MavenExecutionResult result = new DefaultMavenExecutionResult();
try
{
try try
{ {
request = populator.populateDefaults( request, configuration ); request = populator.populateDefaults( request, configuration );
@ -366,7 +381,7 @@ public class MavenEmbedder
// If the artifact handlers are not loaded up-front then this dependency element is not // If the artifact handlers are not loaded up-front then this dependency element is not
// registered as an artifact and is not added to the classpath elements. // registered as an artifact and is not added to the classpath elements.
MavenProject project = readProject( request.getPom() ); MavenProject project = readProject( request.getPom(), request );
// Map handlers = findArtifactTypeHandlers( project ); // Map handlers = findArtifactTypeHandlers( project );
@ -434,6 +449,11 @@ public class MavenEmbedder
return result; return result;
} }
finally
{
request.getRealmManager().clear();
}
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Artifacts // Artifacts
@ -786,6 +806,7 @@ public class MavenEmbedder
finally finally
{ {
loggerManager.setThresholds( oldThreshold ); loggerManager.setThresholds( oldThreshold );
request.getRealmManager().clear();
} }
} }