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