1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl.collect;
20
21 import java.lang.ref.WeakReference;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.WeakHashMap;
29 import java.util.concurrent.ConcurrentHashMap;
30
31 import org.eclipse.aether.RepositoryCache;
32 import org.eclipse.aether.RepositorySystemSession;
33 import org.eclipse.aether.artifact.Artifact;
34 import org.eclipse.aether.collection.DependencyManager;
35 import org.eclipse.aether.collection.DependencySelector;
36 import org.eclipse.aether.collection.DependencyTraverser;
37 import org.eclipse.aether.collection.VersionFilter;
38 import org.eclipse.aether.graph.Dependency;
39 import org.eclipse.aether.graph.DependencyNode;
40 import org.eclipse.aether.repository.ArtifactRepository;
41 import org.eclipse.aether.repository.RemoteRepository;
42 import org.eclipse.aether.resolution.ArtifactDescriptorException;
43 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
44 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
45 import org.eclipse.aether.resolution.VersionRangeRequest;
46 import org.eclipse.aether.resolution.VersionRangeResult;
47 import org.eclipse.aether.util.ConfigUtils;
48 import org.eclipse.aether.version.Version;
49 import org.eclipse.aether.version.VersionConstraint;
50
51
52
53
54 public final class DataPool {
55 private static final String CONFIG_PROP_COLLECTOR_POOL_ARTIFACT = "aether.dependencyCollector.pool.artifact";
56
57 private static final String CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY = "aether.dependencyCollector.pool.dependency";
58
59 private static final String CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR = "aether.dependencyCollector.pool.descriptor";
60
61 private static final String ARTIFACT_POOL = DataPool.class.getName() + "$Artifact";
62
63 private static final String DEPENDENCY_POOL = DataPool.class.getName() + "$Dependency";
64
65 private static final String DESCRIPTORS = DataPool.class.getName() + "$Descriptors";
66
67 public static final ArtifactDescriptorResult NO_DESCRIPTOR =
68 new ArtifactDescriptorResult(new ArtifactDescriptorRequest());
69
70
71
72
73 private final InternPool<Artifact, Artifact> artifacts;
74
75
76
77
78 private final InternPool<Dependency, Dependency> dependencies;
79
80
81
82
83 private final InternPool<Object, Descriptor> descriptors;
84
85
86
87
88 private final ConcurrentHashMap<Object, Constraint> constraints;
89
90
91
92
93 private final ConcurrentHashMap<Object, List<DependencyNode>> nodes;
94
95 @SuppressWarnings("unchecked")
96 public DataPool(RepositorySystemSession session) {
97 final RepositoryCache cache = session.getCache();
98
99 InternPool<Artifact, Artifact> artifactsPool = null;
100 InternPool<Dependency, Dependency> dependenciesPool = null;
101 InternPool<Object, Descriptor> descriptorsPool = null;
102 if (cache != null) {
103 artifactsPool = (InternPool<Artifact, Artifact>) cache.get(session, ARTIFACT_POOL);
104 dependenciesPool = (InternPool<Dependency, Dependency>) cache.get(session, DEPENDENCY_POOL);
105 descriptorsPool = (InternPool<Object, Descriptor>) cache.get(session, DESCRIPTORS);
106 }
107
108 if (artifactsPool == null) {
109 String artifactPoolType = ConfigUtils.getString(session, WEAK, CONFIG_PROP_COLLECTOR_POOL_ARTIFACT);
110
111 artifactsPool = createPool(artifactPoolType);
112 if (cache != null) {
113 cache.put(session, ARTIFACT_POOL, artifactsPool);
114 }
115 }
116
117 if (dependenciesPool == null) {
118 String dependencyPoolType = ConfigUtils.getString(session, WEAK, CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY);
119
120 dependenciesPool = createPool(dependencyPoolType);
121 if (cache != null) {
122 cache.put(session, DEPENDENCY_POOL, dependenciesPool);
123 }
124 }
125
126 if (descriptorsPool == null) {
127 String descriptorPoolType = ConfigUtils.getString(session, HARD, CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR);
128
129 descriptorsPool = createPool(descriptorPoolType);
130 if (cache != null) {
131 cache.put(session, DESCRIPTORS, descriptorsPool);
132 }
133 }
134
135 this.artifacts = artifactsPool;
136 this.dependencies = dependenciesPool;
137 this.descriptors = descriptorsPool;
138
139 this.constraints = new ConcurrentHashMap<>(256);
140 this.nodes = new ConcurrentHashMap<>(256);
141 }
142
143 public Artifact intern(Artifact artifact) {
144 return artifacts.intern(artifact, artifact);
145 }
146
147 public Dependency intern(Dependency dependency) {
148 return dependencies.intern(dependency, dependency);
149 }
150
151 public Object toKey(ArtifactDescriptorRequest request) {
152 return request.getArtifact();
153 }
154
155 public ArtifactDescriptorResult getDescriptor(Object key, ArtifactDescriptorRequest request) {
156 Descriptor descriptor = descriptors.get(key);
157 if (descriptor != null) {
158 return descriptor.toResult(request);
159 }
160 return null;
161 }
162
163 public void putDescriptor(Object key, ArtifactDescriptorResult result) {
164 descriptors.intern(key, new GoodDescriptor(result));
165 }
166
167 public void putDescriptor(Object key, ArtifactDescriptorException e) {
168 descriptors.intern(key, BadDescriptor.INSTANCE);
169 }
170
171 public Object toKey(VersionRangeRequest request) {
172 return new ConstraintKey(request);
173 }
174
175 public VersionRangeResult getConstraint(Object key, VersionRangeRequest request) {
176 Constraint constraint = constraints.get(key);
177 if (constraint != null) {
178 return constraint.toResult(request);
179 }
180 return null;
181 }
182
183 public void putConstraint(Object key, VersionRangeResult result) {
184 constraints.put(key, new Constraint(result));
185 }
186
187 public Object toKey(
188 Artifact artifact,
189 List<RemoteRepository> repositories,
190 DependencySelector selector,
191 DependencyManager manager,
192 DependencyTraverser traverser,
193 VersionFilter filter) {
194 return new GraphKey(artifact, repositories, selector, manager, traverser, filter);
195 }
196
197 public List<DependencyNode> getChildren(Object key) {
198 return nodes.get(key);
199 }
200
201 public void putChildren(Object key, List<DependencyNode> children) {
202 nodes.put(key, children);
203 }
204
205 abstract static class Descriptor {
206
207 public abstract ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request);
208 }
209
210 static final class GoodDescriptor extends Descriptor {
211
212 final Artifact artifact;
213
214 final List<Artifact> relocations;
215
216 final Collection<Artifact> aliases;
217
218 final List<RemoteRepository> repositories;
219
220 final List<Dependency> dependencies;
221
222 final List<Dependency> managedDependencies;
223
224 GoodDescriptor(ArtifactDescriptorResult result) {
225 artifact = result.getArtifact();
226 relocations = result.getRelocations();
227 aliases = result.getAliases();
228 dependencies = result.getDependencies();
229 managedDependencies = result.getManagedDependencies();
230 repositories = result.getRepositories();
231 }
232
233 public ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request) {
234 ArtifactDescriptorResult result = new ArtifactDescriptorResult(request);
235 result.setArtifact(artifact);
236 result.setRelocations(relocations);
237 result.setAliases(aliases);
238 result.setDependencies(dependencies);
239 result.setManagedDependencies(managedDependencies);
240 result.setRepositories(repositories);
241 return result;
242 }
243 }
244
245 static final class BadDescriptor extends Descriptor {
246
247 static final BadDescriptor INSTANCE = new BadDescriptor();
248
249 public ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request) {
250 return NO_DESCRIPTOR;
251 }
252 }
253
254 private static final class Constraint {
255 final VersionRepo[] repositories;
256
257 final VersionConstraint versionConstraint;
258
259 Constraint(VersionRangeResult result) {
260 versionConstraint = result.getVersionConstraint();
261 List<Version> versions = result.getVersions();
262 repositories = new VersionRepo[versions.size()];
263 int i = 0;
264 for (Version version : versions) {
265 repositories[i++] = new VersionRepo(version, result.getRepository(version));
266 }
267 }
268
269 VersionRangeResult toResult(VersionRangeRequest request) {
270 VersionRangeResult result = new VersionRangeResult(request);
271 for (VersionRepo vr : repositories) {
272 result.addVersion(vr.version);
273 result.setRepository(vr.version, vr.repo);
274 }
275 result.setVersionConstraint(versionConstraint);
276 return result;
277 }
278
279 static final class VersionRepo {
280 final Version version;
281
282 final ArtifactRepository repo;
283
284 VersionRepo(Version version, ArtifactRepository repo) {
285 this.version = version;
286 this.repo = repo;
287 }
288 }
289 }
290
291 static final class ConstraintKey {
292 private final Artifact artifact;
293
294 private final List<RemoteRepository> repositories;
295
296 private final int hashCode;
297
298 ConstraintKey(VersionRangeRequest request) {
299 artifact = request.getArtifact();
300 repositories = request.getRepositories();
301 hashCode = artifact.hashCode();
302 }
303
304 @Override
305 public boolean equals(Object obj) {
306 if (obj == this) {
307 return true;
308 } else if (!(obj instanceof ConstraintKey)) {
309 return false;
310 }
311 ConstraintKey that = (ConstraintKey) obj;
312 return artifact.equals(that.artifact) && equals(repositories, that.repositories);
313 }
314
315 private static boolean equals(List<RemoteRepository> repos1, List<RemoteRepository> repos2) {
316 if (repos1.size() != repos2.size()) {
317 return false;
318 }
319 for (Iterator<RemoteRepository> it1 = repos1.iterator(), it2 = repos2.iterator();
320 it1.hasNext() && it2.hasNext(); ) {
321 RemoteRepository repo1 = it1.next();
322 RemoteRepository repo2 = it2.next();
323 if (repo1.isRepositoryManager() != repo2.isRepositoryManager()) {
324 return false;
325 }
326 if (repo1.isRepositoryManager()) {
327 if (!equals(repo1.getMirroredRepositories(), repo2.getMirroredRepositories())) {
328 return false;
329 }
330 } else if (!repo1.getUrl().equals(repo2.getUrl())) {
331 return false;
332 } else if (repo1.getPolicy(true).isEnabled()
333 != repo2.getPolicy(true).isEnabled()) {
334 return false;
335 } else if (repo1.getPolicy(false).isEnabled()
336 != repo2.getPolicy(false).isEnabled()) {
337 return false;
338 }
339 }
340 return true;
341 }
342
343 @Override
344 public int hashCode() {
345 return hashCode;
346 }
347 }
348
349 static final class GraphKey {
350 private final Artifact artifact;
351
352 private final List<RemoteRepository> repositories;
353
354 private final DependencySelector selector;
355
356 private final DependencyManager manager;
357
358 private final DependencyTraverser traverser;
359
360 private final VersionFilter filter;
361
362 private final int hashCode;
363
364 GraphKey(
365 Artifact artifact,
366 List<RemoteRepository> repositories,
367 DependencySelector selector,
368 DependencyManager manager,
369 DependencyTraverser traverser,
370 VersionFilter filter) {
371 this.artifact = artifact;
372 this.repositories = repositories;
373 this.selector = selector;
374 this.manager = manager;
375 this.traverser = traverser;
376 this.filter = filter;
377
378 hashCode = Objects.hash(artifact, repositories, selector, manager, traverser, filter);
379 }
380
381 @Override
382 public boolean equals(Object obj) {
383 if (obj == this) {
384 return true;
385 } else if (!(obj instanceof GraphKey)) {
386 return false;
387 }
388 GraphKey that = (GraphKey) obj;
389 return Objects.equals(artifact, that.artifact)
390 && Objects.equals(repositories, that.repositories)
391 && Objects.equals(selector, that.selector)
392 && Objects.equals(manager, that.manager)
393 && Objects.equals(traverser, that.traverser)
394 && Objects.equals(filter, that.filter);
395 }
396
397 @Override
398 public int hashCode() {
399 return hashCode;
400 }
401 }
402
403 private static <K, V> InternPool<K, V> createPool(String type) {
404 if (HARD.equals(type)) {
405 return new HardInternPool<>();
406 } else if (WEAK.equals(type)) {
407 return new WeakInternPool<>();
408 } else {
409 throw new IllegalArgumentException("Unknown object pool type: '" + type + "'");
410 }
411 }
412
413 private static final String HARD = "hard";
414
415 private static final String WEAK = "weak";
416
417 private interface InternPool<K, V> {
418 V get(K key);
419
420 V intern(K key, V value);
421 }
422
423 private static class HardInternPool<K, V> implements InternPool<K, V> {
424 private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>(256);
425
426 @Override
427 public V get(K key) {
428 return map.get(key);
429 }
430
431 @Override
432 public V intern(K key, V value) {
433 return map.computeIfAbsent(key, k -> value);
434 }
435 }
436
437 private static class WeakInternPool<K, V> implements InternPool<K, V> {
438 private final Map<K, WeakReference<V>> map = Collections.synchronizedMap(new WeakHashMap<>(256));
439
440 @Override
441 public V get(K key) {
442 WeakReference<V> ref = map.get(key);
443 return ref != null ? ref.get() : null;
444 }
445
446 @Override
447 public V intern(K key, V value) {
448 WeakReference<V> pooledRef = map.get(key);
449 if (pooledRef != null) {
450 V pooled = pooledRef.get();
451 if (pooled != null) {
452 return pooled;
453 }
454 }
455 map.put(key, new WeakReference<>(value));
456 return value;
457 }
458 }
459 }