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