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