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 CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY_LISTS =
62 "aether.dependencyCollector.pool.dependencyLists";
63
64 private static final String CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_DEPENDENCIES =
65 "aether.dependencyCollector.pool.internArtifactDescriptorDependencies";
66
67 private static final String CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_MANAGED_DEPENDENCIES =
68 "aether.dependencyCollector.pool.internArtifactDescriptorManagedDependencies";
69
70 private static final String ARTIFACT_POOL = DataPool.class.getName() + "$Artifact";
71
72 private static final String DEPENDENCY_POOL = DataPool.class.getName() + "$Dependency";
73
74 private static final String DESCRIPTORS = DataPool.class.getName() + "$Descriptors";
75
76 private static final String DEPENDENCY_LISTS_POOL = DataPool.class.getName() + "$DependencyLists";
77
78 public static final ArtifactDescriptorResult NO_DESCRIPTOR =
79 new ArtifactDescriptorResult(new ArtifactDescriptorRequest());
80
81
82
83
84 private final InternPool<Artifact, Artifact> artifacts;
85
86
87
88
89 private final InternPool<Dependency, Dependency> dependencies;
90
91
92
93
94 private final InternPool<DescriptorKey, Descriptor> descriptors;
95
96
97
98
99 private final InternPool<List<Dependency>, List<Dependency>> dependencyLists;
100
101
102
103
104 private final ConcurrentHashMap<Object, Constraint> constraints;
105
106
107
108
109 private final ConcurrentHashMap<Object, List<DependencyNode>> nodes;
110
111 private final boolean internArtifactDescriptorDependencies;
112
113 private final boolean internArtifactDescriptorManagedDependencies;
114
115 @SuppressWarnings("unchecked")
116 public DataPool(RepositorySystemSession session) {
117 final RepositoryCache cache = session.getCache();
118
119 internArtifactDescriptorDependencies = ConfigUtils.getBoolean(
120 session, false, CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_DEPENDENCIES);
121 internArtifactDescriptorManagedDependencies = ConfigUtils.getBoolean(
122 session, true, CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_MANAGED_DEPENDENCIES);
123
124 InternPool<Artifact, Artifact> artifactsPool = null;
125 InternPool<Dependency, Dependency> dependenciesPool = null;
126 InternPool<DescriptorKey, Descriptor> descriptorsPool = null;
127 InternPool<List<Dependency>, List<Dependency>> dependencyListsPool = null;
128 if (cache != null) {
129 artifactsPool = (InternPool<Artifact, Artifact>) cache.get(session, ARTIFACT_POOL);
130 dependenciesPool = (InternPool<Dependency, Dependency>) cache.get(session, DEPENDENCY_POOL);
131 descriptorsPool = (InternPool<DescriptorKey, Descriptor>) cache.get(session, DESCRIPTORS);
132 dependencyListsPool =
133 (InternPool<List<Dependency>, List<Dependency>>) cache.get(session, DEPENDENCY_LISTS_POOL);
134 }
135
136 if (artifactsPool == null) {
137 String artifactPoolType = ConfigUtils.getString(session, WEAK, CONFIG_PROP_COLLECTOR_POOL_ARTIFACT);
138
139 artifactsPool = createPool(artifactPoolType);
140 if (cache != null) {
141 cache.put(session, ARTIFACT_POOL, artifactsPool);
142 }
143 }
144
145 if (dependenciesPool == null) {
146 String dependencyPoolType = ConfigUtils.getString(session, WEAK, CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY);
147
148 dependenciesPool = createPool(dependencyPoolType);
149 if (cache != null) {
150 cache.put(session, DEPENDENCY_POOL, dependenciesPool);
151 }
152 }
153
154 if (descriptorsPool == null) {
155 String descriptorPoolType = ConfigUtils.getString(session, HARD, CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR);
156
157 descriptorsPool = createPool(descriptorPoolType);
158 if (cache != null) {
159 cache.put(session, DESCRIPTORS, descriptorsPool);
160 }
161 }
162
163 if (dependencyListsPool == null) {
164 String dependencyListsPoolType =
165 ConfigUtils.getString(session, HARD, CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY_LISTS);
166
167 dependencyListsPool = createPool(dependencyListsPoolType);
168 if (cache != null) {
169 cache.put(session, DEPENDENCY_LISTS_POOL, dependencyListsPool);
170 }
171 }
172
173 this.artifacts = artifactsPool;
174 this.dependencies = dependenciesPool;
175 this.descriptors = descriptorsPool;
176 this.dependencyLists = dependencyListsPool;
177
178 this.constraints = new ConcurrentHashMap<>(256);
179 this.nodes = new ConcurrentHashMap<>(256);
180 }
181
182 public Artifact intern(Artifact artifact) {
183 return artifacts.intern(artifact, artifact);
184 }
185
186 public Dependency intern(Dependency dependency) {
187 return dependencies.intern(dependency, dependency);
188 }
189
190 public DescriptorKey toKey(ArtifactDescriptorRequest request) {
191 return new DescriptorKey(request.getArtifact());
192 }
193
194 public ArtifactDescriptorResult getDescriptor(DescriptorKey key, ArtifactDescriptorRequest request) {
195 Descriptor descriptor = descriptors.get(key);
196 if (descriptor != null) {
197 return descriptor.toResult(request);
198 }
199 return null;
200 }
201
202 public void putDescriptor(DescriptorKey key, ArtifactDescriptorResult result) {
203 if (internArtifactDescriptorDependencies) {
204 result.setDependencies(intern(result.getDependencies()));
205 }
206 if (internArtifactDescriptorManagedDependencies) {
207 result.setManagedDependencies(intern(result.getManagedDependencies()));
208 }
209 descriptors.intern(key, new GoodDescriptor(result));
210 }
211
212 public void putDescriptor(DescriptorKey key, ArtifactDescriptorException e) {
213 descriptors.intern(key, BadDescriptor.INSTANCE);
214 }
215
216 private List<Dependency> intern(List<Dependency> dependencies) {
217 return dependencyLists.intern(dependencies, dependencies);
218 }
219
220 public Object toKey(VersionRangeRequest request) {
221 return new ConstraintKey(request);
222 }
223
224 public VersionRangeResult getConstraint(Object key, VersionRangeRequest request) {
225 Constraint constraint = constraints.get(key);
226 if (constraint != null) {
227 return constraint.toResult(request);
228 }
229 return null;
230 }
231
232 public void putConstraint(Object key, VersionRangeResult result) {
233 constraints.put(key, new Constraint(result));
234 }
235
236 public Object toKey(
237 Artifact artifact,
238 List<RemoteRepository> repositories,
239 DependencySelector selector,
240 DependencyManager manager,
241 DependencyTraverser traverser,
242 VersionFilter filter) {
243 return new GraphKey(artifact, repositories, selector, manager, traverser, filter);
244 }
245
246 public List<DependencyNode> getChildren(Object key) {
247 return nodes.get(key);
248 }
249
250 public void putChildren(Object key, List<DependencyNode> children) {
251 nodes.put(key, children);
252 }
253
254 public static final class DescriptorKey {
255 private final Artifact artifact;
256 private final int hashCode;
257
258 private DescriptorKey(Artifact artifact) {
259 this.artifact = artifact;
260 this.hashCode = Objects.hashCode(artifact);
261 }
262
263 @Override
264 public boolean equals(Object o) {
265 if (this == o) {
266 return true;
267 }
268 if (o == null || getClass() != o.getClass()) {
269 return false;
270 }
271 DescriptorKey that = (DescriptorKey) o;
272 return Objects.equals(artifact, that.artifact);
273 }
274
275 @Override
276 public int hashCode() {
277 return hashCode;
278 }
279
280 @Override
281 public String toString() {
282 return getClass().getSimpleName() + "{" + "artifact='" + artifact + '\'' + '}';
283 }
284 }
285
286 abstract static class Descriptor {
287 public abstract ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request);
288 }
289
290 static final class GoodDescriptor extends Descriptor {
291
292 final Artifact artifact;
293
294 final List<Artifact> relocations;
295
296 final Collection<Artifact> aliases;
297
298 final List<RemoteRepository> repositories;
299
300 final List<Dependency> dependencies;
301
302 final List<Dependency> managedDependencies;
303
304 GoodDescriptor(ArtifactDescriptorResult result) {
305 artifact = result.getArtifact();
306 relocations = result.getRelocations();
307 aliases = result.getAliases();
308 dependencies = result.getDependencies();
309 managedDependencies = result.getManagedDependencies();
310 repositories = result.getRepositories();
311 }
312
313 public ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request) {
314 ArtifactDescriptorResult result = new ArtifactDescriptorResult(request);
315 result.setArtifact(artifact);
316 result.setRelocations(relocations);
317 result.setAliases(aliases);
318 result.setDependencies(dependencies);
319 result.setManagedDependencies(managedDependencies);
320 result.setRepositories(repositories);
321 return result;
322 }
323 }
324
325 static final class BadDescriptor extends Descriptor {
326
327 static final BadDescriptor INSTANCE = new BadDescriptor();
328
329 public ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request) {
330 return NO_DESCRIPTOR;
331 }
332 }
333
334 private static final class Constraint {
335 final VersionRepo[] repositories;
336
337 final VersionConstraint versionConstraint;
338
339 Constraint(VersionRangeResult result) {
340 versionConstraint = result.getVersionConstraint();
341 List<Version> versions = result.getVersions();
342 repositories = new VersionRepo[versions.size()];
343 int i = 0;
344 for (Version version : versions) {
345 repositories[i++] = new VersionRepo(version, result.getRepository(version));
346 }
347 }
348
349 VersionRangeResult toResult(VersionRangeRequest request) {
350 VersionRangeResult result = new VersionRangeResult(request);
351 for (VersionRepo vr : repositories) {
352 result.addVersion(vr.version);
353 result.setRepository(vr.version, vr.repo);
354 }
355 result.setVersionConstraint(versionConstraint);
356 return result;
357 }
358
359 static final class VersionRepo {
360 final Version version;
361
362 final ArtifactRepository repo;
363
364 VersionRepo(Version version, ArtifactRepository repo) {
365 this.version = version;
366 this.repo = repo;
367 }
368 }
369 }
370
371 static final class ConstraintKey {
372 private final Artifact artifact;
373
374 private final List<RemoteRepository> repositories;
375
376 private final int hashCode;
377
378 ConstraintKey(VersionRangeRequest request) {
379 artifact = request.getArtifact();
380 repositories = request.getRepositories();
381 hashCode = artifact.hashCode();
382 }
383
384 @Override
385 public boolean equals(Object obj) {
386 if (obj == this) {
387 return true;
388 } else if (!(obj instanceof ConstraintKey)) {
389 return false;
390 }
391 ConstraintKey that = (ConstraintKey) obj;
392 return artifact.equals(that.artifact) && equals(repositories, that.repositories);
393 }
394
395 private static boolean equals(List<RemoteRepository> repos1, List<RemoteRepository> repos2) {
396 if (repos1.size() != repos2.size()) {
397 return false;
398 }
399 for (Iterator<RemoteRepository> it1 = repos1.iterator(), it2 = repos2.iterator();
400 it1.hasNext() && it2.hasNext(); ) {
401 RemoteRepository repo1 = it1.next();
402 RemoteRepository repo2 = it2.next();
403 if (repo1.isRepositoryManager() != repo2.isRepositoryManager()) {
404 return false;
405 }
406 if (repo1.isRepositoryManager()) {
407 if (!equals(repo1.getMirroredRepositories(), repo2.getMirroredRepositories())) {
408 return false;
409 }
410 } else if (!repo1.getUrl().equals(repo2.getUrl())) {
411 return false;
412 } else if (repo1.getPolicy(true).isEnabled()
413 != repo2.getPolicy(true).isEnabled()) {
414 return false;
415 } else if (repo1.getPolicy(false).isEnabled()
416 != repo2.getPolicy(false).isEnabled()) {
417 return false;
418 }
419 }
420 return true;
421 }
422
423 @Override
424 public int hashCode() {
425 return hashCode;
426 }
427 }
428
429 static final class GraphKey {
430 private final Artifact artifact;
431
432 private final List<RemoteRepository> repositories;
433
434 private final DependencySelector selector;
435
436 private final DependencyManager manager;
437
438 private final DependencyTraverser traverser;
439
440 private final VersionFilter filter;
441
442 private final int hashCode;
443
444 GraphKey(
445 Artifact artifact,
446 List<RemoteRepository> repositories,
447 DependencySelector selector,
448 DependencyManager manager,
449 DependencyTraverser traverser,
450 VersionFilter filter) {
451 this.artifact = artifact;
452 this.repositories = repositories;
453 this.selector = selector;
454 this.manager = manager;
455 this.traverser = traverser;
456 this.filter = filter;
457
458 hashCode = Objects.hash(artifact, repositories, selector, manager, traverser, filter);
459 }
460
461 @Override
462 public boolean equals(Object obj) {
463 if (obj == this) {
464 return true;
465 } else if (!(obj instanceof GraphKey)) {
466 return false;
467 }
468 GraphKey that = (GraphKey) obj;
469 return Objects.equals(artifact, that.artifact)
470 && Objects.equals(repositories, that.repositories)
471 && Objects.equals(selector, that.selector)
472 && Objects.equals(manager, that.manager)
473 && Objects.equals(traverser, that.traverser)
474 && Objects.equals(filter, that.filter);
475 }
476
477 @Override
478 public int hashCode() {
479 return hashCode;
480 }
481 }
482
483 private static <K, V> InternPool<K, V> createPool(String type) {
484 if (HARD.equals(type)) {
485 return new HardInternPool<>();
486 } else if (WEAK.equals(type)) {
487 return new WeakInternPool<>();
488 } else {
489 throw new IllegalArgumentException("Unknown object pool type: '" + type + "'");
490 }
491 }
492
493 private static final String HARD = "hard";
494
495 private static final String WEAK = "weak";
496
497 private interface InternPool<K, V> {
498 V get(K key);
499
500 V intern(K key, V value);
501 }
502
503 private static class HardInternPool<K, V> implements InternPool<K, V> {
504 private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>(256);
505
506 @Override
507 public V get(K key) {
508 return map.get(key);
509 }
510
511 @Override
512 public V intern(K key, V value) {
513 return map.computeIfAbsent(key, k -> value);
514 }
515 }
516
517 private static class WeakInternPool<K, V> implements InternPool<K, V> {
518 private final Map<K, WeakReference<V>> map = Collections.synchronizedMap(new WeakHashMap<>(256));
519
520 @Override
521 public V get(K key) {
522 WeakReference<V> ref = map.get(key);
523 return ref != null ? ref.get() : null;
524 }
525
526 @Override
527 public V intern(K key, V value) {
528 WeakReference<V> pooledRef = map.get(key);
529 if (pooledRef != null) {
530 V pooled = pooledRef.get();
531 if (pooled != null) {
532 return pooled;
533 }
534 }
535 map.put(key, new WeakReference<>(value));
536 return value;
537 }
538 }
539 }