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.df;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.atomic.AtomicReference;
29
30 import org.eclipse.aether.RepositorySystemSession;
31 import org.eclipse.aether.RequestTrace;
32 import org.eclipse.aether.artifact.Artifact;
33 import org.eclipse.aether.collection.CollectRequest;
34 import org.eclipse.aether.collection.DependencyCollectionException;
35 import org.eclipse.aether.collection.DependencyManager;
36 import org.eclipse.aether.collection.DependencySelector;
37 import org.eclipse.aether.collection.DependencyTraverser;
38 import org.eclipse.aether.collection.VersionFilter;
39 import org.eclipse.aether.graph.DefaultDependencyNode;
40 import org.eclipse.aether.graph.Dependency;
41 import org.eclipse.aether.graph.DependencyNode;
42 import org.eclipse.aether.impl.ArtifactDescriptorReader;
43 import org.eclipse.aether.impl.RemoteRepositoryManager;
44 import org.eclipse.aether.impl.VersionRangeResolver;
45 import org.eclipse.aether.internal.impl.collect.DataPool;
46 import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext;
47 import org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle;
48 import org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext;
49 import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate;
50 import org.eclipse.aether.internal.impl.collect.PremanagedDependency;
51 import org.eclipse.aether.repository.RemoteRepository;
52 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
53 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
54 import org.eclipse.aether.resolution.VersionRangeRequest;
55 import org.eclipse.aether.resolution.VersionRangeResolutionException;
56 import org.eclipse.aether.resolution.VersionRangeResult;
57 import org.eclipse.aether.spi.artifact.decorator.ArtifactDecoratorFactory;
58 import org.eclipse.aether.util.ConfigUtils;
59 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
60 import org.eclipse.aether.version.Version;
61
62
63
64
65
66
67
68 @Singleton
69 @Named(DfDependencyCollector.NAME)
70 public class DfDependencyCollector extends DependencyCollectorDelegate {
71 public static final String NAME = "df";
72
73 @Inject
74 public DfDependencyCollector(
75 RemoteRepositoryManager remoteRepositoryManager,
76 ArtifactDescriptorReader artifactDescriptorReader,
77 VersionRangeResolver versionRangeResolver,
78 Map<String, ArtifactDecoratorFactory> artifactDecoratorFactories) {
79 super(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver, artifactDecoratorFactories);
80 }
81
82 @SuppressWarnings("checkstyle:parameternumber")
83 @Override
84 protected void doCollectDependencies(
85 RepositorySystemSession session,
86 RequestTrace trace,
87 DataPool pool,
88 DefaultDependencyCollectionContext context,
89 DefaultVersionFilterContext versionContext,
90 CollectRequest request,
91 DependencyNode node,
92 List<RemoteRepository> repositories,
93 List<Dependency> dependencies,
94 List<Dependency> managedDependencies,
95 Results results)
96 throws DependencyCollectionException {
97 NodeStack nodes = new NodeStack();
98 nodes.push(node);
99
100 Args args = new Args(session, pool, nodes, context, versionContext, request);
101
102 process(
103 args,
104 trace,
105 results,
106 dependencies,
107 repositories,
108 session.getDependencySelector() != null
109 ? session.getDependencySelector().deriveChildSelector(context)
110 : null,
111 session.getDependencyManager() != null
112 ? session.getDependencyManager().deriveChildManager(context)
113 : null,
114 session.getDependencyTraverser() != null
115 ? session.getDependencyTraverser().deriveChildTraverser(context)
116 : null,
117 session.getVersionFilter() != null ? session.getVersionFilter().deriveChildFilter(context) : null);
118
119 if (args.interruptedException.get() != null) {
120 throw new DependencyCollectionException(
121 results.getResult(), "Collection interrupted", args.interruptedException.get());
122 }
123 }
124
125 @SuppressWarnings("checkstyle:parameternumber")
126 private void process(
127 final Args args,
128 RequestTrace trace,
129 Results results,
130 List<Dependency> dependencies,
131 List<RemoteRepository> repositories,
132 DependencySelector depSelector,
133 DependencyManager depManager,
134 DependencyTraverser depTraverser,
135 VersionFilter verFilter) {
136 if (Thread.interrupted()) {
137 args.interruptedException.set(new InterruptedException());
138 }
139 if (args.interruptedException.get() != null) {
140 return;
141 }
142 for (Dependency dependency : dependencies) {
143 processDependency(
144 args, trace, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency);
145 }
146 }
147
148 @SuppressWarnings("checkstyle:parameternumber")
149 private void processDependency(
150 Args args,
151 RequestTrace trace,
152 Results results,
153 List<RemoteRepository> repositories,
154 DependencySelector depSelector,
155 DependencyManager depManager,
156 DependencyTraverser depTraverser,
157 VersionFilter verFilter,
158 Dependency dependency) {
159
160 List<Artifact> relocations = Collections.emptyList();
161 processDependency(
162 args,
163 trace,
164 results,
165 repositories,
166 depSelector,
167 depManager,
168 depTraverser,
169 verFilter,
170 dependency,
171 relocations,
172 false);
173 }
174
175 @SuppressWarnings("checkstyle:parameternumber")
176 private void processDependency(
177 Args args,
178 RequestTrace parent,
179 Results results,
180 List<RemoteRepository> repositories,
181 DependencySelector depSelector,
182 DependencyManager depManager,
183 DependencyTraverser depTraverser,
184 VersionFilter verFilter,
185 Dependency dependency,
186 List<Artifact> relocations,
187 boolean disableVersionManagement) {
188 if (depSelector != null && !depSelector.selectDependency(dependency)) {
189 return;
190 }
191
192 RequestTrace trace = collectStepTrace(parent, args.request.getRequestContext(), args.nodes.nodes, dependency);
193 PremanagedDependency preManaged =
194 PremanagedDependency.create(depManager, dependency, disableVersionManagement, args.premanagedState);
195 dependency = preManaged.getManagedDependency();
196
197 boolean noDescriptor = isLackingDescriptor(args.session, dependency.getArtifact());
198
199 boolean traverse = !noDescriptor && (depTraverser == null || depTraverser.traverseDependency(dependency));
200
201 List<? extends Version> versions;
202 VersionRangeResult rangeResult;
203 try {
204 VersionRangeRequest rangeRequest =
205 createVersionRangeRequest(args.request.getRequestContext(), trace, repositories, dependency);
206
207 rangeResult = cachedResolveRangeResult(rangeRequest, args.pool, args.session);
208
209 versions = filterVersions(dependency, rangeResult, verFilter, args.versionContext);
210 } catch (VersionRangeResolutionException e) {
211 results.addException(dependency, e, args.nodes.nodes);
212 return;
213 }
214
215 for (Version version : versions) {
216 Artifact originalArtifact = dependency.getArtifact().setVersion(version.toString());
217 Dependency d = dependency.setArtifact(originalArtifact);
218
219 ArtifactDescriptorRequest descriptorRequest =
220 createArtifactDescriptorRequest(args.request.getRequestContext(), trace, repositories, d);
221
222 final ArtifactDescriptorResult descriptorResult =
223 getArtifactDescriptorResult(args, results, noDescriptor, d, descriptorRequest);
224 if (descriptorResult != null) {
225 d = d.setArtifact(descriptorResult.getArtifact());
226
227 DependencyNode node = args.nodes.top();
228
229 int cycleEntry = DefaultDependencyCycle.find(args.nodes.nodes, d.getArtifact());
230 if (cycleEntry >= 0) {
231 results.addCycle(args.nodes.nodes, cycleEntry, d);
232 DependencyNode cycleNode = args.nodes.get(cycleEntry);
233 if (cycleNode.getDependency() != null) {
234 DefaultDependencyNode child = createDependencyNode(
235 relocations, preManaged, rangeResult, version, d, descriptorResult, cycleNode);
236 node.getChildren().add(child);
237 continue;
238 }
239 }
240
241 if (!descriptorResult.getRelocations().isEmpty()) {
242 boolean disableVersionManagementSubsequently =
243 originalArtifact.getGroupId().equals(d.getArtifact().getGroupId())
244 && originalArtifact
245 .getArtifactId()
246 .equals(d.getArtifact().getArtifactId());
247
248 processDependency(
249 args,
250 parent,
251 results,
252 repositories,
253 depSelector,
254 depManager,
255 depTraverser,
256 verFilter,
257 d,
258 descriptorResult.getRelocations(),
259 disableVersionManagementSubsequently);
260 return;
261 } else {
262 d = args.pool.intern(d.setArtifact(args.pool.intern(d.getArtifact())));
263
264 List<RemoteRepository> repos =
265 getRemoteRepositories(rangeResult.getRepository(version), repositories);
266
267 DefaultDependencyNode child = createDependencyNode(
268 relocations,
269 preManaged,
270 rangeResult,
271 version,
272 d,
273 descriptorResult.getAliases(),
274 repos,
275 args.request.getRequestContext());
276
277 node.getChildren().add(child);
278
279 boolean recurse =
280 traverse && !descriptorResult.getDependencies().isEmpty();
281 if (recurse) {
282 doRecurse(
283 args,
284 parent,
285 results,
286 repositories,
287 depSelector,
288 depManager,
289 depTraverser,
290 verFilter,
291 d,
292 descriptorResult,
293 child);
294 }
295 }
296 } else {
297 DependencyNode node = args.nodes.top();
298 List<RemoteRepository> repos = getRemoteRepositories(rangeResult.getRepository(version), repositories);
299 DefaultDependencyNode child = createDependencyNode(
300 relocations,
301 preManaged,
302 rangeResult,
303 version,
304 d,
305 null,
306 repos,
307 args.request.getRequestContext());
308 node.getChildren().add(child);
309 }
310 }
311 }
312
313 @SuppressWarnings("checkstyle:parameternumber")
314 private void doRecurse(
315 Args args,
316 RequestTrace trace,
317 Results results,
318 List<RemoteRepository> repositories,
319 DependencySelector depSelector,
320 DependencyManager depManager,
321 DependencyTraverser depTraverser,
322 VersionFilter verFilter,
323 Dependency d,
324 ArtifactDescriptorResult descriptorResult,
325 DefaultDependencyNode child) {
326 DefaultDependencyCollectionContext context = args.collectionContext.get();
327 args.collectionContext.compareAndSet(context, context.set(d, descriptorResult.getManagedDependencies()));
328 context = args.collectionContext.get();
329
330 DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector(context) : null;
331 DependencyManager childManager = depManager != null ? depManager.deriveChildManager(context) : null;
332 DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser(context) : null;
333 VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter(context) : null;
334
335 final List<RemoteRepository> childRepos = args.ignoreRepos
336 ? repositories
337 : remoteRepositoryManager.aggregateRepositories(
338 args.session, repositories, descriptorResult.getRepositories(), true);
339
340 Object key =
341 args.pool.toKey(d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter);
342
343 List<DependencyNode> children = args.pool.getChildren(key);
344 if (children == null) {
345 args.pool.putChildren(key, child.getChildren());
346
347 args.nodes.push(child);
348
349 process(
350 args,
351 trace,
352 results,
353 descriptorResult.getDependencies(),
354 childRepos,
355 childSelector,
356 childManager,
357 childTraverser,
358 childFilter);
359
360 args.nodes.pop();
361 } else {
362 child.setChildren(children);
363 }
364 }
365
366 private ArtifactDescriptorResult getArtifactDescriptorResult(
367 Args args,
368 Results results,
369 boolean noDescriptor,
370 Dependency d,
371 ArtifactDescriptorRequest descriptorRequest) {
372 return noDescriptor
373 ? new ArtifactDescriptorResult(descriptorRequest)
374 : resolveCachedArtifactDescriptor(
375 args.pool, descriptorRequest, args.session, d, results, args.nodes.nodes);
376 }
377
378 static class Args {
379
380 final RepositorySystemSession session;
381
382 final boolean ignoreRepos;
383
384 final boolean premanagedState;
385
386 final DataPool pool;
387
388 final NodeStack nodes;
389
390 final AtomicReference<DefaultDependencyCollectionContext> collectionContext;
391
392 final DefaultVersionFilterContext versionContext;
393
394 final CollectRequest request;
395
396 final AtomicReference<InterruptedException> interruptedException;
397
398 Args(
399 RepositorySystemSession session,
400 DataPool pool,
401 NodeStack nodes,
402 DefaultDependencyCollectionContext collectionContext,
403 DefaultVersionFilterContext versionContext,
404 CollectRequest request) {
405 this.session = session;
406 this.request = request;
407 this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories();
408 this.premanagedState = ConfigUtils.getBoolean(session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE);
409 this.pool = pool;
410 this.nodes = nodes;
411 this.collectionContext = new AtomicReference<>(collectionContext);
412 this.versionContext = versionContext;
413 this.interruptedException = new AtomicReference<>(null);
414 }
415 }
416 }