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(), request.getRepositories());
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, new BadDescriptor(e));
251 }
252
253
254
255
256
257
258 public String getDescriptorFailure(DescriptorKey key) {
259 Descriptor descriptor = descriptors.get(key);
260 if (descriptor instanceof BadDescriptor) {
261 return ((BadDescriptor) descriptor).reason;
262 }
263 return null;
264 }
265
266 private List<Dependency> intern(List<Dependency> dependencies) {
267 return dependencyLists.intern(dependencies, dependencies);
268 }
269
270 public Object toKey(VersionRangeRequest request) {
271 return new ConstraintKey(request);
272 }
273
274 public VersionRangeResult getConstraint(Object key, VersionRangeRequest request) {
275 Constraint constraint = constraints.get(key);
276 if (constraint != null) {
277 return constraint.toResult(request);
278 }
279 return null;
280 }
281
282 public void putConstraint(Object key, VersionRangeResult result) {
283 constraints.put(key, new Constraint(result));
284 }
285
286 public Object toKey(
287 Artifact artifact,
288 List<RemoteRepository> repositories,
289 DependencySelector selector,
290 DependencyManager manager,
291 DependencyTraverser traverser,
292 VersionFilter filter) {
293 return new GraphKey(artifact, repositories, selector, manager, traverser, filter);
294 }
295
296 public List<DependencyNode> getChildren(Object key) {
297 return nodes.get(key);
298 }
299
300 public void putChildren(Object key, List<DependencyNode> children) {
301 nodes.put(key, children);
302 }
303
304 public static final class DescriptorKey {
305 private final Artifact artifact;
306 private final List<RemoteRepository> repositories;
307 private final int hashCode;
308
309 private DescriptorKey(Artifact artifact, List<RemoteRepository> repositories) {
310 this.artifact = artifact;
311 this.repositories = repositories;
312 this.hashCode = Objects.hashCode(artifact);
313 }
314
315 @Override
316 public boolean equals(Object o) {
317 if (this == o) {
318 return true;
319 }
320 if (o == null || getClass() != o.getClass()) {
321 return false;
322 }
323 DescriptorKey that = (DescriptorKey) o;
324 return Objects.equals(artifact, that.artifact) && repositoriesEquals(repositories, that.repositories);
325 }
326
327 @Override
328 public int hashCode() {
329 return hashCode;
330 }
331
332 @Override
333 public String toString() {
334 return getClass().getSimpleName() + "{" + "artifact='" + artifact + '\'' + ", repositories='" + repositories
335 + '\'' + '}';
336 }
337 }
338
339 abstract static class Descriptor {
340 public abstract ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request);
341 }
342
343 static final class GoodDescriptor extends Descriptor {
344
345 final Artifact artifact;
346
347 final List<Artifact> relocations;
348
349 final Collection<Artifact> aliases;
350
351 final List<RemoteRepository> repositories;
352
353 final List<Dependency> dependencies;
354
355 final List<Dependency> managedDependencies;
356
357 GoodDescriptor(ArtifactDescriptorResult result) {
358 artifact = result.getArtifact();
359 relocations = result.getRelocations();
360 aliases = result.getAliases();
361 dependencies = result.getDependencies();
362 managedDependencies = result.getManagedDependencies();
363 repositories = result.getRepositories();
364 }
365
366 public ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request) {
367 ArtifactDescriptorResult result = new ArtifactDescriptorResult(request);
368 result.setArtifact(artifact);
369 result.setRelocations(relocations);
370 result.setAliases(aliases);
371 result.setDependencies(dependencies);
372 result.setManagedDependencies(managedDependencies);
373 result.setRepositories(repositories);
374 return result;
375 }
376 }
377
378 static final class BadDescriptor extends Descriptor {
379
380 final String reason;
381
382 BadDescriptor(ArtifactDescriptorException exception) {
383 this.reason = exception != null ? exception.getMessage() : null;
384 }
385
386 public ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request) {
387 return NO_DESCRIPTOR;
388 }
389 }
390
391 private static final class Constraint {
392 final VersionRepo[] repositories;
393
394 final VersionConstraint versionConstraint;
395
396 Constraint(VersionRangeResult result) {
397 versionConstraint = result.getVersionConstraint();
398 List<Version> versions = result.getVersions();
399 repositories = new VersionRepo[versions.size()];
400 int i = 0;
401 for (Version version : versions) {
402 repositories[i++] = new VersionRepo(version, result.getRepository(version));
403 }
404 }
405
406 VersionRangeResult toResult(VersionRangeRequest request) {
407 VersionRangeResult result = new VersionRangeResult(request);
408 for (VersionRepo vr : repositories) {
409 result.addVersion(vr.version);
410 result.setRepository(vr.version, vr.repo);
411 }
412 result.setVersionConstraint(versionConstraint);
413 return result;
414 }
415
416 static final class VersionRepo {
417 final Version version;
418
419 final ArtifactRepository repo;
420
421 VersionRepo(Version version, ArtifactRepository repo) {
422 this.version = version;
423 this.repo = repo;
424 }
425 }
426 }
427
428 static final class ConstraintKey {
429 private final Artifact artifact;
430
431 private final List<RemoteRepository> repositories;
432
433 private final int hashCode;
434
435 ConstraintKey(VersionRangeRequest request) {
436 artifact = request.getArtifact();
437 repositories = request.getRepositories();
438 hashCode = artifact.hashCode();
439 }
440
441 @Override
442 public boolean equals(Object obj) {
443 if (obj == this) {
444 return true;
445 } else if (!(obj instanceof ConstraintKey)) {
446 return false;
447 }
448 ConstraintKey that = (ConstraintKey) obj;
449 return artifact.equals(that.artifact) && repositoriesEquals(repositories, that.repositories);
450 }
451
452 @Override
453 public int hashCode() {
454 return hashCode;
455 }
456 }
457
458 private static boolean repositoriesEquals(List<RemoteRepository> repos1, List<RemoteRepository> repos2) {
459 if (repos1.size() != repos2.size()) {
460 return false;
461 }
462 for (Iterator<RemoteRepository> it1 = repos1.iterator(), it2 = repos2.iterator();
463 it1.hasNext() && it2.hasNext(); ) {
464 RemoteRepository repo1 = it1.next();
465 RemoteRepository repo2 = it2.next();
466 if (repo1.isRepositoryManager() != repo2.isRepositoryManager()) {
467 return false;
468 }
469 if (repo1.isRepositoryManager()) {
470 if (!repositoriesEquals(repo1.getMirroredRepositories(), repo2.getMirroredRepositories())) {
471 return false;
472 }
473 } else if (!repo1.getUrl().equals(repo2.getUrl())) {
474 return false;
475 } else if (repo1.getPolicy(true).isEnabled()
476 != repo2.getPolicy(true).isEnabled()) {
477 return false;
478 } else if (repo1.getPolicy(false).isEnabled()
479 != repo2.getPolicy(false).isEnabled()) {
480 return false;
481 }
482 }
483 return true;
484 }
485
486 static final class GraphKey {
487 private final Artifact artifact;
488
489 private final List<RemoteRepository> repositories;
490
491 private final DependencySelector selector;
492
493 private final DependencyManager manager;
494
495 private final DependencyTraverser traverser;
496
497 private final VersionFilter filter;
498
499 private final int hashCode;
500
501 GraphKey(
502 Artifact artifact,
503 List<RemoteRepository> repositories,
504 DependencySelector selector,
505 DependencyManager manager,
506 DependencyTraverser traverser,
507 VersionFilter filter) {
508 this.artifact = artifact;
509 this.repositories = repositories;
510 this.selector = selector;
511 this.manager = manager;
512 this.traverser = traverser;
513 this.filter = filter;
514
515 hashCode = Objects.hash(artifact, repositories, selector, manager, traverser, filter);
516 }
517
518 @Override
519 public boolean equals(Object obj) {
520 if (obj == this) {
521 return true;
522 } else if (!(obj instanceof GraphKey)) {
523 return false;
524 }
525 GraphKey that = (GraphKey) obj;
526 return Objects.equals(artifact, that.artifact)
527 && Objects.equals(repositories, that.repositories)
528 && Objects.equals(selector, that.selector)
529 && Objects.equals(manager, that.manager)
530 && Objects.equals(traverser, that.traverser)
531 && Objects.equals(filter, that.filter);
532 }
533
534 @Override
535 public int hashCode() {
536 return hashCode;
537 }
538 }
539
540 private static <K, V> InternPool<K, V> createPool(String type) {
541 if (HARD.equals(type)) {
542 return new HardInternPool<>();
543 } else if (WEAK.equals(type)) {
544 return new WeakInternPool<>();
545 } else {
546 throw new IllegalArgumentException("Unknown object pool type: '" + type + "'");
547 }
548 }
549
550 public static final String HARD = "hard";
551
552 public static final String WEAK = "weak";
553
554 private interface InternPool<K, V> {
555 V get(K key);
556
557 V intern(K key, V value);
558 }
559
560 private static class HardInternPool<K, V> implements InternPool<K, V> {
561 private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>(256);
562
563 @Override
564 public V get(K key) {
565 return map.get(key);
566 }
567
568 @Override
569 public V intern(K key, V value) {
570 return map.computeIfAbsent(key, k -> value);
571 }
572 }
573
574
575
576
577
578
579
580
581 private static class WeakInternPool<K, V> implements InternPool<K, V> {
582 private final ConcurrentWeakCache<K, V> cache = new ConcurrentWeakCache<>(256);
583
584 @Override
585 public V get(K key) {
586 return cache.get(key);
587 }
588
589 @Override
590 public V intern(K key, V value) {
591 return cache.putIfAbsent(key, value);
592 }
593 }
594 }