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