diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginCache.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginCache.java new file mode 100644 index 0000000000..096e3b0e05 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginCache.java @@ -0,0 +1,309 @@ +package org.apache.maven.plugin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Exclusion; +import org.apache.maven.model.ModelUtils; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginExecution; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.component.annotations.Component; + +/** + * Default PluginCache implementation. Assumes cached data does not change. + */ +@Component( role = PluginCache.class ) +public class DefaultPluginCache + implements PluginCache +{ + + private static class CacheKey + { + private final Plugin plugin; + + private final List repositories = new ArrayList(); + + private final int hashCode; + + public CacheKey( Plugin plugin, ArtifactRepository localRepository, List remoteRepositories ) + { + this.plugin = ModelUtils.clonePlugin( plugin ); + this.repositories.add( localRepository ); + this.repositories.addAll( remoteRepositories ); + + int hash = 17; + hash = hash * 31 + pluginHashCode( plugin ); + hash = hash * 31 + repositories.hashCode(); + this.hashCode = hash; + } + + @Override + public int hashCode() + { + return hashCode; + } + + @Override + public boolean equals( Object o ) + { + if ( o == this ) + { + return true; + } + + if ( !( o instanceof CacheKey ) ) + { + return false; + } + + CacheKey other = (CacheKey) o; + + return pluginEquals( plugin, other.plugin ); + } + } + + private final Map descriptorsCache = new HashMap(); + + private final Map cache = new HashMap(); + + public CacheRecord get( Plugin plugin, ArtifactRepository localRepository, + List remoteRepositories ) + { + return cache.get( new CacheKey( plugin, localRepository, remoteRepositories ) ); + } + + public PluginDescriptor getPluginDescriptor( Plugin plugin, ArtifactRepository localRepository, + List remoteRepositories ) + { + return clone( descriptorsCache.get( new CacheKey( plugin, localRepository, remoteRepositories ) ) ); + } + + protected static PluginDescriptor clone( PluginDescriptor original ) + { + if ( original == null ) + { + return null; + } + + PluginDescriptor cloned = new PluginDescriptor(); + cloned.setGroupId( original.getGroupId() ); + cloned.setArtifactId( original.getArtifactId() ); + cloned.setVersion( original.getVersion() ); + cloned.setGoalPrefix( original.getGoalPrefix() ); + cloned.setSource( original.getSource() ); + cloned.setInheritedByDefault( original.isInheritedByDefault() ); + + cloned.setIntroducedDependencyArtifacts( original.getIntroducedDependencyArtifacts() ); // TODO do we need to clone this? + cloned.setName( original.getName() ); + cloned.setDescription( original.getDescription() ); + cloned.setPlugin( ModelUtils.clonePlugin( original.getPlugin() ) ); // TODO not sure I need to clone here + cloned.setPluginArtifact( original.getPluginArtifact() ); + + cloned.setId( original.getId() ); + cloned.setIsolatedRealm( original.isIsolatedRealm() ); + cloned.setComponents( original.getComponents() ); + cloned.setDependencies( original.getDependencies() ); + + return cloned; + } + + public void put( Plugin plugin, ArtifactRepository localRepository, List remoteRepositories, + ClassRealm pluginRealm, List pluginArtifacts ) + { + if ( pluginRealm == null || pluginArtifacts == null ) + { + throw new NullPointerException(); + } + + CacheKey key = new CacheKey( plugin, localRepository, remoteRepositories ); + CacheRecord record = new CacheRecord( pluginRealm, pluginArtifacts ); + cache.put( key, record ); + } + + public void putPluginDescriptor( Plugin plugin, ArtifactRepository localRepository, + List remoteRepositories, PluginDescriptor pluginDescriptor ) + { + CacheKey key = new CacheKey( plugin, localRepository, remoteRepositories ); + descriptorsCache.put( key, clone( pluginDescriptor ) ); + } + + public void flush() + { + cache.clear(); + descriptorsCache.clear(); + } + + protected static int pluginHashCode( Plugin plugin ) + { + int hash = 17; + + hash = hash * 31 + plugin.getGroupId().hashCode(); + hash = hash * 31 + plugin.getArtifactId().hashCode(); + hash = hash * 31 + plugin.getVersion().hashCode(); + + hash = hash * 31 + ( plugin.isExtensions() ? 1 : 0 ); + + for ( Dependency dependency : plugin.getDependencies() ) + { + hash = hash * 31 + dependency.getGroupId().hashCode(); + hash = hash * 31 + dependency.getArtifactId().hashCode(); + hash = hash * 31 + dependency.getVersion().hashCode(); + hash = hash * 31 + dependency.getType().hashCode(); + hash = hash * 31 + ( dependency.getClassifier() != null ? dependency.getClassifier().hashCode() : 0 ); + hash = hash * 31 + ( dependency.getScope() != null ? dependency.getScope().hashCode() : 0 ); + + for ( Exclusion exclusion : dependency.getExclusions() ) + { + hash = hash * 31 + exclusion.getGroupId().hashCode(); + hash = hash * 31 + exclusion.getArtifactId().hashCode(); + } + } + + /* + * Must consider executions because each execution ends up as separate plexus component, with its own + * configuration, etc. + */ + for ( PluginExecution execution : plugin.getExecutions() ) + { + hash = hash * 31 + execution.getId().hashCode(); + hash = hash * 31 + ( execution.getInherited() != null ? execution.getInherited().hashCode() : 0 ); + hash = hash * 31 + ( execution.getPhase() != null ? execution.getPhase().hashCode() : 0); + hash = hash * 31 + ( execution.getConfiguration() != null ? execution.getConfiguration().hashCode() : 0 ); + hash = hash * 31 + execution.getGoals().hashCode(); + } + + return hash; + } + + protected static boolean pluginEquals( Plugin a, Plugin b ) + { + return eq( a.getGroupId(), b.getGroupId() ) // + && eq( a.getArtifactId(), b.getArtifactId() ) // + && eq( a.getVersion(), b.getVersion() ) // + && a.isExtensions() == b.isExtensions() // + && pluginExecutionsEquals( a.getExecutions(), b.getExecutions() ) // + && dependenciesEquals( a.getDependencies(), b.getDependencies() ); + } + + protected static boolean pluginExecutionsEquals( List a, List b ) + { + if ( a.size() != b.size() ) + { + return false; + } + + Iterator aI = a.iterator(); + Iterator bI = b.iterator(); + + while ( aI.hasNext() ) + { + PluginExecution aD = aI.next(); + PluginExecution bD = bI.next(); + + boolean r = eq( aD.getId(), bD.getId() ) // + && eq( aD.getInherited(), bD.getInherited() ) // + && eq( aD.getPhase(), bD.getPhase() ) // + && eq( aD.getConfiguration(), bD.getConfiguration() ) // + && eq( aD.getGoals(), bD.getGoals() ); + + if ( !r ) + { + return false; + } + } + + return true; + } + + private static boolean dependenciesEquals( List a, List b ) + { + if ( a.size() != b.size() ) + { + return false; + } + + Iterator aI = a.iterator(); + Iterator bI = b.iterator(); + + while ( aI.hasNext() ) + { + Dependency aD = aI.next(); + Dependency bD = bI.next(); + + boolean r = eq( aD.getGroupId(), bD.getGroupId() ) // + && eq( aD.getArtifactId(), bD.getArtifactId() ) // + && eq( aD.getVersion(), bD.getVersion() ) // + && eq( aD.getType(), bD.getType() ) // + && eq( aD.getClassifier(), bD.getScope() ); + + r &= exclusionsEquals( aD.getExclusions(), bD.getExclusions() ); + + if ( !r ) + { + return false; + } + } + + return true; + } + + private static boolean exclusionsEquals( List a, List b ) + { + if ( a.size() != b.size() ) + { + return false; + } + + Iterator aI = a.iterator(); + Iterator bI = b.iterator(); + + while ( aI.hasNext() ) + { + Exclusion aD = aI.next(); + Exclusion bD = bI.next(); + + boolean r = eq( aD.getGroupId(), bD.getGroupId() ) // + && eq( aD.getArtifactId(), bD.getArtifactId() ); + + if ( !r ) + { + return false; + } + } + + return true; + } + + private static boolean eq( T s1, T s2 ) + { + return s1 != null ? s1.equals( s2 ) : s2 == null; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginCache.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginCache.java new file mode 100644 index 0000000000..e940a155be --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginCache.java @@ -0,0 +1,38 @@ +package org.apache.maven.plugin; + +import java.util.List; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.codehaus.plexus.classworlds.realm.ClassRealm; + +public interface PluginCache +{ + + public static class CacheRecord + { + public final ClassRealm realm; + public final List artifacts; + + public CacheRecord( ClassRealm realm, List artifacts ) + { + this.realm = realm; + this.artifacts = artifacts; + } + } + + PluginDescriptor getPluginDescriptor( Plugin plugin, ArtifactRepository localRepository, + List remoteRepositories ); + + void putPluginDescriptor( Plugin plugin, ArtifactRepository localRepository, + List remoteRepositories, PluginDescriptor pluginDescriptor ); + + CacheRecord get( Plugin plugin, ArtifactRepository localRepository, List remoteRepositories ); + + void put( Plugin plugin, ArtifactRepository localRepository, List remoteRepositories, + ClassRealm pluginRealm, List pluginArtifacts ); + + void flush(); +}