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 public abstract class AbstractDependencyManager implements DependencyManager {
61
62 protected final int depth;
63
64 protected final int deriveUntil;
65
66 protected final int applyFrom;
67
68 protected final MMap<Key, Holder<String>> managedVersions;
69
70 protected final MMap<Key, Holder<String>> managedScopes;
71
72 protected final MMap<Key, Holder<Boolean>> managedOptionals;
73
74 protected final MMap<Key, Holder<String>> managedLocalPaths;
75
76 protected final MMap<Key, Collection<Holder<Collection<Exclusion>>>> managedExclusions;
77
78 protected final SystemDependencyScope systemDependencyScope;
79
80 private final int hashCode;
81
82 protected AbstractDependencyManager(int deriveUntil, int applyFrom, ScopeManager scopeManager) {
83 this(
84 0,
85 deriveUntil,
86 applyFrom,
87 MMap.empty(),
88 MMap.empty(),
89 MMap.empty(),
90 MMap.empty(),
91 MMap.empty(),
92 scopeManager != null
93 ? scopeManager.getSystemDependencyScope().orElse(null)
94 : SystemDependencyScope.LEGACY);
95 }
96
97 @SuppressWarnings("checkstyle:ParameterNumber")
98 protected AbstractDependencyManager(
99 int depth,
100 int deriveUntil,
101 int applyFrom,
102 MMap<Key, Holder<String>> managedVersions,
103 MMap<Key, Holder<String>> managedScopes,
104 MMap<Key, Holder<Boolean>> managedOptionals,
105 MMap<Key, Holder<String>> managedLocalPaths,
106 MMap<Key, Collection<Holder<Collection<Exclusion>>>> managedExclusions,
107 SystemDependencyScope systemDependencyScope) {
108 this.depth = depth;
109 this.deriveUntil = deriveUntil;
110 this.applyFrom = applyFrom;
111 this.managedVersions = requireNonNull(managedVersions);
112 this.managedScopes = requireNonNull(managedScopes);
113 this.managedOptionals = requireNonNull(managedOptionals);
114 this.managedLocalPaths = requireNonNull(managedLocalPaths);
115 this.managedExclusions = requireNonNull(managedExclusions);
116
117 this.systemDependencyScope = systemDependencyScope;
118
119
120 this.hashCode = Objects.hash(depth, managedVersions, managedScopes, managedOptionals, managedExclusions);
121 }
122
123 protected abstract DependencyManager newInstance(
124 MMap<Key, Holder<String>> managedVersions,
125 MMap<Key, Holder<String>> managedScopes,
126 MMap<Key, Holder<Boolean>> managedOptionals,
127 MMap<Key, Holder<String>> managedLocalPaths,
128 MMap<Key, Collection<Holder<Collection<Exclusion>>>> managedExclusions);
129
130 @Override
131 public DependencyManager deriveChildManager(DependencyCollectionContext context) {
132 requireNonNull(context, "context cannot be null");
133 if (!isDerived()) {
134 return this;
135 }
136
137 MMap<Key, Holder<String>> managedVersions = this.managedVersions;
138 MMap<Key, Holder<String>> managedScopes = this.managedScopes;
139 MMap<Key, Holder<Boolean>> managedOptionals = this.managedOptionals;
140 MMap<Key, Holder<String>> managedLocalPaths = this.managedLocalPaths;
141 MMap<Key, Collection<Holder<Collection<Exclusion>>>> managedExclusions = this.managedExclusions;
142
143 for (Dependency managedDependency : context.getManagedDependencies()) {
144 Artifact artifact = managedDependency.getArtifact();
145 Key key = new Key(artifact);
146
147 String version = artifact.getVersion();
148 if (!version.isEmpty() && !managedVersions.containsKey(key)) {
149 if (managedVersions == this.managedVersions) {
150 managedVersions = MMap.copy(this.managedVersions);
151 }
152 managedVersions.put(key, new Holder<>(depth, version));
153 }
154
155 String scope = managedDependency.getScope();
156 if (!scope.isEmpty() && !managedScopes.containsKey(key)) {
157 if (managedScopes == this.managedScopes) {
158 managedScopes = MMap.copy(this.managedScopes);
159 }
160 managedScopes.put(key, new Holder<>(depth, scope));
161 }
162
163 Boolean optional = managedDependency.getOptional();
164 if (optional != null && !managedOptionals.containsKey(key)) {
165 if (managedOptionals == this.managedOptionals) {
166 managedOptionals = MMap.copy(this.managedOptionals);
167 }
168 managedOptionals.put(key, new Holder<>(depth, optional));
169 }
170
171 String localPath = systemDependencyScope == null
172 ? null
173 : systemDependencyScope.getSystemPath(managedDependency.getArtifact());
174 if (localPath != null && !managedLocalPaths.containsKey(key)) {
175 if (managedLocalPaths == this.managedLocalPaths) {
176 managedLocalPaths = MMap.copy(this.managedLocalPaths);
177 }
178 managedLocalPaths.put(key, new Holder<>(depth, localPath));
179 }
180
181 Collection<Exclusion> exclusions = managedDependency.getExclusions();
182 if (!exclusions.isEmpty()) {
183 if (managedExclusions == this.managedExclusions) {
184 managedExclusions = MMap.copyWithKey(key, this.managedExclusions);
185 }
186 Collection<Holder<Collection<Exclusion>>> managed = managedExclusions.get(key);
187 if (managed == null) {
188 managed = new ArrayList<>();
189 managedExclusions.put(key, managed);
190 }
191 managed.add(new Holder<>(depth, exclusions));
192 }
193 }
194
195 return newInstance(
196 managedVersions.done(),
197 managedScopes.done(),
198 managedOptionals.done(),
199 managedLocalPaths.done(),
200 managedExclusions.done());
201 }
202
203 @Override
204 public DependencyManagement manageDependency(Dependency dependency) {
205 requireNonNull(dependency, "dependency cannot be null");
206 DependencyManagement management = null;
207 Key key = new Key(dependency.getArtifact());
208
209 if (isApplied()) {
210 Holder<String> version = managedVersions.get(key);
211
212
213 if (version != null && isApplicable(version)) {
214 management = new DependencyManagement();
215 management.setVersion(version.getValue());
216 }
217
218 Holder<String> scope = managedScopes.get(key);
219
220
221 if (scope != null && isApplicable(scope)) {
222 if (management == null) {
223 management = new DependencyManagement();
224 }
225 management.setScope(scope.getValue());
226
227 if (systemDependencyScope != null
228 && !systemDependencyScope.is(scope.getValue())
229 && systemDependencyScope.getSystemPath(dependency.getArtifact()) != null) {
230 HashMap<String, String> properties =
231 new HashMap<>(dependency.getArtifact().getProperties());
232 systemDependencyScope.setSystemPath(properties, null);
233 management.setProperties(properties);
234 }
235 }
236
237
238
239 if (systemDependencyScope != null
240 && (scope != null && systemDependencyScope.is(scope.getValue())
241 || (scope == null && systemDependencyScope.is(dependency.getScope())))) {
242 Holder<String> localPath = managedLocalPaths.get(key);
243 if (localPath != null) {
244 if (management == null) {
245 management = new DependencyManagement();
246 }
247 HashMap<String, String> properties =
248 new HashMap<>(dependency.getArtifact().getProperties());
249 systemDependencyScope.setSystemPath(properties, localPath.getValue());
250 management.setProperties(properties);
251 }
252 }
253
254
255
256 Holder<Boolean> optional = managedOptionals.get(key);
257 if (optional != null && isApplicable(optional)) {
258 if (management == null) {
259 management = new DependencyManagement();
260 }
261 management.setOptional(optional.getValue());
262 }
263 }
264
265
266
267
268
269
270 Collection<Holder<Collection<Exclusion>>> exclusions = managedExclusions.get(key);
271 if (exclusions != null) {
272 if (management == null) {
273 management = new DependencyManagement();
274 }
275 Collection<Exclusion> result = new LinkedHashSet<>(dependency.getExclusions());
276 for (Holder<Collection<Exclusion>> exclusion : exclusions) {
277 result.addAll(exclusion.getValue());
278 }
279 management.setExclusions(result);
280 }
281
282 return management;
283 }
284
285
286
287
288 protected boolean isDerived() {
289 return depth < deriveUntil;
290 }
291
292
293
294
295 protected boolean isApplied() {
296 return depth >= applyFrom;
297 }
298
299
300
301
302 protected boolean isApplicable(Holder<?> holder) {
303
304
305
306
307 return holder.getDepth() == 0 || depth > holder.getDepth() + 1;
308 }
309
310 @Override
311 public boolean equals(Object obj) {
312 if (this == obj) {
313 return true;
314 } else if (null == obj || !getClass().equals(obj.getClass())) {
315 return false;
316 }
317
318 AbstractDependencyManager that = (AbstractDependencyManager) obj;
319
320 return depth == that.depth
321 && managedVersions.equals(that.managedVersions)
322 && managedScopes.equals(that.managedScopes)
323 && managedOptionals.equals(that.managedOptionals)
324 && managedExclusions.equals(that.managedExclusions);
325 }
326
327 @Override
328 public int hashCode() {
329 return hashCode;
330 }
331
332 protected static class Key {
333 private final Artifact artifact;
334 private final int hashCode;
335
336 Key(Artifact artifact) {
337 this.artifact = artifact;
338 this.hashCode = Objects.hash(
339 artifact.getArtifactId(), artifact.getGroupId(), artifact.getExtension(), artifact.getClassifier());
340 }
341
342 @Override
343 public boolean equals(Object obj) {
344 if (obj == this) {
345 return true;
346 } else if (!(obj instanceof Key)) {
347 return false;
348 }
349 Key that = (Key) obj;
350 return artifact.getArtifactId().equals(that.artifact.getArtifactId())
351 && artifact.getGroupId().equals(that.artifact.getGroupId())
352 && artifact.getExtension().equals(that.artifact.getExtension())
353 && artifact.getClassifier().equals(that.artifact.getClassifier());
354 }
355
356 @Override
357 public int hashCode() {
358 return hashCode;
359 }
360
361 @Override
362 public String toString() {
363 return String.valueOf(artifact);
364 }
365 }
366
367 protected static class Holder<T> {
368 private final int depth;
369 private final T value;
370 private final int hashCode;
371
372 Holder(int depth, T value) {
373 this.depth = depth;
374 this.value = requireNonNull(value);
375 this.hashCode = Objects.hash(depth, value);
376 }
377
378 public int getDepth() {
379 return depth;
380 }
381
382 public T getValue() {
383 return value;
384 }
385
386 @Override
387 public boolean equals(Object o) {
388 if (!(o instanceof Holder)) {
389 return false;
390 }
391 Holder<?> holder = (Holder<?>) o;
392 return depth == holder.depth && Objects.equals(value, holder.value);
393 }
394
395 @Override
396 public int hashCode() {
397 return hashCode;
398 }
399 }
400 }