001package org.eclipse.aether.internal.impl.collect.df; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.Collections; 023import java.util.List; 024 025import javax.inject.Inject; 026import javax.inject.Named; 027import javax.inject.Singleton; 028 029import org.eclipse.aether.RepositorySystemSession; 030import org.eclipse.aether.RequestTrace; 031import org.eclipse.aether.artifact.Artifact; 032import org.eclipse.aether.collection.CollectRequest; 033import org.eclipse.aether.collection.DependencyManager; 034import org.eclipse.aether.collection.DependencySelector; 035import org.eclipse.aether.collection.DependencyTraverser; 036import org.eclipse.aether.collection.VersionFilter; 037import org.eclipse.aether.graph.DefaultDependencyNode; 038import org.eclipse.aether.graph.Dependency; 039import org.eclipse.aether.graph.DependencyNode; 040import org.eclipse.aether.impl.ArtifactDescriptorReader; 041import org.eclipse.aether.impl.RemoteRepositoryManager; 042import org.eclipse.aether.impl.VersionRangeResolver; 043import org.eclipse.aether.internal.impl.collect.DataPool; 044import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext; 045import org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle; 046import org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext; 047import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; 048import org.eclipse.aether.internal.impl.collect.PremanagedDependency; 049import org.eclipse.aether.repository.RemoteRepository; 050import org.eclipse.aether.resolution.ArtifactDescriptorException; 051import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 052import org.eclipse.aether.resolution.ArtifactDescriptorResult; 053import org.eclipse.aether.resolution.VersionRangeRequest; 054import org.eclipse.aether.resolution.VersionRangeResolutionException; 055import org.eclipse.aether.resolution.VersionRangeResult; 056import org.eclipse.aether.spi.locator.Service; 057import org.eclipse.aether.util.ConfigUtils; 058import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 059import org.eclipse.aether.version.Version; 060 061/** 062 * Depth-first {@link org.eclipse.aether.impl.DependencyCollector} (the "original" default). Originally 063 * this class was located a package higher (as "default" implementation). 064 * 065 * @since 1.8.0 066 */ 067@Singleton 068@Named( DfDependencyCollector.NAME ) 069public class DfDependencyCollector 070 extends DependencyCollectorDelegate implements Service 071{ 072 public static final String NAME = "df"; 073 074 /** 075 * Default ctor for SL. 076 * 077 * @deprecated Will be dropped once SL gone. 078 */ 079 @Deprecated 080 public DfDependencyCollector() 081 { 082 // enables default constructor 083 } 084 085 @Inject 086 DfDependencyCollector( RemoteRepositoryManager remoteRepositoryManager, 087 ArtifactDescriptorReader artifactDescriptorReader, 088 VersionRangeResolver versionRangeResolver ) 089 { 090 super( remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver ); 091 } 092 093 @SuppressWarnings( "checkstyle:parameternumber" ) 094 @Override 095 protected void doCollectDependencies( RepositorySystemSession session, RequestTrace trace, DataPool pool, 096 DefaultDependencyCollectionContext context, 097 DefaultVersionFilterContext versionContext, 098 CollectRequest request, DependencyNode node, 099 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}