001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl.collect.df; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.util.Collections; 026import java.util.List; 027 028import org.eclipse.aether.RepositorySystemSession; 029import org.eclipse.aether.RequestTrace; 030import org.eclipse.aether.artifact.Artifact; 031import org.eclipse.aether.collection.CollectRequest; 032import org.eclipse.aether.collection.DependencyManager; 033import org.eclipse.aether.collection.DependencySelector; 034import org.eclipse.aether.collection.DependencyTraverser; 035import org.eclipse.aether.collection.VersionFilter; 036import org.eclipse.aether.graph.DefaultDependencyNode; 037import org.eclipse.aether.graph.Dependency; 038import org.eclipse.aether.graph.DependencyNode; 039import org.eclipse.aether.impl.ArtifactDescriptorReader; 040import org.eclipse.aether.impl.RemoteRepositoryManager; 041import org.eclipse.aether.impl.VersionRangeResolver; 042import org.eclipse.aether.internal.impl.collect.DataPool; 043import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext; 044import org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle; 045import org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext; 046import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; 047import org.eclipse.aether.internal.impl.collect.PremanagedDependency; 048import org.eclipse.aether.repository.RemoteRepository; 049import org.eclipse.aether.resolution.ArtifactDescriptorException; 050import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 051import org.eclipse.aether.resolution.ArtifactDescriptorResult; 052import org.eclipse.aether.resolution.VersionRangeRequest; 053import org.eclipse.aether.resolution.VersionRangeResolutionException; 054import org.eclipse.aether.resolution.VersionRangeResult; 055import org.eclipse.aether.spi.locator.Service; 056import org.eclipse.aether.util.ConfigUtils; 057import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 058import org.eclipse.aether.version.Version; 059 060/** 061 * Depth-first {@link org.eclipse.aether.impl.DependencyCollector} (the "original" default). Originally 062 * this class was located a package higher (as "default" implementation). 063 * 064 * @since 1.8.0 065 */ 066@Singleton 067@Named(DfDependencyCollector.NAME) 068public class DfDependencyCollector extends DependencyCollectorDelegate implements Service { 069 public static final String NAME = "df"; 070 071 /** 072 * Default ctor for SL. 073 * 074 * @deprecated Will be dropped once SL gone. 075 */ 076 @Deprecated 077 public DfDependencyCollector() { 078 // enables default constructor 079 } 080 081 @Inject 082 public DfDependencyCollector( 083 RemoteRepositoryManager remoteRepositoryManager, 084 ArtifactDescriptorReader artifactDescriptorReader, 085 VersionRangeResolver versionRangeResolver) { 086 super(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver); 087 } 088 089 @SuppressWarnings("checkstyle:parameternumber") 090 @Override 091 protected void doCollectDependencies( 092 RepositorySystemSession session, 093 RequestTrace trace, 094 DataPool pool, 095 DefaultDependencyCollectionContext context, 096 DefaultVersionFilterContext versionContext, 097 CollectRequest request, 098 DependencyNode node, 099 List<RemoteRepository> repositories, 100 List<Dependency> dependencies, 101 List<Dependency> managedDependencies, 102 Results results) { 103 NodeStack nodes = new NodeStack(); 104 nodes.push(node); 105 106 Args args = new Args(session, pool, nodes, context, versionContext, request); 107 108 process( 109 args, 110 trace, 111 results, 112 dependencies, 113 repositories, 114 session.getDependencySelector() != null 115 ? session.getDependencySelector().deriveChildSelector(context) 116 : null, 117 session.getDependencyManager() != null 118 ? session.getDependencyManager().deriveChildManager(context) 119 : null, 120 session.getDependencyTraverser() != null 121 ? session.getDependencyTraverser().deriveChildTraverser(context) 122 : null, 123 session.getVersionFilter() != null ? session.getVersionFilter().deriveChildFilter(context) : null); 124 } 125 126 @SuppressWarnings("checkstyle:parameternumber") 127 private void process( 128 final Args args, 129 RequestTrace trace, 130 Results results, 131 List<Dependency> dependencies, 132 List<RemoteRepository> repositories, 133 DependencySelector depSelector, 134 DependencyManager depManager, 135 DependencyTraverser depTraverser, 136 VersionFilter verFilter) { 137 for (Dependency dependency : dependencies) { 138 processDependency( 139 args, trace, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency); 140 } 141 } 142 143 @SuppressWarnings("checkstyle:parameternumber") 144 private void processDependency( 145 Args args, 146 RequestTrace trace, 147 Results results, 148 List<RemoteRepository> repositories, 149 DependencySelector depSelector, 150 DependencyManager depManager, 151 DependencyTraverser depTraverser, 152 VersionFilter verFilter, 153 Dependency dependency) { 154 155 List<Artifact> relocations = Collections.emptyList(); 156 processDependency( 157 args, 158 trace, 159 results, 160 repositories, 161 depSelector, 162 depManager, 163 depTraverser, 164 verFilter, 165 dependency, 166 relocations, 167 false); 168 } 169 170 @SuppressWarnings("checkstyle:parameternumber") 171 private void processDependency( 172 Args args, 173 RequestTrace parent, 174 Results results, 175 List<RemoteRepository> repositories, 176 DependencySelector depSelector, 177 DependencyManager depManager, 178 DependencyTraverser depTraverser, 179 VersionFilter verFilter, 180 Dependency dependency, 181 List<Artifact> relocations, 182 boolean disableVersionManagement) { 183 if (depSelector != null && !depSelector.selectDependency(dependency)) { 184 return; 185 } 186 187 RequestTrace trace = collectStepTrace(parent, args.request.getRequestContext(), args.nodes.nodes, dependency); 188 PremanagedDependency preManaged = 189 PremanagedDependency.create(depManager, dependency, disableVersionManagement, args.premanagedState); 190 dependency = preManaged.getManagedDependency(); 191 192 boolean noDescriptor = isLackingDescriptor(dependency.getArtifact()); 193 194 boolean traverse = !noDescriptor && (depTraverser == null || depTraverser.traverseDependency(dependency)); 195 196 List<? extends Version> versions; 197 VersionRangeResult rangeResult; 198 try { 199 VersionRangeRequest rangeRequest = 200 createVersionRangeRequest(args.request.getRequestContext(), trace, repositories, dependency); 201 202 rangeResult = cachedResolveRangeResult(rangeRequest, args.pool, args.session); 203 204 versions = filterVersions(dependency, rangeResult, verFilter, args.versionContext); 205 } catch (VersionRangeResolutionException e) { 206 results.addException(dependency, e, args.nodes.nodes); 207 return; 208 } 209 210 for (Version version : versions) { 211 Artifact originalArtifact = dependency.getArtifact().setVersion(version.toString()); 212 Dependency d = dependency.setArtifact(originalArtifact); 213 214 ArtifactDescriptorRequest descriptorRequest = 215 createArtifactDescriptorRequest(args.request.getRequestContext(), trace, repositories, d); 216 217 final ArtifactDescriptorResult descriptorResult = 218 getArtifactDescriptorResult(args, results, noDescriptor, d, descriptorRequest); 219 if (descriptorResult != null) { 220 d = d.setArtifact(descriptorResult.getArtifact()); 221 222 DependencyNode node = args.nodes.top(); 223 224 int cycleEntry = DefaultDependencyCycle.find(args.nodes.nodes, d.getArtifact()); 225 if (cycleEntry >= 0) { 226 results.addCycle(args.nodes.nodes, cycleEntry, d); 227 DependencyNode cycleNode = args.nodes.get(cycleEntry); 228 if (cycleNode.getDependency() != null) { 229 DefaultDependencyNode child = createDependencyNode( 230 relocations, preManaged, rangeResult, version, d, descriptorResult, cycleNode); 231 node.getChildren().add(child); 232 continue; 233 } 234 } 235 236 if (!descriptorResult.getRelocations().isEmpty()) { 237 boolean disableVersionManagementSubsequently = 238 originalArtifact.getGroupId().equals(d.getArtifact().getGroupId()) 239 && originalArtifact 240 .getArtifactId() 241 .equals(d.getArtifact().getArtifactId()); 242 243 processDependency( 244 args, 245 parent, 246 results, 247 repositories, 248 depSelector, 249 depManager, 250 depTraverser, 251 verFilter, 252 d, 253 descriptorResult.getRelocations(), 254 disableVersionManagementSubsequently); 255 return; 256 } else { 257 d = args.pool.intern(d.setArtifact(args.pool.intern(d.getArtifact()))); 258 259 List<RemoteRepository> repos = 260 getRemoteRepositories(rangeResult.getRepository(version), repositories); 261 262 DefaultDependencyNode child = createDependencyNode( 263 relocations, 264 preManaged, 265 rangeResult, 266 version, 267 d, 268 descriptorResult.getAliases(), 269 repos, 270 args.request.getRequestContext()); 271 272 node.getChildren().add(child); 273 274 boolean recurse = 275 traverse && !descriptorResult.getDependencies().isEmpty(); 276 if (recurse) { 277 doRecurse( 278 args, 279 parent, 280 results, 281 repositories, 282 depSelector, 283 depManager, 284 depTraverser, 285 verFilter, 286 d, 287 descriptorResult, 288 child); 289 } 290 } 291 } else { 292 DependencyNode node = args.nodes.top(); 293 List<RemoteRepository> repos = getRemoteRepositories(rangeResult.getRepository(version), repositories); 294 DefaultDependencyNode child = createDependencyNode( 295 relocations, 296 preManaged, 297 rangeResult, 298 version, 299 d, 300 null, 301 repos, 302 args.request.getRequestContext()); 303 node.getChildren().add(child); 304 } 305 } 306 } 307 308 @SuppressWarnings("checkstyle:parameternumber") 309 private void doRecurse( 310 Args args, 311 RequestTrace trace, 312 Results results, 313 List<RemoteRepository> repositories, 314 DependencySelector depSelector, 315 DependencyManager depManager, 316 DependencyTraverser depTraverser, 317 VersionFilter verFilter, 318 Dependency d, 319 ArtifactDescriptorResult descriptorResult, 320 DefaultDependencyNode child) { 321 DefaultDependencyCollectionContext context = args.collectionContext; 322 context.set(d, descriptorResult.getManagedDependencies()); 323 324 DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector(context) : null; 325 DependencyManager childManager = depManager != null ? depManager.deriveChildManager(context) : null; 326 DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser(context) : null; 327 VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter(context) : null; 328 329 final List<RemoteRepository> childRepos = args.ignoreRepos 330 ? repositories 331 : remoteRepositoryManager.aggregateRepositories( 332 args.session, repositories, descriptorResult.getRepositories(), true); 333 334 Object key = 335 args.pool.toKey(d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter); 336 337 List<DependencyNode> children = args.pool.getChildren(key); 338 if (children == null) { 339 args.pool.putChildren(key, child.getChildren()); 340 341 args.nodes.push(child); 342 343 process( 344 args, 345 trace, 346 results, 347 descriptorResult.getDependencies(), 348 childRepos, 349 childSelector, 350 childManager, 351 childTraverser, 352 childFilter); 353 354 args.nodes.pop(); 355 } else { 356 child.setChildren(children); 357 } 358 } 359 360 private ArtifactDescriptorResult getArtifactDescriptorResult( 361 Args args, 362 Results results, 363 boolean noDescriptor, 364 Dependency d, 365 ArtifactDescriptorRequest descriptorRequest) { 366 return noDescriptor 367 ? new ArtifactDescriptorResult(descriptorRequest) 368 : resolveCachedArtifactDescriptor(args.pool, descriptorRequest, args.session, d, results, args); 369 } 370 371 private ArtifactDescriptorResult resolveCachedArtifactDescriptor( 372 DataPool pool, 373 ArtifactDescriptorRequest descriptorRequest, 374 RepositorySystemSession session, 375 Dependency d, 376 Results results, 377 Args args) { 378 Object key = pool.toKey(descriptorRequest); 379 ArtifactDescriptorResult descriptorResult = pool.getDescriptor(key, descriptorRequest); 380 if (descriptorResult == null) { 381 try { 382 descriptorResult = descriptorReader.readArtifactDescriptor(session, descriptorRequest); 383 pool.putDescriptor(key, descriptorResult); 384 } catch (ArtifactDescriptorException e) { 385 results.addException(d, e, args.nodes.nodes); 386 pool.putDescriptor(key, e); 387 return null; 388 } 389 390 } else if (descriptorResult == DataPool.NO_DESCRIPTOR) { 391 return null; 392 } 393 394 return descriptorResult; 395 } 396 397 static class Args { 398 399 final RepositorySystemSession session; 400 401 final boolean ignoreRepos; 402 403 final boolean premanagedState; 404 405 final DataPool pool; 406 407 final NodeStack nodes; 408 409 final DefaultDependencyCollectionContext collectionContext; 410 411 final DefaultVersionFilterContext versionContext; 412 413 final CollectRequest request; 414 415 Args( 416 RepositorySystemSession session, 417 DataPool pool, 418 NodeStack nodes, 419 DefaultDependencyCollectionContext collectionContext, 420 DefaultVersionFilterContext versionContext, 421 CollectRequest request) { 422 this.session = session; 423 this.request = request; 424 this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories(); 425 this.premanagedState = ConfigUtils.getBoolean(session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE); 426 this.pool = pool; 427 this.nodes = nodes; 428 this.collectionContext = collectionContext; 429 this.versionContext = versionContext; 430 } 431 } 432}