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