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.Collection;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.LinkedHashSet;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import org.eclipse.aether.artifact.Artifact;
29 import org.eclipse.aether.artifact.ArtifactProperties;
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.util.artifact.JavaScopes;
36
37 import static java.util.Objects.requireNonNull;
38
39
40
41
42
43
44
45 public final class TransitiveDependencyManager implements DependencyManager {
46
47 private final Map<Object, String> managedVersions;
48
49 private final Map<Object, String> managedScopes;
50
51 private final Map<Object, Boolean> managedOptionals;
52
53 private final Map<Object, String> managedLocalPaths;
54
55 private final Map<Object, Collection<Exclusion>> managedExclusions;
56
57 private final int depth;
58
59 private int hashCode;
60
61
62
63
64 public TransitiveDependencyManager() {
65 this(
66 0,
67 Collections.<Object, String>emptyMap(),
68 Collections.<Object, String>emptyMap(),
69 Collections.<Object, Boolean>emptyMap(),
70 Collections.<Object, String>emptyMap(),
71 Collections.<Object, Collection<Exclusion>>emptyMap());
72 }
73
74 private TransitiveDependencyManager(
75 final int depth,
76 final Map<Object, String> managedVersions,
77 final Map<Object, String> managedScopes,
78 final Map<Object, Boolean> managedOptionals,
79 final Map<Object, String> managedLocalPaths,
80 final Map<Object, Collection<Exclusion>> managedExclusions) {
81 super();
82 this.depth = depth;
83 this.managedVersions = managedVersions;
84 this.managedScopes = managedScopes;
85 this.managedOptionals = managedOptionals;
86 this.managedLocalPaths = managedLocalPaths;
87 this.managedExclusions = managedExclusions;
88 }
89
90 public DependencyManager deriveChildManager(final DependencyCollectionContext context) {
91 requireNonNull(context, "context cannot be null");
92 Map<Object, String> versions = managedVersions;
93 Map<Object, String> scopes = managedScopes;
94 Map<Object, Boolean> optionals = managedOptionals;
95 Map<Object, String> localPaths = managedLocalPaths;
96 Map<Object, Collection<Exclusion>> exclusions = managedExclusions;
97
98 for (Dependency managedDependency : context.getManagedDependencies()) {
99 Artifact artifact = managedDependency.getArtifact();
100 Object key = getKey(artifact);
101
102 String version = artifact.getVersion();
103 if (!version.isEmpty() && !versions.containsKey(key)) {
104 if (versions == managedVersions) {
105 versions = new HashMap<>(managedVersions);
106 }
107 versions.put(key, version);
108 }
109
110 String scope = managedDependency.getScope();
111 if (!scope.isEmpty() && !scopes.containsKey(key)) {
112 if (scopes == this.managedScopes) {
113 scopes = new HashMap<>(this.managedScopes);
114 }
115 scopes.put(key, scope);
116 }
117
118 Boolean optional = managedDependency.getOptional();
119 if (optional != null && !optionals.containsKey(key)) {
120 if (optionals == managedOptionals) {
121 optionals = new HashMap<>(managedOptionals);
122 }
123 optionals.put(key, optional);
124 }
125
126 String localPath = managedDependency.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null);
127 if (localPath != null && !localPaths.containsKey(key)) {
128 if (localPaths == this.managedLocalPaths) {
129 localPaths = new HashMap<>(managedLocalPaths);
130 }
131 localPaths.put(key, localPath);
132 }
133
134 if (!managedDependency.getExclusions().isEmpty()) {
135 if (exclusions == managedExclusions) {
136 exclusions = new HashMap<>(managedExclusions);
137 }
138 Collection<Exclusion> managed = exclusions.computeIfAbsent(key, k -> new LinkedHashSet<>());
139 managed.addAll(managedDependency.getExclusions());
140 }
141 }
142
143 return new TransitiveDependencyManager(depth + 1, versions, scopes, optionals, localPaths, exclusions);
144 }
145
146 public DependencyManagement manageDependency(Dependency dependency) {
147 requireNonNull(dependency, "dependency cannot be null");
148 DependencyManagement management = null;
149
150 Object key = getKey(dependency.getArtifact());
151
152 if (depth >= 2) {
153 String version = managedVersions.get(key);
154 if (version != null) {
155 management = new DependencyManagement();
156 management.setVersion(version);
157 }
158
159 String scope = managedScopes.get(key);
160 if (scope != null) {
161 if (management == null) {
162 management = new DependencyManagement();
163 }
164 management.setScope(scope);
165
166 if (!JavaScopes.SYSTEM.equals(scope)
167 && dependency.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null) != null) {
168 Map<String, String> properties =
169 new HashMap<>(dependency.getArtifact().getProperties());
170 properties.remove(ArtifactProperties.LOCAL_PATH);
171 management.setProperties(properties);
172 }
173 }
174
175 if ((JavaScopes.SYSTEM.equals(scope))
176 || (scope == null && JavaScopes.SYSTEM.equals(dependency.getScope()))) {
177 String localPath = managedLocalPaths.get(key);
178 if (localPath != null) {
179 if (management == null) {
180 management = new DependencyManagement();
181 }
182 Map<String, String> properties =
183 new HashMap<>(dependency.getArtifact().getProperties());
184 properties.put(ArtifactProperties.LOCAL_PATH, localPath);
185 management.setProperties(properties);
186 }
187 }
188
189 Boolean optional = managedOptionals.get(key);
190 if (optional != null) {
191 if (management == null) {
192 management = new DependencyManagement();
193 }
194 management.setOptional(optional);
195 }
196 }
197
198 Collection<Exclusion> exclusions = managedExclusions.get(key);
199 if (exclusions != null) {
200 if (management == null) {
201 management = new DependencyManagement();
202 }
203 Collection<Exclusion> result = new LinkedHashSet<>(dependency.getExclusions());
204 result.addAll(exclusions);
205 management.setExclusions(result);
206 }
207
208 return management;
209 }
210
211 private Object getKey(Artifact a) {
212 return new Key(a);
213 }
214
215 @Override
216 public boolean equals(final Object obj) {
217 boolean equal = obj instanceof TransitiveDependencyManager;
218
219 if (equal) {
220 final TransitiveDependencyManager that = (TransitiveDependencyManager) obj;
221 return depth == that.depth
222 && Objects.equals(managedVersions, that.managedVersions)
223 && Objects.equals(managedScopes, that.managedScopes)
224 && Objects.equals(managedOptionals, that.managedOptionals)
225 && Objects.equals(managedExclusions, that.managedExclusions);
226 }
227
228 return false;
229 }
230
231 @Override
232 public int hashCode() {
233 if (hashCode == 0) {
234 hashCode = Objects.hash(depth, managedVersions, managedScopes, managedOptionals, managedExclusions);
235 }
236 return hashCode;
237 }
238
239 static class Key {
240 private final Artifact artifact;
241
242 private final int hashCode;
243
244 Key(final Artifact artifact) {
245 this.artifact = artifact;
246 this.hashCode = Objects.hash(artifact.getGroupId(), artifact.getArtifactId());
247 }
248
249 @Override
250 public boolean equals(final Object obj) {
251 boolean equal = obj instanceof Key;
252
253 if (equal) {
254 final Key that = (Key) obj;
255 return Objects.equals(artifact.getArtifactId(), that.artifact.getArtifactId())
256 && Objects.equals(artifact.getGroupId(), that.artifact.getGroupId())
257 && Objects.equals(artifact.getExtension(), that.artifact.getExtension())
258 && Objects.equals(artifact.getClassifier(), that.artifact.getClassifier());
259 }
260
261 return false;
262 }
263
264 @Override
265 public int hashCode() {
266 return this.hashCode;
267 }
268 }
269 }