1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.project.artifact;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.LinkedHashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Set;
33 import java.util.concurrent.ConcurrentHashMap;
34
35 import org.apache.maven.RepositoryUtils;
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.lifecycle.LifecycleExecutionException;
38 import org.apache.maven.lifecycle.internal.SetWithResolutionResult;
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
47 @Named
48 @Singleton
49 public class DefaultProjectArtifactsCache implements ProjectArtifactsCache {
50
51
52
53 protected static class CacheKey implements Key {
54
55 private final String groupId;
56
57 private final String artifactId;
58
59 private final String version;
60
61 private final Set<String> dependencyArtifacts;
62
63 private final WorkspaceRepository workspace;
64
65 private final LocalRepository localRepo;
66
67 private final List<RemoteRepository> repositories;
68
69 private final Set<String> collect;
70
71 private final Set<String> resolve;
72
73 private boolean aggregating;
74
75 private final int hashCode;
76
77 public CacheKey(
78 MavenProject project,
79 List<RemoteRepository> repositories,
80 Collection<String> scopesToCollect,
81 Collection<String> scopesToResolve,
82 boolean aggregating,
83 RepositorySystemSession session) {
84
85 groupId = project.getGroupId();
86 artifactId = project.getArtifactId();
87 version = project.getVersion();
88
89 Set<String> deps = new LinkedHashSet<>();
90 if (project.getDependencyArtifacts() != null) {
91 for (Artifact dep : project.getDependencyArtifacts()) {
92 deps.add(dep.toString());
93 }
94 }
95 dependencyArtifacts = Collections.unmodifiableSet(deps);
96
97 workspace = RepositoryUtils.getWorkspace(session);
98 this.localRepo = session.getLocalRepository();
99 this.repositories = new ArrayList<>(repositories.size());
100 for (RemoteRepository repository : repositories) {
101 if (repository.isRepositoryManager()) {
102 this.repositories.addAll(repository.getMirroredRepositories());
103 } else {
104 this.repositories.add(repository);
105 }
106 }
107 collect = scopesToCollect == null
108 ? Collections.emptySet()
109 : Collections.unmodifiableSet(new HashSet<>(scopesToCollect));
110 resolve = scopesToResolve == null
111 ? Collections.emptySet()
112 : Collections.unmodifiableSet(new HashSet<>(scopesToResolve));
113 this.aggregating = aggregating;
114
115 int hash = 17;
116 hash = hash * 31 + Objects.hashCode(groupId);
117 hash = hash * 31 + Objects.hashCode(artifactId);
118 hash = hash * 31 + Objects.hashCode(version);
119 hash = hash * 31 + Objects.hashCode(dependencyArtifacts);
120 hash = hash * 31 + Objects.hashCode(workspace);
121 hash = hash * 31 + Objects.hashCode(localRepo);
122 hash = hash * 31 + RepositoryUtils.repositoriesHashCode(repositories);
123 hash = hash * 31 + Objects.hashCode(collect);
124 hash = hash * 31 + Objects.hashCode(resolve);
125 hash = hash * 31 + Objects.hashCode(aggregating);
126 this.hashCode = hash;
127 }
128
129 @Override
130 public String toString() {
131 return groupId + ":" + artifactId + ":" + version;
132 }
133
134 @Override
135 public int hashCode() {
136 return hashCode;
137 }
138
139 @Override
140 public boolean equals(Object o) {
141 if (o == this) {
142 return true;
143 }
144 if (!(o instanceof CacheKey)) {
145 return false;
146 }
147 CacheKey that = (CacheKey) o;
148 return Objects.equals(groupId, that.groupId)
149 && Objects.equals(artifactId, that.artifactId)
150 && Objects.equals(version, that.version)
151 && Objects.equals(dependencyArtifacts, that.dependencyArtifacts)
152 && Objects.equals(workspace, that.workspace)
153 && Objects.equals(localRepo, that.localRepo)
154 && RepositoryUtils.repositoriesEquals(repositories, that.repositories)
155 && Objects.equals(collect, that.collect)
156 && Objects.equals(resolve, that.resolve)
157 && aggregating == that.aggregating;
158 }
159 }
160
161 protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();
162 protected final Map<Key, Key> keys = new ConcurrentHashMap<>();
163
164 @Override
165 public Key createKey(
166 MavenProject project,
167 Collection<String> scopesToCollect,
168 Collection<String> scopesToResolve,
169 boolean aggregating,
170 RepositorySystemSession session) {
171 Key key = new CacheKey(
172 project,
173 project.getRemoteProjectRepositories(),
174 scopesToCollect,
175 scopesToResolve,
176 aggregating,
177 session);
178 return keys.computeIfAbsent(key, k -> k);
179 }
180
181 @Override
182 public CacheRecord get(Key key) throws LifecycleExecutionException {
183 CacheRecord cacheRecord = cache.get(key);
184 if (cacheRecord != null && cacheRecord.getException() != null) {
185 throw cacheRecord.getException();
186 }
187 return cacheRecord;
188 }
189
190 @Override
191 public CacheRecord put(Key key, Set<Artifact> projectArtifacts) {
192 Objects.requireNonNull(projectArtifacts, "projectArtifacts cannot be null");
193 assertUniqueKey(key);
194
195 SetWithResolutionResult artifacts;
196 if (projectArtifacts instanceof SetWithResolutionResult) {
197 artifacts = (SetWithResolutionResult) projectArtifacts;
198 } else if (projectArtifacts instanceof ArtifactsSetWithResult) {
199 artifacts = new SetWithResolutionResult(
200 ((ArtifactsSetWithResult) projectArtifacts).getResult(), projectArtifacts);
201 } else {
202 throw new IllegalArgumentException("projectArtifacts must implement ArtifactsSetWithResult");
203 }
204
205 CacheRecord record = new CacheRecord(artifacts);
206 cache.put(key, record);
207 return record;
208 }
209
210 @Override
211 public CacheRecord put(Key key, LifecycleExecutionException exception) {
212 Objects.requireNonNull(exception, "exception cannot be null");
213 assertUniqueKey(key);
214 CacheRecord record = new CacheRecord(exception);
215 cache.put(key, record);
216 return record;
217 }
218
219 protected void assertUniqueKey(Key key) {
220 if (cache.containsKey(key)) {
221 throw new IllegalStateException("Duplicate artifact resolution result for project " + key);
222 }
223 }
224
225 @Override
226 public void flush() {
227 cache.clear();
228 }
229
230 @Override
231 public void register(MavenProject project, Key cacheKey, CacheRecord record) {
232
233 }
234 }