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.util.ConfigUtils; 056import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 057import org.eclipse.aether.version.Version; 058 059/** 060 * Depth-first {@link org.eclipse.aether.impl.DependencyCollector} (the "original" default). Originally 061 * this class was located a package higher (as "default" implementation). 062 * 063 * @since 1.8.0 064 */ 065@Singleton 066@Named(DfDependencyCollector.NAME) 067public class DfDependencyCollector extends DependencyCollectorDelegate { 068 public static final String NAME = "df"; 069 070 @Inject 071 public DfDependencyCollector( 072 RemoteRepositoryManager remoteRepositoryManager, 073 ArtifactDescriptorReader artifactDescriptorReader, 074 VersionRangeResolver versionRangeResolver) { 075 super(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver); 076 } 077 078 @SuppressWarnings("checkstyle:parameternumber") 079 @Override 080 protected void doCollectDependencies( 081 RepositorySystemSession session, 082 RequestTrace trace, 083 DataPool pool, 084 DefaultDependencyCollectionContext context, 085 DefaultVersionFilterContext versionContext, 086 CollectRequest request, 087 DependencyNode node, 088 List<RemoteRepository> repositories, 089 List<Dependency> dependencies, 090 List<Dependency> managedDependencies, 091 Results results) { 092 NodeStack nodes = new NodeStack(); 093 nodes.push(node); 094 095 Args args = new Args(session, pool, nodes, context, versionContext, request); 096 097 process( 098 args, 099 trace, 100 results, 101 dependencies, 102 repositories, 103 session.getDependencySelector() != null 104 ? session.getDependencySelector().deriveChildSelector(context) 105 : null, 106 session.getDependencyManager() != null 107 ? session.getDependencyManager().deriveChildManager(context) 108 : null, 109 session.getDependencyTraverser() != null 110 ? session.getDependencyTraverser().deriveChildTraverser(context) 111 : null, 112 session.getVersionFilter() != null ? session.getVersionFilter().deriveChildFilter(context) : null); 113 } 114 115 @SuppressWarnings("checkstyle:parameternumber") 116 private void process( 117 final Args args, 118 RequestTrace trace, 119 Results results, 120 List<Dependency> dependencies, 121 List<RemoteRepository> repositories, 122 DependencySelector depSelector, 123 DependencyManager depManager, 124 DependencyTraverser depTraverser, 125 VersionFilter verFilter) { 126 for (Dependency dependency : dependencies) { 127 processDependency( 128 args, trace, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency); 129 } 130 } 131 132 @SuppressWarnings("checkstyle:parameternumber") 133 private void processDependency( 134 Args args, 135 RequestTrace trace, 136 Results results, 137 List<RemoteRepository> repositories, 138 DependencySelector depSelector, 139 DependencyManager depManager, 140 DependencyTraverser depTraverser, 141 VersionFilter verFilter, 142 Dependency dependency) { 143 144 List<Artifact> relocations = Collections.emptyList(); 145 processDependency( 146 args, 147 trace, 148 results, 149 repositories, 150 depSelector, 151 depManager, 152 depTraverser, 153 verFilter, 154 dependency, 155 relocations, 156 false); 157 } 158 159 @SuppressWarnings("checkstyle:parameternumber") 160 private void processDependency( 161 Args args, 162 RequestTrace parent, 163 Results results, 164 List<RemoteRepository> repositories, 165 DependencySelector depSelector, 166 DependencyManager depManager, 167 DependencyTraverser depTraverser, 168 VersionFilter verFilter, 169 Dependency dependency, 170 List<Artifact> relocations, 171 boolean disableVersionManagement) { 172 if (depSelector != null && !depSelector.selectDependency(dependency)) { 173 return; 174 } 175 176 RequestTrace trace = collectStepTrace(parent, args.request.getRequestContext(), args.nodes.nodes, dependency); 177 PremanagedDependency preManaged = 178 PremanagedDependency.create(depManager, dependency, disableVersionManagement, args.premanagedState); 179 dependency = preManaged.getManagedDependency(); 180 181 boolean noDescriptor = isLackingDescriptor(dependency.getArtifact()); 182 183 boolean traverse = !noDescriptor && (depTraverser == null || depTraverser.traverseDependency(dependency)); 184 185 List<? extends Version> versions; 186 VersionRangeResult rangeResult; 187 try { 188 VersionRangeRequest rangeRequest = 189 createVersionRangeRequest(args.request.getRequestContext(), trace, repositories, dependency); 190 191 rangeResult = cachedResolveRangeResult(rangeRequest, args.pool, args.session); 192 193 versions = filterVersions(dependency, rangeResult, verFilter, args.versionContext); 194 } catch (VersionRangeResolutionException e) { 195 results.addException(dependency, e, args.nodes.nodes); 196 return; 197 } 198 199 for (Version version : versions) { 200 Artifact originalArtifact = dependency.getArtifact().setVersion(version.toString()); 201 Dependency d = dependency.setArtifact(originalArtifact); 202 203 ArtifactDescriptorRequest descriptorRequest = 204 createArtifactDescriptorRequest(args.request.getRequestContext(), trace, repositories, d); 205 206 final ArtifactDescriptorResult descriptorResult = 207 getArtifactDescriptorResult(args, results, noDescriptor, d, descriptorRequest); 208 if (descriptorResult != null) { 209 d = d.setArtifact(descriptorResult.getArtifact()); 210 211 DependencyNode node = args.nodes.top(); 212 213 int cycleEntry = DefaultDependencyCycle.find(args.nodes.nodes, d.getArtifact()); 214 if (cycleEntry >= 0) { 215 results.addCycle(args.nodes.nodes, cycleEntry, d); 216 DependencyNode cycleNode = args.nodes.get(cycleEntry); 217 if (cycleNode.getDependency() != null) { 218 DefaultDependencyNode child = createDependencyNode( 219 relocations, preManaged, rangeResult, version, d, descriptorResult, cycleNode); 220 node.getChildren().add(child); 221 continue; 222 } 223 } 224 225 if (!descriptorResult.getRelocations().isEmpty()) { 226 boolean disableVersionManagementSubsequently = 227 originalArtifact.getGroupId().equals(d.getArtifact().getGroupId()) 228 && originalArtifact 229 .getArtifactId() 230 .equals(d.getArtifact().getArtifactId()); 231 232 processDependency( 233 args, 234 parent, 235 results, 236 repositories, 237 depSelector, 238 depManager, 239 depTraverser, 240 verFilter, 241 d, 242 descriptorResult.getRelocations(), 243 disableVersionManagementSubsequently); 244 return; 245 } else { 246 d = args.pool.intern(d.setArtifact(args.pool.intern(d.getArtifact()))); 247 248 List<RemoteRepository> repos = 249 getRemoteRepositories(rangeResult.getRepository(version), repositories); 250 251 DefaultDependencyNode child = createDependencyNode( 252 relocations, 253 preManaged, 254 rangeResult, 255 version, 256 d, 257 descriptorResult.getAliases(), 258 repos, 259 args.request.getRequestContext()); 260 261 node.getChildren().add(child); 262 263 boolean recurse = 264 traverse && !descriptorResult.getDependencies().isEmpty(); 265 if (recurse) { 266 doRecurse( 267 args, 268 parent, 269 results, 270 repositories, 271 depSelector, 272 depManager, 273 depTraverser, 274 verFilter, 275 d, 276 descriptorResult, 277 child); 278 } 279 } 280 } else { 281 DependencyNode node = args.nodes.top(); 282 List<RemoteRepository> repos = getRemoteRepositories(rangeResult.getRepository(version), repositories); 283 DefaultDependencyNode child = createDependencyNode( 284 relocations, 285 preManaged, 286 rangeResult, 287 version, 288 d, 289 null, 290 repos, 291 args.request.getRequestContext()); 292 node.getChildren().add(child); 293 } 294 } 295 } 296 297 @SuppressWarnings("checkstyle:parameternumber") 298 private void doRecurse( 299 Args args, 300 RequestTrace trace, 301 Results results, 302 List<RemoteRepository> repositories, 303 DependencySelector depSelector, 304 DependencyManager depManager, 305 DependencyTraverser depTraverser, 306 VersionFilter verFilter, 307 Dependency d, 308 ArtifactDescriptorResult descriptorResult, 309 DefaultDependencyNode child) { 310 DefaultDependencyCollectionContext context = args.collectionContext; 311 context.set(d, descriptorResult.getManagedDependencies()); 312 313 DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector(context) : null; 314 DependencyManager childManager = depManager != null ? depManager.deriveChildManager(context) : null; 315 DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser(context) : null; 316 VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter(context) : null; 317 318 final List<RemoteRepository> childRepos = args.ignoreRepos 319 ? repositories 320 : remoteRepositoryManager.aggregateRepositories( 321 args.session, repositories, descriptorResult.getRepositories(), true); 322 323 Object key = 324 args.pool.toKey(d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter); 325 326 List<DependencyNode> children = args.pool.getChildren(key); 327 if (children == null) { 328 args.pool.putChildren(key, child.getChildren()); 329 330 args.nodes.push(child); 331 332 process( 333 args, 334 trace, 335 results, 336 descriptorResult.getDependencies(), 337 childRepos, 338 childSelector, 339 childManager, 340 childTraverser, 341 childFilter); 342 343 args.nodes.pop(); 344 } else { 345 child.setChildren(children); 346 } 347 } 348 349 private ArtifactDescriptorResult getArtifactDescriptorResult( 350 Args args, 351 Results results, 352 boolean noDescriptor, 353 Dependency d, 354 ArtifactDescriptorRequest descriptorRequest) { 355 return noDescriptor 356 ? new ArtifactDescriptorResult(descriptorRequest) 357 : resolveCachedArtifactDescriptor(args.pool, descriptorRequest, args.session, d, results, args); 358 } 359 360 private ArtifactDescriptorResult resolveCachedArtifactDescriptor( 361 DataPool pool, 362 ArtifactDescriptorRequest descriptorRequest, 363 RepositorySystemSession session, 364 Dependency d, 365 Results results, 366 Args args) { 367 Object key = pool.toKey(descriptorRequest); 368 ArtifactDescriptorResult descriptorResult = pool.getDescriptor(key, descriptorRequest); 369 if (descriptorResult == null) { 370 try { 371 descriptorResult = descriptorReader.readArtifactDescriptor(session, descriptorRequest); 372 pool.putDescriptor(key, descriptorResult); 373 } catch (ArtifactDescriptorException e) { 374 results.addException(d, e, args.nodes.nodes); 375 pool.putDescriptor(key, e); 376 return null; 377 } 378 379 } else if (descriptorResult == DataPool.NO_DESCRIPTOR) { 380 return null; 381 } 382 383 return descriptorResult; 384 } 385 386 static class Args { 387 388 final RepositorySystemSession session; 389 390 final boolean ignoreRepos; 391 392 final boolean premanagedState; 393 394 final DataPool pool; 395 396 final NodeStack nodes; 397 398 final DefaultDependencyCollectionContext collectionContext; 399 400 final DefaultVersionFilterContext versionContext; 401 402 final CollectRequest request; 403 404 Args( 405 RepositorySystemSession session, 406 DataPool pool, 407 NodeStack nodes, 408 DefaultDependencyCollectionContext collectionContext, 409 DefaultVersionFilterContext versionContext, 410 CollectRequest request) { 411 this.session = session; 412 this.request = request; 413 this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories(); 414 this.premanagedState = ConfigUtils.getBoolean(session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE); 415 this.pool = pool; 416 this.nodes = nodes; 417 this.collectionContext = collectionContext; 418 this.versionContext = versionContext; 419 } 420 } 421}