From 693f8f6604f24792b4dadbacf2fbc0eb79285915 Mon Sep 17 00:00:00 2001 From: Igor Fedorenko Date: Fri, 8 Aug 2014 22:28:02 +0400 Subject: [PATCH] MNG-5677 hooks to allow fine-grained cache management Also fixed broken cache #flush() and missing #dispose() in couple of places. Signed-off-by: Igor Fedorenko --- .../plugin/DefaultExtensionRealmCache.java | 52 +++++++++++++----- .../plugin/DefaultPluginArtifactsCache.java | 8 +-- .../maven/plugin/DefaultPluginRealmCache.java | 2 +- .../maven/plugin/ExtensionRealmCache.java | 16 ++++-- .../maven/plugin/PluginArtifactsCache.java | 2 +- .../apache/maven/plugin/PluginRealmCache.java | 2 +- .../internal/DefaultMavenPluginManager.java | 2 +- .../maven/project/DefaultProjectBuilder.java | 1 + .../project/DefaultProjectBuildingHelper.java | 20 ++++--- .../project/DefaultProjectRealmCache.java | 53 ++++++++++++++----- .../maven/project/ProjectRealmCache.java | 17 ++++-- 11 files changed, 127 insertions(+), 48 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java index bc10223162..bda84d0081 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultExtensionRealmCache.java @@ -21,14 +21,16 @@ import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.maven.project.ExtensionDescriptor; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.classworlds.realm.NoSuchRealmException; import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable; import org.eclipse.aether.artifact.Artifact; /** @@ -36,10 +38,11 @@ */ @Component( role = ExtensionRealmCache.class ) public class DefaultExtensionRealmCache - implements ExtensionRealmCache + implements ExtensionRealmCache, Disposable { - private static class CacheKey + protected static class CacheKey + implements Key { private final List files; @@ -97,28 +100,36 @@ public boolean equals( Object o ) && sizes.equals( other.sizes ); } + @Override + public String toString() + { + return files.toString(); + } } - private final Map cache = new HashMap(); + protected final Map cache = new ConcurrentHashMap(); - public CacheRecord get( List extensionArtifacts ) + @Override + public Key createKey( List extensionArtifacts ) { - return cache.get( new CacheKey( extensionArtifacts ) ); + return new CacheKey( extensionArtifacts ); } - public CacheRecord put( List extensionArtifacts, ClassRealm extensionRealm, - ExtensionDescriptor extensionDescriptor ) + public CacheRecord get( Key key ) + { + return cache.get( key ); + } + + public CacheRecord put( Key key, ClassRealm extensionRealm, ExtensionDescriptor extensionDescriptor ) { if ( extensionRealm == null ) { throw new NullPointerException(); } - CacheKey key = new CacheKey( extensionArtifacts ); - if ( cache.containsKey( key ) ) { - throw new IllegalStateException( "Duplicate extension realm for extension " + extensionArtifacts ); + throw new IllegalStateException( "Duplicate extension realm for extension " + key ); } CacheRecord record = new CacheRecord( extensionRealm, extensionDescriptor ); @@ -130,12 +141,29 @@ public CacheRecord put( List extensionArtifacts, ClassRealm public void flush() { + for ( CacheRecord record : cache.values() ) + { + ClassRealm realm = record.realm; + try + { + realm.getWorld().disposeRealm( realm.getId() ); + } + catch ( NoSuchRealmException e ) + { + // ignore + } + } cache.clear(); } - public void register( MavenProject project, CacheRecord record ) + public void register( MavenProject project, Key key, CacheRecord record ) { // default cache does not track extension usage } + public void dispose() + { + flush(); + } + } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginArtifactsCache.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginArtifactsCache.java index 145482d85a..6ee3463c6a 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginArtifactsCache.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginArtifactsCache.java @@ -21,9 +21,9 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.maven.model.Plugin; import org.apache.maven.project.MavenProject; @@ -44,7 +44,7 @@ public class DefaultPluginArtifactsCache implements PluginArtifactsCache { - private static class CacheKey + protected static class CacheKey implements Key { @@ -133,7 +133,7 @@ private static boolean eq( T s1, T s2 ) } - protected final Map cache = new HashMap(); + protected final Map cache = new ConcurrentHashMap(); public Key createKey( Plugin plugin, DependencyFilter extensionFilter, List repositories, RepositorySystemSession session ) @@ -210,7 +210,7 @@ protected static boolean pluginEquals( Plugin a, Plugin b ) return CacheUtils.pluginEquals( a, b ); } - public void register( MavenProject project, CacheRecord record ) + public void register( MavenProject project, Key cacheKey, CacheRecord record ) { // default cache does not track record usage } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java index e459cbcab4..d8670369e0 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java @@ -206,7 +206,7 @@ protected static boolean pluginEquals( Plugin a, Plugin b ) return CacheUtils.pluginEquals( a, b ); } - public void register( MavenProject project, CacheRecord record ) + public void register( MavenProject project, Key key, CacheRecord record ) { // default cache does not track plugin usage } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java b/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java index 560e454da7..61d3058d0a 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/ExtensionRealmCache.java @@ -36,6 +36,13 @@ */ public interface ExtensionRealmCache { + /** + * A cache key. + */ + interface Key + { + // marker interface for cache keys + } static class CacheRecord { @@ -52,10 +59,11 @@ public CacheRecord( ClassRealm realm, ExtensionDescriptor descriptor ) } - CacheRecord get( List extensionArtifacts ); + Key createKey( List extensionArtifacts ); - CacheRecord put( List extensionArtifacts, ClassRealm extensionRealm, - ExtensionDescriptor extensionDescriptor ); + CacheRecord get( Key key ); + + CacheRecord put( Key key, ClassRealm extensionRealm, ExtensionDescriptor extensionDescriptor ); void flush(); @@ -67,6 +75,6 @@ CacheRecord put( List extensionArtifacts, ClassRealm extensi * @param project The project that employs the plugin realm, must not be {@code null}. * @param record The cache record being used for the project, must not be {@code null}. */ - void register( MavenProject project, CacheRecord record ); + void register( MavenProject project, Key key, CacheRecord record ); } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginArtifactsCache.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginArtifactsCache.java index fe0ef15f33..e4d256f9a2 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/PluginArtifactsCache.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginArtifactsCache.java @@ -86,6 +86,6 @@ Key createKey( Plugin plugin, DependencyFilter extensionFilter, List * @param project The project that employs the plugin realm, must not be {@code null}. * @param record The cache record being used for the project, must not be {@code null}. */ - void register( MavenProject project, CacheRecord record ); + void register( MavenProject project, Key key, CacheRecord record ); } 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 8c8f507463..90dd9ec88f 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 @@ -330,7 +330,7 @@ public synchronized void setupPluginRealm( PluginDescriptor pluginDescriptor, Ma pluginRealmCache.put( cacheKey, pluginDescriptor.getClassRealm(), pluginDescriptor.getArtifacts() ); } - pluginRealmCache.register( project, cacheRecord ); + pluginRealmCache.register( project, cacheKey, cacheRecord ); } private void createPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent, diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index 32786ae12b..8e1d51e75f 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -143,6 +143,7 @@ private ProjectBuildingResult build( File pomFile, ModelSource modelSource, Inte ModelBuildingRequest request = getModelBuildingRequest( config ); project = new MavenProject(); + project.setFile( pomFile ); DefaultModelBuildingListener listener = new DefaultModelBuildingListener( project, projectBuildingHelper, projectBuildingRequest ); diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java index 58a87fcdcb..fccdcfe789 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingHelper.java @@ -244,18 +244,20 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje { pluginArtifactsCache.put( cacheKey, e ); - pluginArtifactsCache.register( project, recordArtifacts ); + pluginArtifactsCache.register( project, cacheKey, recordArtifacts ); throw e; } } - pluginArtifactsCache.register( project, recordArtifacts ); + pluginArtifactsCache.register( project, cacheKey, recordArtifacts ); ClassRealm extensionRealm; ExtensionDescriptor extensionDescriptor = null; + + final ExtensionRealmCache.Key extensionKey = extensionRealmCache.createKey( artifacts ); - ExtensionRealmCache.CacheRecord recordRealm = extensionRealmCache.get( artifacts ); + ExtensionRealmCache.CacheRecord recordRealm = extensionRealmCache.get( extensionKey ); if ( recordRealm != null ) { @@ -295,10 +297,10 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje } } - recordRealm = extensionRealmCache.put( artifacts, extensionRealm, extensionDescriptor ); + recordRealm = extensionRealmCache.put( extensionKey, extensionRealm, extensionDescriptor ); } - extensionRealmCache.register( project, recordRealm ); + extensionRealmCache.register( project, extensionKey, recordRealm ); extensionRealms.add( extensionRealm ); if ( extensionDescriptor != null ) @@ -324,7 +326,9 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje logger.debug( "Extension realms for project " + model.getId() + ": " + extensionRealms ); } - ProjectRealmCache.CacheRecord record = projectRealmCache.get( extensionRealms ); + ProjectRealmCache.Key projectRealmKey = projectRealmCache.createKey( extensionRealms ); + + ProjectRealmCache.CacheRecord record = projectRealmCache.get( projectRealmKey ); if ( record == null ) { @@ -365,10 +369,10 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje extensionArtifactFilter = new ExclusionsDependencyFilter( exclusions ); } - record = projectRealmCache.put( extensionRealms, projectRealm, extensionArtifactFilter ); + record = projectRealmCache.put( projectRealmKey, projectRealm, extensionArtifactFilter ); } - projectRealmCache.register( project, record ); + projectRealmCache.register( project, projectRealmKey, record ); return record; } diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java index 1c5dfa3517..6ad8150d4d 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectRealmCache.java @@ -20,12 +20,14 @@ */ import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.classworlds.realm.NoSuchRealmException; import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable; import org.eclipse.aether.graph.DependencyFilter; /** @@ -33,10 +35,11 @@ */ @Component( role = ProjectRealmCache.class ) public class DefaultProjectRealmCache - implements ProjectRealmCache + implements ProjectRealmCache, Disposable { - private static class CacheKey + protected static class CacheKey + implements Key { private final List extensionRealms; @@ -74,28 +77,36 @@ public boolean equals( Object o ) return extensionRealms.equals( other.extensionRealms ); } + @Override + public String toString() + { + return extensionRealms.toString(); + } } - private final Map cache = new HashMap(); + protected final Map cache = new ConcurrentHashMap(); - public CacheRecord get( List extensionRealms ) + @Override + public Key createKey( List extensionRealms ) { - return cache.get( new CacheKey( extensionRealms ) ); + return new CacheKey( extensionRealms ); } - public CacheRecord put( List extensionRealms, ClassRealm projectRealm, - DependencyFilter extensionArtifactFilter ) + public CacheRecord get( Key key ) + { + return cache.get( key ); + } + + public CacheRecord put( Key key, ClassRealm projectRealm, DependencyFilter extensionArtifactFilter ) { if ( projectRealm == null ) { throw new NullPointerException(); } - CacheKey key = new CacheKey( extensionRealms ); - if ( cache.containsKey( key ) ) { - throw new IllegalStateException( "Duplicate project realm for extensions " + extensionRealms ); + throw new IllegalStateException( "Duplicate project realm for extensions " + key ); } CacheRecord record = new CacheRecord( projectRealm, extensionArtifactFilter ); @@ -107,12 +118,30 @@ public CacheRecord put( List extensionRealms, ClassRealm p public void flush() { + for ( CacheRecord record : cache.values() ) + { + ClassRealm realm = record.realm; + try + { + realm.getWorld().disposeRealm( realm.getId() ); + } + catch ( NoSuchRealmException e ) + { + // ignore + } + } cache.clear(); } - public void register( MavenProject project, CacheRecord record ) + public void register( MavenProject project, Key key, CacheRecord record ) { // default cache does not track record usage } + @Override + public void dispose() + { + flush(); + } + } diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java b/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java index 415eab996b..779d96b9e1 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectRealmCache.java @@ -35,6 +35,14 @@ public interface ProjectRealmCache { + /** + * A cache key. + */ + interface Key + { + // marker interface for cache keys + } + static class CacheRecord { @@ -50,10 +58,11 @@ public CacheRecord( ClassRealm realm, DependencyFilter extensionArtifactFilter ) } - CacheRecord get( List extensionRealms ); + Key createKey( List extensionRealms ); - CacheRecord put( List extensionRealms, ClassRealm projectRealm, - DependencyFilter extensionArtifactFilter ); + CacheRecord get( Key key ); + + CacheRecord put( Key key, ClassRealm projectRealm, DependencyFilter extensionArtifactFilter ); void flush(); @@ -65,6 +74,6 @@ CacheRecord put( List extensionRealms, ClassRealm projectR * @param project The project that employs the plugin realm, must not be {@code null}. * @param record The cache record being used for the project, must not be {@code null}. */ - void register( MavenProject project, CacheRecord record ); + void register( MavenProject project, Key key, CacheRecord record ); }