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