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