1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.util.graph.manager;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.LinkedHashSet;
25 import java.util.Objects;
26
27 import org.eclipse.aether.artifact.Artifact;
28 import org.eclipse.aether.collection.DependencyCollectionContext;
29 import org.eclipse.aether.collection.DependencyManagement;
30 import org.eclipse.aether.collection.DependencyManager;
31 import org.eclipse.aether.graph.Dependency;
32 import org.eclipse.aether.graph.Exclusion;
33 import org.eclipse.aether.scope.ScopeManager;
34 import org.eclipse.aether.scope.SystemDependencyScope;
35
36 import static java.util.Objects.requireNonNull;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public abstract class AbstractDependencyManager implements DependencyManager {
68 protected final ArrayList<AbstractDependencyManager> path;
69
70 protected final int depth;
71
72 protected final int deriveUntil;
73
74 protected final int applyFrom;
75
76 protected final MMap<Key, String> managedVersions;
77
78 protected final MMap<Key, String> managedScopes;
79
80 protected final MMap<Key, Boolean> managedOptionals;
81
82 protected final MMap<Key, String> managedLocalPaths;
83
84 protected final MMap<Key, Holder<Collection<Exclusion>>> managedExclusions;
85
86 protected final SystemDependencyScope systemDependencyScope;
87
88 private final int hashCode;
89
90 protected AbstractDependencyManager(int deriveUntil, int applyFrom, ScopeManager scopeManager) {
91 this(
92 new ArrayList<>(),
93 0,
94 deriveUntil,
95 applyFrom,
96 null,
97 null,
98 null,
99 null,
100 null,
101 scopeManager != null
102 ? scopeManager.getSystemDependencyScope().orElse(null)
103 : SystemDependencyScope.LEGACY);
104 }
105
106 @SuppressWarnings("checkstyle:ParameterNumber")
107 protected AbstractDependencyManager(
108 ArrayList<AbstractDependencyManager> path,
109 int depth,
110 int deriveUntil,
111 int applyFrom,
112 MMap<Key, String> managedVersions,
113 MMap<Key, String> managedScopes,
114 MMap<Key, Boolean> managedOptionals,
115 MMap<Key, String> managedLocalPaths,
116 MMap<Key, Holder<Collection<Exclusion>>> managedExclusions,
117 SystemDependencyScope systemDependencyScope) {
118 this.path = path;
119 this.depth = depth;
120 this.deriveUntil = deriveUntil;
121 this.applyFrom = applyFrom;
122 this.managedVersions = managedVersions;
123 this.managedScopes = managedScopes;
124 this.managedOptionals = managedOptionals;
125 this.managedLocalPaths = managedLocalPaths;
126 this.managedExclusions = managedExclusions;
127
128 this.systemDependencyScope = systemDependencyScope;
129
130
131 this.hashCode = Objects.hash(path, depth, managedVersions, managedScopes, managedOptionals, managedExclusions);
132 }
133
134 protected abstract DependencyManager newInstance(
135 MMap<Key, String> managedVersions,
136 MMap<Key, String> managedScopes,
137 MMap<Key, Boolean> managedOptionals,
138 MMap<Key, String> managedLocalPaths,
139 MMap<Key, Holder<Collection<Exclusion>>> managedExclusions);
140
141 private boolean containsManagedVersion(Key key) {
142 for (AbstractDependencyManager ancestor : path) {
143 if (ancestor.managedVersions != null && ancestor.managedVersions.containsKey(key)) {
144 return true;
145 }
146 }
147 return managedVersions != null && managedVersions.containsKey(key);
148 }
149
150 private String getManagedVersion(Key key) {
151 for (AbstractDependencyManager ancestor : path) {
152 if (ancestor.managedVersions != null && ancestor.managedVersions.containsKey(key)) {
153 return ancestor.managedVersions.get(key);
154 }
155 }
156 if (depth == 1 && managedVersions != null && managedVersions.containsKey(key)) {
157 return managedVersions.get(key);
158 }
159 return null;
160 }
161
162 private boolean containsManagedScope(Key key) {
163 for (AbstractDependencyManager ancestor : path) {
164 if (ancestor.managedScopes != null && ancestor.managedScopes.containsKey(key)) {
165 return true;
166 }
167 }
168 return managedScopes != null && managedScopes.containsKey(key);
169 }
170
171 private String getManagedScope(Key key) {
172 for (AbstractDependencyManager ancestor : path) {
173 if (ancestor.managedScopes != null && ancestor.managedScopes.containsKey(key)) {
174 return ancestor.managedScopes.get(key);
175 }
176 }
177 if (depth == 1 && managedScopes != null && managedScopes.containsKey(key)) {
178 return managedScopes.get(key);
179 }
180 return null;
181 }
182
183 private boolean containsManagedOptional(Key key) {
184 for (AbstractDependencyManager ancestor : path) {
185 if (ancestor.managedOptionals != null && ancestor.managedOptionals.containsKey(key)) {
186 return true;
187 }
188 }
189 return managedOptionals != null && managedOptionals.containsKey(key);
190 }
191
192 private Boolean getManagedOptional(Key key) {
193 for (AbstractDependencyManager ancestor : path) {
194 if (ancestor.managedOptionals != null && ancestor.managedOptionals.containsKey(key)) {
195 return ancestor.managedOptionals.get(key);
196 }
197 }
198 if (depth == 1 && managedOptionals != null && managedOptionals.containsKey(key)) {
199 return managedOptionals.get(key);
200 }
201 return null;
202 }
203
204 private boolean containsManagedLocalPath(Key key) {
205 for (AbstractDependencyManager ancestor : path) {
206 if (ancestor.managedLocalPaths != null && ancestor.managedLocalPaths.containsKey(key)) {
207 return true;
208 }
209 }
210 return managedLocalPaths != null && managedLocalPaths.containsKey(key);
211 }
212
213 private String getManagedLocalPath(Key key) {
214 for (AbstractDependencyManager ancestor : path) {
215 if (ancestor.managedLocalPaths != null && ancestor.managedLocalPaths.containsKey(key)) {
216 return ancestor.managedLocalPaths.get(key);
217 }
218 }
219 if (managedLocalPaths != null && managedLocalPaths.containsKey(key)) {
220 return managedLocalPaths.get(key);
221 }
222 return null;
223 }
224
225
226
227
228 private Collection<Exclusion> getManagedExclusions(Key key) {
229 ArrayList<Exclusion> result = new ArrayList<>();
230 for (AbstractDependencyManager ancestor : path) {
231 if (ancestor.managedExclusions != null && ancestor.managedExclusions.containsKey(key)) {
232 result.addAll(ancestor.managedExclusions.get(key).value);
233 }
234 }
235 if (managedExclusions != null && managedExclusions.containsKey(key)) {
236 result.addAll(managedExclusions.get(key).value);
237 }
238 return result.isEmpty() ? null : result;
239 }
240
241 @Override
242 public DependencyManager deriveChildManager(DependencyCollectionContext context) {
243 requireNonNull(context, "context cannot be null");
244 if (!isDerived()) {
245 return this;
246 }
247
248 MMap<Key, String> managedVersions = null;
249 MMap<Key, String> managedScopes = null;
250 MMap<Key, Boolean> managedOptionals = null;
251 MMap<Key, String> managedLocalPaths = null;
252 MMap<Key, Holder<Collection<Exclusion>>> managedExclusions = null;
253
254 for (Dependency managedDependency : context.getManagedDependencies()) {
255 Artifact artifact = managedDependency.getArtifact();
256 Key key = new Key(artifact);
257
258 String version = artifact.getVersion();
259 if (!version.isEmpty() && !containsManagedVersion(key)) {
260 if (managedVersions == null) {
261 managedVersions = MMap.emptyNotDone();
262 }
263 managedVersions.put(key, version);
264 }
265
266 String scope = managedDependency.getScope();
267 if (!scope.isEmpty() && !containsManagedScope(key)) {
268 if (managedScopes == null) {
269 managedScopes = MMap.emptyNotDone();
270 }
271 managedScopes.put(key, scope);
272 }
273
274 Boolean optional = managedDependency.getOptional();
275 if (optional != null && !containsManagedOptional(key)) {
276 if (managedOptionals == null) {
277 managedOptionals = MMap.emptyNotDone();
278 }
279 managedOptionals.put(key, optional);
280 }
281
282 String localPath = systemDependencyScope == null
283 ? null
284 : systemDependencyScope.getSystemPath(managedDependency.getArtifact());
285 if (localPath != null && !containsManagedLocalPath(key)) {
286 if (managedLocalPaths == null) {
287 managedLocalPaths = MMap.emptyNotDone();
288 }
289 managedLocalPaths.put(key, localPath);
290 }
291
292 Collection<Exclusion> exclusions = managedDependency.getExclusions();
293 if (!exclusions.isEmpty()) {
294 if (managedExclusions == null) {
295 managedExclusions = MMap.emptyNotDone();
296 }
297 Holder<Collection<Exclusion>> managed = managedExclusions.get(key);
298 if (managed != null) {
299 ArrayList<Exclusion> ex = new ArrayList<>(managed.getValue());
300 ex.addAll(exclusions);
301 managed = new Holder<>(ex);
302 managedExclusions.put(key, managed);
303 } else {
304 managedExclusions.put(key, new Holder<>(exclusions));
305 }
306 }
307 }
308
309 return newInstance(
310 managedVersions != null ? managedVersions.done() : null,
311 managedScopes != null ? managedScopes.done() : null,
312 managedOptionals != null ? managedOptionals.done() : null,
313 managedLocalPaths != null ? managedLocalPaths.done() : null,
314 managedExclusions != null ? managedExclusions.done() : null);
315 }
316
317 @Override
318 public DependencyManagement manageDependency(Dependency dependency) {
319 requireNonNull(dependency, "dependency cannot be null");
320 DependencyManagement management = null;
321 Key key = new Key(dependency.getArtifact());
322
323 if (isApplied()) {
324 String version = getManagedVersion(key);
325
326
327 if (version != null) {
328 management = new DependencyManagement();
329 management.setVersion(version);
330 }
331
332 String scope = getManagedScope(key);
333
334
335 if (scope != null) {
336 if (management == null) {
337 management = new DependencyManagement();
338 }
339 management.setScope(scope);
340
341 if (systemDependencyScope != null
342 && !systemDependencyScope.is(scope)
343 && systemDependencyScope.getSystemPath(dependency.getArtifact()) != null) {
344 HashMap<String, String> properties =
345 new HashMap<>(dependency.getArtifact().getProperties());
346 systemDependencyScope.setSystemPath(properties, null);
347 management.setProperties(properties);
348 }
349 }
350
351
352
353 if (systemDependencyScope != null
354 && (scope != null && systemDependencyScope.is(scope)
355 || (scope == null && systemDependencyScope.is(dependency.getScope())))) {
356 String localPath = getManagedLocalPath(key);
357 if (localPath != null) {
358 if (management == null) {
359 management = new DependencyManagement();
360 }
361 HashMap<String, String> properties =
362 new HashMap<>(dependency.getArtifact().getProperties());
363 systemDependencyScope.setSystemPath(properties, localPath);
364 management.setProperties(properties);
365 }
366 }
367
368
369
370 Boolean optional = getManagedOptional(key);
371 if (optional != null) {
372 if (management == null) {
373 management = new DependencyManagement();
374 }
375 management.setOptional(optional);
376 }
377 }
378
379
380
381
382
383
384 Collection<Exclusion> exclusions = getManagedExclusions(key);
385 if (exclusions != null) {
386 if (management == null) {
387 management = new DependencyManagement();
388 }
389 Collection<Exclusion> result = new LinkedHashSet<>(dependency.getExclusions());
390 result.addAll(exclusions);
391 management.setExclusions(result);
392 }
393
394 return management;
395 }
396
397
398
399
400 protected boolean isDerived() {
401 return depth < deriveUntil;
402 }
403
404
405
406
407 protected boolean isApplied() {
408 return depth >= applyFrom;
409 }
410
411 @Override
412 public boolean equals(Object obj) {
413 if (this == obj) {
414 return true;
415 } else if (null == obj || !getClass().equals(obj.getClass())) {
416 return false;
417 }
418
419 AbstractDependencyManager that = (AbstractDependencyManager) obj;
420
421 return Objects.equals(path, that.path)
422 && depth == that.depth
423 && Objects.equals(managedVersions, that.managedVersions)
424 && Objects.equals(managedScopes, that.managedScopes)
425 && Objects.equals(managedOptionals, that.managedOptionals)
426 && Objects.equals(managedExclusions, that.managedExclusions);
427 }
428
429 @Override
430 public int hashCode() {
431 return hashCode;
432 }
433
434 protected static class Key {
435 private final Artifact artifact;
436 private final int hashCode;
437
438 Key(Artifact artifact) {
439 this.artifact = artifact;
440 this.hashCode = Objects.hash(
441 artifact.getArtifactId(), artifact.getGroupId(), artifact.getExtension(), artifact.getClassifier());
442 }
443
444 @Override
445 public boolean equals(Object obj) {
446 if (obj == this) {
447 return true;
448 } else if (!(obj instanceof Key)) {
449 return false;
450 }
451 Key that = (Key) obj;
452 return artifact.getArtifactId().equals(that.artifact.getArtifactId())
453 && artifact.getGroupId().equals(that.artifact.getGroupId())
454 && artifact.getExtension().equals(that.artifact.getExtension())
455 && artifact.getClassifier().equals(that.artifact.getClassifier());
456 }
457
458 @Override
459 public int hashCode() {
460 return hashCode;
461 }
462
463 @Override
464 public String toString() {
465 return String.valueOf(artifact);
466 }
467 }
468
469
470
471
472
473
474 protected static class Holder<T> {
475 private final T value;
476 private final int hashCode;
477
478 Holder(T value) {
479 this.value = requireNonNull(value);
480 this.hashCode = Objects.hash(value);
481 }
482
483 public T getValue() {
484 return value;
485 }
486
487 @Override
488 public boolean equals(Object o) {
489 if (!(o instanceof Holder)) {
490 return false;
491 }
492 Holder<?> holder = (Holder<?>) o;
493 return Objects.equals(value, holder.value);
494 }
495
496 @Override
497 public int hashCode() {
498 return hashCode;
499 }
500 }
501 }