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