View Javadoc
1   package org.eclipse.aether.internal.impl.collect;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.LinkedHashMap;
28  import java.util.List;
29  import java.util.Map;
30  import static java.util.Objects.requireNonNull;
31  
32  import javax.inject.Inject;
33  import javax.inject.Named;
34  
35  import org.eclipse.aether.DefaultRepositorySystemSession;
36  import org.eclipse.aether.RepositoryException;
37  import org.eclipse.aether.RepositorySystemSession;
38  import org.eclipse.aether.RequestTrace;
39  import org.eclipse.aether.artifact.Artifact;
40  import org.eclipse.aether.artifact.ArtifactProperties;
41  import org.eclipse.aether.collection.CollectRequest;
42  import org.eclipse.aether.collection.CollectResult;
43  import org.eclipse.aether.collection.DependencyCollectionException;
44  import org.eclipse.aether.collection.DependencyGraphTransformer;
45  import org.eclipse.aether.collection.DependencyManagement;
46  import org.eclipse.aether.collection.DependencyManager;
47  import org.eclipse.aether.collection.DependencySelector;
48  import org.eclipse.aether.collection.DependencyTraverser;
49  import org.eclipse.aether.collection.VersionFilter;
50  import org.eclipse.aether.graph.DefaultDependencyNode;
51  import org.eclipse.aether.graph.Dependency;
52  import org.eclipse.aether.graph.DependencyNode;
53  import org.eclipse.aether.graph.Exclusion;
54  import org.eclipse.aether.impl.ArtifactDescriptorReader;
55  import org.eclipse.aether.impl.DependencyCollector;
56  import org.eclipse.aether.impl.RemoteRepositoryManager;
57  import org.eclipse.aether.impl.VersionRangeResolver;
58  import org.eclipse.aether.repository.ArtifactRepository;
59  import org.eclipse.aether.repository.RemoteRepository;
60  import org.eclipse.aether.resolution.ArtifactDescriptorException;
61  import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
62  import org.eclipse.aether.resolution.ArtifactDescriptorResult;
63  import org.eclipse.aether.resolution.VersionRangeRequest;
64  import org.eclipse.aether.resolution.VersionRangeResolutionException;
65  import org.eclipse.aether.resolution.VersionRangeResult;
66  import org.eclipse.aether.spi.locator.Service;
67  import org.eclipse.aether.spi.locator.ServiceLocator;
68  import org.eclipse.aether.util.ConfigUtils;
69  import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
70  import org.eclipse.aether.util.graph.transformer.TransformationContextKeys;
71  import org.eclipse.aether.version.Version;
72  import org.slf4j.Logger;
73  import org.slf4j.LoggerFactory;
74  
75  /**
76   */
77  @Named
78  public class DefaultDependencyCollector
79      implements DependencyCollector, Service
80  {
81  
82      private static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions";
83  
84      private static final int CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT = 50;
85  
86      private static final String CONFIG_PROP_MAX_CYCLES = "aether.dependencyCollector.maxCycles";
87  
88      private static final int CONFIG_PROP_MAX_CYCLES_DEFAULT = 10;
89  
90      private static final Logger LOGGER = LoggerFactory.getLogger( DefaultDependencyCollector.class );
91  
92      private RemoteRepositoryManager remoteRepositoryManager;
93  
94      private ArtifactDescriptorReader descriptorReader;
95  
96      private VersionRangeResolver versionRangeResolver;
97  
98      public DefaultDependencyCollector()
99      {
100         // enables default constructor
101     }
102 
103     @Inject
104     DefaultDependencyCollector( RemoteRepositoryManager remoteRepositoryManager,
105                                 ArtifactDescriptorReader artifactDescriptorReader,
106                                 VersionRangeResolver versionRangeResolver )
107     {
108         setRemoteRepositoryManager( remoteRepositoryManager );
109         setArtifactDescriptorReader( artifactDescriptorReader );
110         setVersionRangeResolver( versionRangeResolver );
111     }
112 
113     public void initService( ServiceLocator locator )
114     {
115         setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) );
116         setArtifactDescriptorReader( locator.getService( ArtifactDescriptorReader.class ) );
117         setVersionRangeResolver( locator.getService( VersionRangeResolver.class ) );
118     }
119 
120     public DefaultDependencyCollector setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager )
121     {
122         this.remoteRepositoryManager =
123                 requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" );
124         return this;
125     }
126 
127     public DefaultDependencyCollector setArtifactDescriptorReader( ArtifactDescriptorReader artifactDescriptorReader )
128     {
129         descriptorReader = requireNonNull( artifactDescriptorReader, "artifact descriptor reader cannot be null" );
130         return this;
131     }
132 
133     public DefaultDependencyCollector setVersionRangeResolver( VersionRangeResolver versionRangeResolver )
134     {
135         this.versionRangeResolver =
136                 requireNonNull( versionRangeResolver, "version range resolver cannot be null" );
137         return this;
138     }
139 
140     @SuppressWarnings( "checkstyle:methodlength" )
141     public CollectResult collectDependencies( RepositorySystemSession session, CollectRequest request )
142         throws DependencyCollectionException
143     {
144         session = optimizeSession( session );
145 
146         RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
147 
148         CollectResult result = new CollectResult( request );
149 
150         DependencySelector depSelector = session.getDependencySelector();
151         DependencyManager depManager = session.getDependencyManager();
152         DependencyTraverser depTraverser = session.getDependencyTraverser();
153         VersionFilter verFilter = session.getVersionFilter();
154 
155         Dependency root = request.getRoot();
156         List<RemoteRepository> repositories = request.getRepositories();
157         List<Dependency> dependencies = request.getDependencies();
158         List<Dependency> managedDependencies = request.getManagedDependencies();
159 
160         Map<String, Object> stats = LOGGER.isDebugEnabled() ? new LinkedHashMap<String, Object>() : null;
161         long time1 = System.nanoTime();
162 
163         DefaultDependencyNode node;
164         if ( root != null )
165         {
166             List<? extends Version> versions;
167             VersionRangeResult rangeResult;
168             try
169             {
170                 VersionRangeRequest rangeRequest =
171                     new VersionRangeRequest( root.getArtifact(), request.getRepositories(),
172                                              request.getRequestContext() );
173                 rangeRequest.setTrace( trace );
174                 rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest );
175                 versions = filterVersions( root, rangeResult, verFilter, new DefaultVersionFilterContext( session ) );
176             }
177             catch ( VersionRangeResolutionException e )
178             {
179                 result.addException( e );
180                 throw new DependencyCollectionException( result, e.getMessage() );
181             }
182 
183             Version version = versions.get( versions.size() - 1 );
184             root = root.setArtifact( root.getArtifact().setVersion( version.toString() ) );
185 
186             ArtifactDescriptorResult descriptorResult;
187             try
188             {
189                 ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest();
190                 descriptorRequest.setArtifact( root.getArtifact() );
191                 descriptorRequest.setRepositories( request.getRepositories() );
192                 descriptorRequest.setRequestContext( request.getRequestContext() );
193                 descriptorRequest.setTrace( trace );
194                 if ( isLackingDescriptor( root.getArtifact() ) )
195                 {
196                     descriptorResult = new ArtifactDescriptorResult( descriptorRequest );
197                 }
198                 else
199                 {
200                     descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest );
201                 }
202             }
203             catch ( ArtifactDescriptorException e )
204             {
205                 result.addException( e );
206                 throw new DependencyCollectionException( result, e.getMessage() );
207             }
208 
209             root = root.setArtifact( descriptorResult.getArtifact() );
210 
211             if ( !session.isIgnoreArtifactDescriptorRepositories() )
212             {
213                 repositories = remoteRepositoryManager.aggregateRepositories( session, repositories,
214                                                                               descriptorResult.getRepositories(),
215                                                                               true );
216             }
217             dependencies = mergeDeps( dependencies, descriptorResult.getDependencies() );
218             managedDependencies = mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() );
219 
220             node = new DefaultDependencyNode( root );
221             node.setRequestContext( request.getRequestContext() );
222             node.setRelocations( descriptorResult.getRelocations() );
223             node.setVersionConstraint( rangeResult.getVersionConstraint() );
224             node.setVersion( version );
225             node.setAliases( descriptorResult.getAliases() );
226             node.setRepositories( request.getRepositories() );
227         }
228         else
229         {
230             node = new DefaultDependencyNode( request.getRootArtifact() );
231             node.setRequestContext( request.getRequestContext() );
232             node.setRepositories( request.getRepositories() );
233         }
234 
235         result.setRoot( node );
236 
237         boolean traverse = root == null || depTraverser == null || depTraverser.traverseDependency( root );
238         String errorPath = null;
239         if ( traverse && !dependencies.isEmpty() )
240         {
241             DataPool pool = new DataPool( session );
242 
243             NodeStack nodes = new NodeStack();
244             nodes.push( node );
245 
246             DefaultDependencyCollectionContext context =
247                 new DefaultDependencyCollectionContext( session, request.getRootArtifact(), root, managedDependencies );
248 
249             DefaultVersionFilterContext versionContext = new DefaultVersionFilterContext( session );
250 
251             Args args = new Args( session, trace, pool, nodes, context, versionContext, request );
252             Results results = new Results( result, session );
253 
254             process( args, results, dependencies, repositories,
255                      depSelector != null ? depSelector.deriveChildSelector( context ) : null,
256                      depManager != null ? depManager.deriveChildManager( context ) : null,
257                      depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null,
258                      verFilter != null ? verFilter.deriveChildFilter( context ) : null );
259 
260             errorPath = results.errorPath;
261         }
262 
263         long time2 = System.nanoTime();
264 
265         DependencyGraphTransformer transformer = session.getDependencyGraphTransformer();
266         if ( transformer != null )
267         {
268             try
269             {
270                 DefaultDependencyGraphTransformationContext context =
271                     new DefaultDependencyGraphTransformationContext( session );
272                 context.put( TransformationContextKeys.STATS, stats );
273                 result.setRoot( transformer.transformGraph( node, context ) );
274             }
275             catch ( RepositoryException e )
276             {
277                 result.addException( e );
278             }
279         }
280 
281         if ( stats != null )
282         {
283             long time3 = System.nanoTime();
284             stats.put( "DefaultDependencyCollector.collectTime", time2 - time1 );
285             stats.put( "DefaultDependencyCollector.transformTime", time3 - time2 );
286             LOGGER.debug( "Dependency collection stats: " + stats );
287         }
288 
289         if ( errorPath != null )
290         {
291             throw new DependencyCollectionException( result, "Failed to collect dependencies at " + errorPath );
292         }
293         if ( !result.getExceptions().isEmpty() )
294         {
295             throw new DependencyCollectionException( result );
296         }
297 
298         return result;
299     }
300 
301     private static RepositorySystemSession optimizeSession( RepositorySystemSession session )
302     {
303         DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session );
304         optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) );
305         return optimized;
306     }
307 
308     private List<Dependency> mergeDeps( List<Dependency> dominant, List<Dependency> recessive )
309     {
310         List<Dependency> result;
311         if ( dominant == null || dominant.isEmpty() )
312         {
313             result = recessive;
314         }
315         else if ( recessive == null || recessive.isEmpty() )
316         {
317             result = dominant;
318         }
319         else
320         {
321             int initialCapacity = dominant.size() + recessive.size();
322             result = new ArrayList<>( initialCapacity );
323             Collection<String> ids = new HashSet<String>( initialCapacity, 1.0f );
324             for ( Dependency dependency : dominant )
325             {
326                 ids.add( getId( dependency.getArtifact() ) );
327                 result.add( dependency );
328             }
329             for ( Dependency dependency : recessive )
330             {
331                 if ( !ids.contains( getId( dependency.getArtifact() ) ) )
332                 {
333                     result.add( dependency );
334                 }
335             }
336         }
337         return result;
338     }
339 
340     private static String getId( Artifact a )
341     {
342         return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension();
343     }
344 
345     @SuppressWarnings( "checkstyle:parameternumber" )
346     private void process( final Args args, Results results, List<Dependency> dependencies,
347                           List<RemoteRepository> repositories, DependencySelector depSelector,
348                           DependencyManager depManager, DependencyTraverser depTraverser, VersionFilter verFilter )
349     {
350         for ( Dependency dependency : dependencies )
351         {
352             processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter,
353                                dependency );
354         }
355     }
356 
357     @SuppressWarnings( "checkstyle:parameternumber" )
358     private void processDependency( Args args, Results results, List<RemoteRepository> repositories,
359                                     DependencySelector depSelector, DependencyManager depManager,
360                                     DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency )
361     {
362 
363         List<Artifact> relocations = Collections.emptyList();
364         boolean disableVersionManagement = false;
365         processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency,
366                            relocations, disableVersionManagement );
367     }
368 
369     @SuppressWarnings( "checkstyle:parameternumber" )
370     private void processDependency( Args args, Results results, List<RemoteRepository> repositories,
371                                     DependencySelector depSelector, DependencyManager depManager,
372                                     DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency,
373                                     List<Artifact> relocations, boolean disableVersionManagement )
374     {
375 
376         if ( depSelector != null && !depSelector.selectDependency( dependency ) )
377         {
378             return;
379         }
380 
381         PremanagedDependency preManaged =
382             PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState );
383         dependency = preManaged.managedDependency;
384 
385         boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() );
386 
387         boolean traverse = !noDescriptor && ( depTraverser == null || depTraverser.traverseDependency( dependency ) );
388 
389         List<? extends Version> versions;
390         VersionRangeResult rangeResult;
391         try
392         {
393             VersionRangeRequest rangeRequest = createVersionRangeRequest( args, repositories, dependency );
394 
395             rangeResult = cachedResolveRangeResult( rangeRequest, args.pool, args.session );
396 
397             versions = filterVersions( dependency, rangeResult, verFilter, args.versionContext );
398         }
399         catch ( VersionRangeResolutionException e )
400         {
401             results.addException( dependency, e, args.nodes );
402             return;
403         }
404 
405         for ( Version version : versions )
406         {
407             Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() );
408             Dependency d = dependency.setArtifact( originalArtifact );
409 
410             ArtifactDescriptorRequest descriptorRequest = createArtifactDescriptorRequest( args, repositories, d );
411 
412             final ArtifactDescriptorResult descriptorResult =
413                 getArtifactDescriptorResult( args, results, noDescriptor, d, descriptorRequest );
414             if ( descriptorResult != null )
415             {
416                 d = d.setArtifact( descriptorResult.getArtifact() );
417 
418                 DependencyNode node = args.nodes.top();
419 
420                 int cycleEntry = args.nodes.find( d.getArtifact() );
421                 if ( cycleEntry >= 0 )
422                 {
423                     results.addCycle( args.nodes, cycleEntry, d );
424                     DependencyNode cycleNode = args.nodes.get( cycleEntry );
425                     if ( cycleNode.getDependency() != null )
426                     {
427                         DefaultDependencyNode child =
428                             createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult,
429                                                   cycleNode );
430                         node.getChildren().add( child );
431                         continue;
432                     }
433                 }
434 
435                 if ( !descriptorResult.getRelocations().isEmpty() )
436                 {
437                     boolean disableVersionManagementSubsequently =
438                         originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() )
439                             && originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() );
440 
441                     processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d,
442                                        descriptorResult.getRelocations(), disableVersionManagementSubsequently );
443                     return;
444                 }
445                 else
446                 {
447                     d = args.pool.intern( d.setArtifact( args.pool.intern( d.getArtifact() ) ) );
448 
449                     List<RemoteRepository> repos =
450                         getRemoteRepositories( rangeResult.getRepository( version ), repositories );
451 
452                     DefaultDependencyNode child =
453                         createDependencyNode( relocations, preManaged, rangeResult, version, d,
454                                               descriptorResult.getAliases(), repos, args.request.getRequestContext() );
455 
456                     node.getChildren().add( child );
457 
458                     boolean recurse = traverse && !descriptorResult.getDependencies().isEmpty();
459                     if ( recurse )
460                     {
461                         doRecurse( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d,
462                                    descriptorResult, child );
463                     }
464                 }
465             }
466             else
467             {
468                 DependencyNode node = args.nodes.top();
469                 List<RemoteRepository> repos =
470                     getRemoteRepositories( rangeResult.getRepository( version ), repositories );
471                 DefaultDependencyNode child =
472                     createDependencyNode( relocations, preManaged, rangeResult, version, d, null, repos,
473                                           args.request.getRequestContext() );
474                 node.getChildren().add( child );
475             }
476         }
477     }
478 
479     @SuppressWarnings( "checkstyle:parameternumber" )
480     private void doRecurse( Args args, Results results, List<RemoteRepository> repositories,
481                             DependencySelector depSelector, DependencyManager depManager,
482                             DependencyTraverser depTraverser, VersionFilter verFilter, Dependency d,
483                             ArtifactDescriptorResult descriptorResult, DefaultDependencyNode child )
484     {
485         DefaultDependencyCollectionContext context = args.collectionContext;
486         context.set( d, descriptorResult.getManagedDependencies() );
487 
488         DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector( context ) : null;
489         DependencyManager childManager = depManager != null ? depManager.deriveChildManager( context ) : null;
490         DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null;
491         VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null;
492 
493         final List<RemoteRepository> childRepos =
494             args.ignoreRepos
495                 ? repositories
496                 : remoteRepositoryManager.aggregateRepositories( args.session, repositories,
497                                                                  descriptorResult.getRepositories(), true );
498 
499         Object key =
500             args.pool.toKey( d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter );
501 
502         List<DependencyNode> children = args.pool.getChildren( key );
503         if ( children == null )
504         {
505             args.pool.putChildren( key, child.getChildren() );
506 
507             args.nodes.push( child );
508 
509             process( args, results, descriptorResult.getDependencies(), childRepos, childSelector, childManager,
510                      childTraverser, childFilter );
511 
512             args.nodes.pop();
513         }
514         else
515         {
516             child.setChildren( children );
517         }
518     }
519 
520     private ArtifactDescriptorResult getArtifactDescriptorResult( Args args, Results results, boolean noDescriptor,
521                                                                   Dependency d,
522                                                                   ArtifactDescriptorRequest descriptorRequest )
523     {
524         return noDescriptor
525                    ? new ArtifactDescriptorResult( descriptorRequest )
526                    : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, args );
527 
528     }
529 
530     private ArtifactDescriptorResult resolveCachedArtifactDescriptor( DataPool pool,
531                                                                       ArtifactDescriptorRequest descriptorRequest,
532                                                                       RepositorySystemSession session, Dependency d,
533                                                                       Results results, Args args )
534     {
535         Object key = pool.toKey( descriptorRequest );
536         ArtifactDescriptorResult descriptorResult = pool.getDescriptor( key, descriptorRequest );
537         if ( descriptorResult == null )
538         {
539             try
540             {
541                 descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest );
542                 pool.putDescriptor( key, descriptorResult );
543             }
544             catch ( ArtifactDescriptorException e )
545             {
546                 results.addException( d, e, args.nodes );
547                 pool.putDescriptor( key, e );
548                 return null;
549             }
550 
551         }
552         else if ( descriptorResult == DataPool.NO_DESCRIPTOR )
553         {
554             return null;
555         }
556 
557         return descriptorResult;
558     }
559 
560     @SuppressWarnings( "checkstyle:parameternumber" )
561     private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations,
562                                                                PremanagedDependency preManaged,
563                                                                VersionRangeResult rangeResult, Version version,
564                                                                Dependency d, Collection<Artifact> aliases,
565                                                                List<RemoteRepository> repos, String requestContext )
566     {
567         DefaultDependencyNode child = new DefaultDependencyNode( d );
568         preManaged.applyTo( child );
569         child.setRelocations( relocations );
570         child.setVersionConstraint( rangeResult.getVersionConstraint() );
571         child.setVersion( version );
572         child.setAliases( aliases );
573         child.setRepositories( repos );
574         child.setRequestContext( requestContext );
575         return child;
576     }
577 
578     private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations,
579                                                                PremanagedDependency preManaged,
580                                                                VersionRangeResult rangeResult, Version version,
581                                                                Dependency d, ArtifactDescriptorResult descriptorResult,
582                                                                DependencyNode cycleNode )
583     {
584         DefaultDependencyNode child =
585             createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(),
586                                   cycleNode.getRepositories(), cycleNode.getRequestContext() );
587         child.setChildren( cycleNode.getChildren() );
588         return child;
589     }
590 
591     private static ArtifactDescriptorRequest createArtifactDescriptorRequest( Args args,
592                                                                               List<RemoteRepository> repositories,
593                                                                               Dependency d )
594     {
595         ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest();
596         descriptorRequest.setArtifact( d.getArtifact() );
597         descriptorRequest.setRepositories( repositories );
598         descriptorRequest.setRequestContext( args.request.getRequestContext() );
599         descriptorRequest.setTrace( args.trace );
600         return descriptorRequest;
601     }
602 
603     private static VersionRangeRequest createVersionRangeRequest( Args args, List<RemoteRepository> repositories,
604                                                                   Dependency dependency )
605     {
606         VersionRangeRequest rangeRequest = new VersionRangeRequest();
607         rangeRequest.setArtifact( dependency.getArtifact() );
608         rangeRequest.setRepositories( repositories );
609         rangeRequest.setRequestContext( args.request.getRequestContext() );
610         rangeRequest.setTrace( args.trace );
611         return rangeRequest;
612     }
613 
614     private VersionRangeResult cachedResolveRangeResult( VersionRangeRequest rangeRequest, DataPool pool,
615                                                          RepositorySystemSession session )
616         throws VersionRangeResolutionException
617     {
618         Object key = pool.toKey( rangeRequest );
619         VersionRangeResult rangeResult = pool.getConstraint( key, rangeRequest );
620         if ( rangeResult == null )
621         {
622             rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest );
623             pool.putConstraint( key, rangeResult );
624         }
625         return rangeResult;
626     }
627 
628     private static boolean isLackingDescriptor( Artifact artifact )
629     {
630         return artifact.getProperty( ArtifactProperties.LOCAL_PATH, null ) != null;
631     }
632 
633     private static List<RemoteRepository> getRemoteRepositories( ArtifactRepository repository,
634                                                                  List<RemoteRepository> repositories )
635     {
636         if ( repository instanceof RemoteRepository )
637         {
638             return Collections.singletonList( (RemoteRepository) repository );
639         }
640         if ( repository != null )
641         {
642             return Collections.emptyList();
643         }
644         return repositories;
645     }
646 
647     private static List<? extends Version> filterVersions( Dependency dependency, VersionRangeResult rangeResult,
648                                                            VersionFilter verFilter,
649                                                            DefaultVersionFilterContext verContext )
650         throws VersionRangeResolutionException
651     {
652         if ( rangeResult.getVersions().isEmpty() )
653         {
654             throw new VersionRangeResolutionException( rangeResult,
655                                                        "No versions available for " + dependency.getArtifact()
656                                                            + " within specified range" );
657         }
658 
659         List<? extends Version> versions;
660         if ( verFilter != null && rangeResult.getVersionConstraint().getRange() != null )
661         {
662             verContext.set( dependency, rangeResult );
663             try
664             {
665                 verFilter.filterVersions( verContext );
666             }
667             catch ( RepositoryException e )
668             {
669                 throw new VersionRangeResolutionException( rangeResult,
670                                                            "Failed to filter versions for " + dependency.getArtifact()
671                                                                + ": " + e.getMessage(), e );
672             }
673             versions = verContext.get();
674             if ( versions.isEmpty() )
675             {
676                 throw new VersionRangeResolutionException( rangeResult,
677                                                            "No acceptable versions for " + dependency.getArtifact()
678                                                                + ": " + rangeResult.getVersions() );
679             }
680         }
681         else
682         {
683             versions = rangeResult.getVersions();
684         }
685         return versions;
686     }
687 
688     static class Args
689     {
690 
691         final RepositorySystemSession session;
692 
693         final boolean ignoreRepos;
694 
695         final boolean premanagedState;
696 
697         final RequestTrace trace;
698 
699         final DataPool pool;
700 
701         final NodeStack nodes;
702 
703         final DefaultDependencyCollectionContext collectionContext;
704 
705         final DefaultVersionFilterContext versionContext;
706 
707         final CollectRequest request;
708 
709         Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, NodeStack nodes,
710                      DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext,
711                      CollectRequest request )
712         {
713             this.session = session;
714             this.request = request;
715             this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories();
716             this.premanagedState = ConfigUtils.getBoolean( session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE );
717             this.trace = trace;
718             this.pool = pool;
719             this.nodes = nodes;
720             this.collectionContext = collectionContext;
721             this.versionContext = versionContext;
722         }
723 
724     }
725 
726     static class Results
727     {
728 
729         private final CollectResult result;
730 
731         final int maxExceptions;
732 
733         final int maxCycles;
734 
735         String errorPath;
736 
737         Results( CollectResult result, RepositorySystemSession session )
738         {
739             this.result = result;
740 
741             maxExceptions =
742                     ConfigUtils.getInteger( session, CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT, CONFIG_PROP_MAX_EXCEPTIONS );
743 
744             maxCycles = ConfigUtils.getInteger( session, CONFIG_PROP_MAX_CYCLES_DEFAULT, CONFIG_PROP_MAX_CYCLES );
745         }
746 
747         public void addException( Dependency dependency, Exception e, NodeStack nodes )
748         {
749             if ( maxExceptions < 0 || result.getExceptions().size() < maxExceptions )
750             {
751                 result.addException( e );
752                 if ( errorPath == null )
753                 {
754                     StringBuilder buffer = new StringBuilder( 256 );
755                     for ( int i = 0; i < nodes.size(); i++ )
756                     {
757                         if ( buffer.length() > 0 )
758                         {
759                             buffer.append( " -> " );
760                         }
761                         Dependency dep = nodes.get( i ).getDependency();
762                         if ( dep != null )
763                         {
764                             buffer.append( dep.getArtifact() );
765                         }
766                     }
767                     if ( buffer.length() > 0 )
768                     {
769                         buffer.append( " -> " );
770                     }
771                     buffer.append( dependency.getArtifact() );
772                     errorPath = buffer.toString();
773                 }
774             }
775         }
776 
777         public void addCycle( NodeStack nodes, int cycleEntry, Dependency dependency )
778         {
779             if ( maxCycles < 0 || result.getCycles().size() < maxCycles )
780             {
781                 result.addCycle( new DefaultDependencyCycle( nodes, cycleEntry, dependency ) );
782             }
783         }
784 
785     }
786 
787     static class PremanagedDependency
788     {
789 
790         final String premanagedVersion;
791 
792         final String premanagedScope;
793 
794         final Boolean premanagedOptional;
795 
796         /**
797          * @since 1.1.0
798          */
799         final Collection<Exclusion> premanagedExclusions;
800 
801         /**
802          * @since 1.1.0
803          */
804         final Map<String, String> premanagedProperties;
805 
806         final int managedBits;
807 
808         final Dependency managedDependency;
809 
810         final boolean premanagedState;
811 
812         @SuppressWarnings( "checkstyle:parameternumber" )
813         PremanagedDependency( String premanagedVersion, String premanagedScope, Boolean premanagedOptional,
814                               Collection<Exclusion> premanagedExclusions, Map<String, String> premanagedProperties,
815                               int managedBits, Dependency managedDependency, boolean premanagedState )
816         {
817             this.premanagedVersion = premanagedVersion;
818             this.premanagedScope = premanagedScope;
819             this.premanagedOptional = premanagedOptional;
820             this.premanagedExclusions =
821                 premanagedExclusions != null
822                     ? Collections.unmodifiableCollection( new ArrayList<>( premanagedExclusions ) )
823                     : null;
824 
825             this.premanagedProperties =
826                 premanagedProperties != null
827                     ? Collections.unmodifiableMap( new HashMap<>( premanagedProperties ) )
828                     : null;
829 
830             this.managedBits = managedBits;
831             this.managedDependency = managedDependency;
832             this.premanagedState = premanagedState;
833         }
834 
835         static PremanagedDependency create( DependencyManager depManager, Dependency dependency,
836                                             boolean disableVersionManagement, boolean premanagedState )
837         {
838             DependencyManagement depMngt = depManager != null ? depManager.manageDependency( dependency ) : null;
839 
840             int managedBits = 0;
841             String premanagedVersion = null;
842             String premanagedScope = null;
843             Boolean premanagedOptional = null;
844             Collection<Exclusion> premanagedExclusions = null;
845             Map<String, String> premanagedProperties = null;
846 
847             if ( depMngt != null )
848             {
849                 if ( depMngt.getVersion() != null && !disableVersionManagement )
850                 {
851                     Artifact artifact = dependency.getArtifact();
852                     premanagedVersion = artifact.getVersion();
853                     dependency = dependency.setArtifact( artifact.setVersion( depMngt.getVersion() ) );
854                     managedBits |= DependencyNode.MANAGED_VERSION;
855                 }
856                 if ( depMngt.getProperties() != null )
857                 {
858                     Artifact artifact = dependency.getArtifact();
859                     premanagedProperties = artifact.getProperties();
860                     dependency = dependency.setArtifact( artifact.setProperties( depMngt.getProperties() ) );
861                     managedBits |= DependencyNode.MANAGED_PROPERTIES;
862                 }
863                 if ( depMngt.getScope() != null )
864                 {
865                     premanagedScope = dependency.getScope();
866                     dependency = dependency.setScope( depMngt.getScope() );
867                     managedBits |= DependencyNode.MANAGED_SCOPE;
868                 }
869                 if ( depMngt.getOptional() != null )
870                 {
871                     premanagedOptional = dependency.isOptional();
872                     dependency = dependency.setOptional( depMngt.getOptional() );
873                     managedBits |= DependencyNode.MANAGED_OPTIONAL;
874                 }
875                 if ( depMngt.getExclusions() != null )
876                 {
877                     premanagedExclusions = dependency.getExclusions();
878                     dependency = dependency.setExclusions( depMngt.getExclusions() );
879                     managedBits |= DependencyNode.MANAGED_EXCLUSIONS;
880                 }
881             }
882             return new PremanagedDependency( premanagedVersion, premanagedScope, premanagedOptional,
883                                              premanagedExclusions, premanagedProperties, managedBits, dependency,
884                                              premanagedState );
885 
886         }
887 
888         public void applyTo( DefaultDependencyNode child )
889         {
890             child.setManagedBits( managedBits );
891             if ( premanagedState )
892             {
893                 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION, premanagedVersion );
894                 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE, premanagedScope );
895                 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_OPTIONAL, premanagedOptional );
896                 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_EXCLUSIONS, premanagedExclusions );
897                 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_PROPERTIES, premanagedProperties );
898             }
899         }
900 
901     }
902 
903 }