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