Add a ProjectArtifactsCache similar to PluginArtifactsCache Signed-off-by: Jason van Zyl <ja...@vanzyl.ca>
closes #82 Project: http://git-wip-us.apache.org/repos/asf/maven/repo Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/bf05ee15 Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/bf05ee15 Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/bf05ee15 Branch: refs/heads/MNG-6169_2/not-updated-MJAR-MCOMPILER Commit: bf05ee15c5fb2f6d77f074113e807924b72231c8 Parents: b9d46b5 Author: Anton Tanasenko <atg.sleepl...@gmail.com> Authored: Wed May 18 18:40:28 2016 +0300 Committer: Michael Osipov <micha...@apache.org> Committed: Fri May 12 21:46:08 2017 +0200 ---------------------------------------------------------------------- .../internal/LifecycleDependencyResolver.java | 34 ++- .../plugin/DefaultProjectArtifactsCache.java | 256 +++++++++++++++++++ .../maven/plugin/ProjectArtifactsCache.java | 90 +++++++ 3 files changed, 377 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven/blob/bf05ee15/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java ---------------------------------------------------------------------- diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java index 0d42aeb..504274f 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java @@ -37,6 +37,7 @@ import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.execution.MavenSession; import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.plugin.ProjectArtifactsCache; import org.apache.maven.project.DefaultDependencyResolutionRequest; import org.apache.maven.project.DependencyResolutionException; import org.apache.maven.project.DependencyResolutionResult; @@ -75,6 +76,9 @@ public class LifecycleDependencyResolver @Inject private EventSpyDispatcher eventSpyDispatcher; + + @Inject + private ProjectArtifactsCache projectArtifactsCache; public LifecycleDependencyResolver() { @@ -123,9 +127,33 @@ public class LifecycleDependencyResolver throw new LifecycleExecutionException( e ); } } - - Set<Artifact> artifacts = - getDependencies( project, scopesToCollect, scopesToResolve, session, aggregating, projectArtifacts ); + + Set<Artifact> artifacts; + ProjectArtifactsCache.Key cacheKey = projectArtifactsCache.createKey( project, scopesToCollect, + scopesToResolve, aggregating, session.getRepositorySession() ); + ProjectArtifactsCache.CacheRecord recordArtifacts; + recordArtifacts = projectArtifactsCache.get( cacheKey ); + + if ( recordArtifacts != null ) + { + artifacts = recordArtifacts.artifacts; + } + else + { + try + { + artifacts = getDependencies( project, scopesToCollect, scopesToResolve, session, aggregating, + projectArtifacts ); + recordArtifacts = projectArtifactsCache.put( cacheKey, artifacts ); + } + catch ( LifecycleExecutionException e ) + { + projectArtifactsCache.put( cacheKey, e ); + projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + throw e; + } + } + projectArtifactsCache.register( project, cacheKey, recordArtifacts ); project.setResolvedArtifacts( artifacts ); http://git-wip-us.apache.org/repos/asf/maven/blob/bf05ee15/maven-core/src/main/java/org/apache/maven/plugin/DefaultProjectArtifactsCache.java ---------------------------------------------------------------------- diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultProjectArtifactsCache.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultProjectArtifactsCache.java new file mode 100644 index 0000000..1eaa627 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultProjectArtifactsCache.java @@ -0,0 +1,256 @@ +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.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.lang3.Validate; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.Plugin; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.annotations.Component; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.WorkspaceRepository; + +/** + * @author Igor Fedorenko + * @author Benjamin Bentmann + * @author Anton Tanasenko + */ +@Component( role = ProjectArtifactsCache.class ) +public class DefaultProjectArtifactsCache + implements ProjectArtifactsCache +{ + + protected static class CacheKey + implements Key + { + + private final String groupId; + + private final String artifactId; + + private final String version; + + private final Set<String> dependencyArtifacts; + + private final WorkspaceRepository workspace; + + private final LocalRepository localRepo; + + private final List<RemoteRepository> repositories; + + private final Set<String> collect; + + private final Set<String> resolve; + + private boolean aggregating; + + private final int hashCode; + + public CacheKey( MavenProject project, List<RemoteRepository> repositories, + Collection<String> scopesToCollect, Collection<String> scopesToResolve, boolean aggregating, + RepositorySystemSession session ) + { + + groupId = project.getGroupId(); + artifactId = project.getArtifactId(); + version = project.getVersion(); + + Set<String> deps = new HashSet<>(); + if ( project.getDependencyArtifacts() != null ) + { + for ( Artifact dep: project.getDependencyArtifacts() ) + { + deps.add( dep.toString() ); + } + } + dependencyArtifacts = Collections.unmodifiableSet( deps ); + + workspace = CacheUtils.getWorkspace( session ); + this.localRepo = session.getLocalRepository(); + this.repositories = new ArrayList<>( repositories.size() ); + for ( RemoteRepository repository : repositories ) + { + if ( repository.isRepositoryManager() ) + { + this.repositories.addAll( repository.getMirroredRepositories() ); + } + else + { + this.repositories.add( repository ); + } + } + collect = scopesToCollect == null + ? Collections.<String>emptySet() + : Collections.unmodifiableSet( new HashSet<>( scopesToCollect ) ); + resolve = scopesToResolve == null + ? Collections.<String>emptySet() + : Collections.unmodifiableSet( new HashSet<>( scopesToResolve ) ); + this.aggregating = aggregating; + + int hash = 17; + hash = hash * 31 + hash( groupId ); + hash = hash * 31 + hash( artifactId ); + hash = hash * 31 + hash( version ); + hash = hash * 31 + hash( dependencyArtifacts ); + hash = hash * 31 + hash( workspace ); + hash = hash * 31 + hash( localRepo ); + hash = hash * 31 + CacheUtils.repositoriesHashCode( repositories ); + hash = hash * 31 + hash( collect ); + hash = hash * 31 + hash( resolve ); + hash = hash * 31 + hash( aggregating ); + this.hashCode = hash; + } + + @Override + public String toString() + { + return groupId + ":" + artifactId + ":" + version; + } + + @Override + public int hashCode() + { + return hashCode; + } + + private static int hash( Object obj ) + { + return obj != null ? obj.hashCode() : 0; + } + + @Override + public boolean equals( Object o ) + { + if ( o == this ) + { + return true; + } + + if ( !( o instanceof CacheKey ) ) + { + return false; + } + + CacheKey that = (CacheKey) o; + + return eq( groupId, that.groupId ) && eq( artifactId, that.artifactId ) && eq( version, that.version ) + && eq( dependencyArtifacts, that.dependencyArtifacts ) + && eq( workspace, that.workspace ) && eq( localRepo, that.localRepo ) + && CacheUtils.repositoriesEquals( repositories, that.repositories ) && eq( collect, that.collect ) + && eq( resolve, that.resolve ) && aggregating == that.aggregating; + } + + private static <T> boolean eq( T s1, T s2 ) + { + return s1 != null ? s1.equals( s2 ) : s2 == null; + } + + } + + protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>(); + + public Key createKey( MavenProject project, Collection<String> scopesToCollect, + Collection<String> scopesToResolve, boolean aggregating, RepositorySystemSession session ) + { + return new CacheKey( project, project.getRemoteProjectRepositories(), scopesToCollect, scopesToResolve, + aggregating, session ); + } + + public CacheRecord get( Key key ) + throws LifecycleExecutionException + { + CacheRecord cacheRecord = cache.get( key ); + + if ( cacheRecord != null && cacheRecord.exception != null ) + { + throw cacheRecord.exception; + } + + return cacheRecord; + } + + public CacheRecord put( Key key, Set<Artifact> projectArtifacts ) + { + Validate.notNull( projectArtifacts, "projectArtifacts cannot be null" ); + + assertUniqueKey( key ); + + CacheRecord record = + new CacheRecord( Collections.unmodifiableSet( new HashSet<>( projectArtifacts ) ) ); + + cache.put( key, record ); + + return record; + } + + protected void assertUniqueKey( Key key ) + { + if ( cache.containsKey( key ) ) + { + throw new IllegalStateException( "Duplicate artifact resolution result for project " + key ); + } + } + + public CacheRecord put( Key key, LifecycleExecutionException exception ) + { + Validate.notNull( exception, "exception cannot be null" ); + + assertUniqueKey( key ); + + CacheRecord record = new CacheRecord( exception ); + + cache.put( key, record ); + + return record; + } + + public void flush() + { + cache.clear(); + } + + protected static int pluginHashCode( Plugin plugin ) + { + return CacheUtils.pluginHashCode( plugin ); + } + + protected static boolean pluginEquals( Plugin a, Plugin b ) + { + return CacheUtils.pluginEquals( a, b ); + } + + public void register( MavenProject project, Key cacheKey, CacheRecord record ) + { + // default cache does not track record usage + } + +} http://git-wip-us.apache.org/repos/asf/maven/blob/bf05ee15/maven-core/src/main/java/org/apache/maven/plugin/ProjectArtifactsCache.java ---------------------------------------------------------------------- diff --git a/maven-core/src/main/java/org/apache/maven/plugin/ProjectArtifactsCache.java b/maven-core/src/main/java/org/apache/maven/plugin/ProjectArtifactsCache.java new file mode 100644 index 0000000..42a95e5 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/ProjectArtifactsCache.java @@ -0,0 +1,90 @@ +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.Collection; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.project.MavenProject; +import org.eclipse.aether.RepositorySystemSession; +/** + * Caches project artifacts. <strong>Warning:</strong> This is an internal utility interface that is only public for + * technical reasons, it is not part of the public API. In particular, this interface can be changed or deleted without + * prior notice. + * + * @author Igor Fedorenko + * @author Benjamin Bentmann + * @author Anton Tanasenko + */ +public interface ProjectArtifactsCache +{ + + /** + * A cache key. + */ + interface Key + { + // marker interface for cache keys + } + + static class CacheRecord + { + + public final Set<Artifact> artifacts; + + public final LifecycleExecutionException exception; + + public CacheRecord( Set<Artifact> artifacts ) + { + this.artifacts = artifacts; + this.exception = null; + } + + public CacheRecord( LifecycleExecutionException exception ) + { + this.artifacts = null; + this.exception = exception; + } + } + + Key createKey( MavenProject project, Collection<String> scopesToCollect, Collection<String> scopesToResolve, + boolean aggregating, RepositorySystemSession session ); + + CacheRecord get( Key key ) throws LifecycleExecutionException; + + CacheRecord put( Key key, Set<Artifact> pluginArtifacts ); + + CacheRecord put( Key key, LifecycleExecutionException e ); + + void flush(); + + /** + * Registers the specified cache record for usage with the given project. Integrators can use the information + * collected from this method in combination with a custom cache implementation to dispose unused records from the + * cache. + * + * @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, Key cacheKey, CacheRecord record ); + +}