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