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