View Javadoc
1   package org.apache.maven.project.artifact;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashSet;
26  import java.util.LinkedHashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Objects;
30  import java.util.Set;
31  import java.util.concurrent.ConcurrentHashMap;
32  
33  import javax.inject.Named;
34  import javax.inject.Singleton;
35  
36  import org.apache.maven.RepositoryUtils;
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.lifecycle.LifecycleExecutionException;
39  import org.apache.maven.project.MavenProject;
40  import org.eclipse.aether.RepositorySystemSession;
41  import org.eclipse.aether.repository.LocalRepository;
42  import org.eclipse.aether.repository.RemoteRepository;
43  import org.eclipse.aether.repository.WorkspaceRepository;
44  
45  /**
46   * @author Igor Fedorenko
47   * @author Benjamin Bentmann
48   * @author Anton Tanasenko
49   */
50  @Named
51  @Singleton
52  public class DefaultProjectArtifactsCache
53      implements ProjectArtifactsCache
54  {
55      /**
56       * CacheKey
57       */
58      protected static class CacheKey
59          implements Key
60      {
61  
62          private final String groupId;
63  
64          private final String artifactId;
65  
66          private final String version;
67  
68          private final Set<String> dependencyArtifacts;
69  
70          private final WorkspaceRepository workspace;
71  
72          private final LocalRepository localRepo;
73  
74          private final List<RemoteRepository> repositories;
75  
76          private final Set<String> collect;
77  
78          private final Set<String> resolve;
79  
80          private boolean aggregating;
81  
82          private final int hashCode;
83  
84          public CacheKey( MavenProject project, List<RemoteRepository> repositories,
85              Collection<String> scopesToCollect, Collection<String> scopesToResolve, boolean aggregating,
86              RepositorySystemSession session )
87          {
88  
89              groupId = project.getGroupId();
90              artifactId = project.getArtifactId();
91              version = project.getVersion();
92  
93              Set<String> deps = new LinkedHashSet<>();
94              if ( project.getDependencyArtifacts() != null )
95              {
96                for ( Artifact dep: project.getDependencyArtifacts() )
97                {
98                  deps.add( dep.toString() );
99                }
100             }
101             dependencyArtifacts = Collections.unmodifiableSet( deps );
102 
103             workspace = RepositoryUtils.getWorkspace( session );
104             this.localRepo = session.getLocalRepository();
105             this.repositories = new ArrayList<>( repositories.size() );
106             for ( RemoteRepository repository : repositories )
107             {
108                 if ( repository.isRepositoryManager() )
109                 {
110                     this.repositories.addAll( repository.getMirroredRepositories() );
111                 }
112                 else
113                 {
114                     this.repositories.add( repository );
115                 }
116             }
117             collect = scopesToCollect == null
118                 ? Collections.emptySet()
119                 : Collections.unmodifiableSet( new HashSet<>( scopesToCollect ) );
120             resolve = scopesToResolve == null
121                 ? Collections.emptySet()
122                 : Collections.unmodifiableSet( new HashSet<>( scopesToResolve ) );
123             this.aggregating = aggregating;
124 
125             int hash = 17;
126             hash = hash * 31 + Objects.hashCode( groupId );
127             hash = hash * 31 + Objects.hashCode( artifactId );
128             hash = hash * 31 + Objects.hashCode( version );
129             hash = hash * 31 + Objects.hashCode( dependencyArtifacts );
130             hash = hash * 31 + Objects.hashCode( workspace );
131             hash = hash * 31 + Objects.hashCode( localRepo );
132             hash = hash * 31 + RepositoryUtils.repositoriesHashCode( repositories );
133             hash = hash * 31 + Objects.hashCode( collect );
134             hash = hash * 31 + Objects.hashCode( resolve );
135             hash = hash * 31 + Objects.hashCode( aggregating );
136             this.hashCode = hash;
137         }
138 
139         @Override
140         public String toString()
141         {
142             return groupId + ":" + artifactId + ":" + version;
143         }
144 
145         @Override
146         public int hashCode()
147         {
148             return hashCode;
149         }
150 
151         @Override
152         public boolean equals( Object o )
153         {
154             if ( o == this )
155             {
156                 return true;
157             }
158 
159             if ( !( o instanceof CacheKey ) )
160             {
161                 return false;
162             }
163 
164             CacheKey that = (CacheKey) o;
165 
166             return Objects.equals( groupId, that.groupId ) && Objects.equals( artifactId, that.artifactId )
167                 && Objects.equals( version, that.version )
168                 && Objects.equals( dependencyArtifacts, that.dependencyArtifacts )
169                 && Objects.equals( workspace, that.workspace )
170                 && Objects.equals( localRepo, that.localRepo )
171                 && RepositoryUtils.repositoriesEquals( repositories, that.repositories )
172                 && Objects.equals( collect, that.collect )
173                 && Objects.equals( resolve, that.resolve )
174                 && aggregating == that.aggregating;
175         }
176     }
177 
178     protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();
179 
180     @Override
181     public Key createKey( MavenProject project, Collection<String> scopesToCollect,
182         Collection<String> scopesToResolve, boolean aggregating, RepositorySystemSession session )
183     {
184         return new CacheKey( project, project.getRemoteProjectRepositories(), scopesToCollect, scopesToResolve,
185             aggregating, session );
186     }
187 
188     @Override
189     public CacheRecord get( Key key )
190         throws LifecycleExecutionException
191     {
192         CacheRecord cacheRecord = cache.get( key );
193 
194         if ( cacheRecord != null && cacheRecord.getException() != null )
195         {
196             throw cacheRecord.getException();
197         }
198 
199         return cacheRecord;
200     }
201 
202     @Override
203     public CacheRecord put( Key key, Set<Artifact> projectArtifacts )
204     {
205         Objects.requireNonNull( projectArtifacts, "projectArtifacts cannot be null" );
206 
207         assertUniqueKey( key );
208 
209         CacheRecord record =
210             new CacheRecord( Collections.unmodifiableSet( new LinkedHashSet<>( projectArtifacts ) ) );
211 
212         cache.put( key, record );
213 
214         return record;
215     }
216 
217     protected void assertUniqueKey( Key key )
218     {
219         if ( cache.containsKey( key ) )
220         {
221             throw new IllegalStateException( "Duplicate artifact resolution result for project " + key );
222         }
223     }
224 
225     @Override
226     public CacheRecord put( Key key, LifecycleExecutionException exception )
227     {
228         Objects.requireNonNull( exception, "exception cannot be null" );
229 
230         assertUniqueKey( key );
231 
232         CacheRecord record = new CacheRecord( exception );
233 
234         cache.put( key, record );
235 
236         return record;
237     }
238 
239     @Override
240     public void flush()
241     {
242         cache.clear();
243     }
244 
245     @Override
246     public void register( MavenProject project, Key cacheKey, CacheRecord record )
247     {
248         // default cache does not track record usage
249     }
250 
251 }