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.bf; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.io.Closeable; 026import java.util.ArrayDeque; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.Collections; 030import java.util.LinkedHashMap; 031import java.util.List; 032import java.util.Map; 033import java.util.Optional; 034import java.util.Queue; 035import java.util.Set; 036import java.util.concurrent.Callable; 037import java.util.concurrent.CompletableFuture; 038import java.util.concurrent.ConcurrentHashMap; 039import java.util.concurrent.Future; 040import java.util.concurrent.atomic.AtomicReference; 041import java.util.function.Supplier; 042import java.util.stream.Collectors; 043import java.util.stream.Stream; 044 045import org.eclipse.aether.RepositorySystemSession; 046import org.eclipse.aether.RequestTrace; 047import org.eclipse.aether.artifact.Artifact; 048import org.eclipse.aether.collection.CollectRequest; 049import org.eclipse.aether.collection.DependencyCollectionException; 050import org.eclipse.aether.collection.DependencyManager; 051import org.eclipse.aether.collection.DependencySelector; 052import org.eclipse.aether.collection.DependencyTraverser; 053import org.eclipse.aether.collection.VersionFilter; 054import org.eclipse.aether.graph.DefaultDependencyNode; 055import org.eclipse.aether.graph.Dependency; 056import org.eclipse.aether.graph.DependencyNode; 057import org.eclipse.aether.impl.ArtifactDescriptorReader; 058import org.eclipse.aether.impl.RemoteRepositoryManager; 059import org.eclipse.aether.impl.VersionRangeResolver; 060import org.eclipse.aether.internal.impl.collect.DataPool; 061import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext; 062import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector; 063import org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext; 064import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; 065import org.eclipse.aether.internal.impl.collect.PremanagedDependency; 066import org.eclipse.aether.repository.RemoteRepository; 067import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 068import org.eclipse.aether.resolution.ArtifactDescriptorResult; 069import org.eclipse.aether.resolution.VersionRangeRequest; 070import org.eclipse.aether.resolution.VersionRangeResult; 071import org.eclipse.aether.spi.artifact.decorator.ArtifactDecoratorFactory; 072import org.eclipse.aether.util.ConfigUtils; 073import org.eclipse.aether.util.artifact.ArtifactIdUtils; 074import org.eclipse.aether.util.concurrency.SmartExecutor; 075import org.eclipse.aether.util.concurrency.SmartExecutorUtils; 076import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 077import org.eclipse.aether.version.Version; 078 079import static org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle.find; 080 081/** 082 * Breadth-first {@link org.eclipse.aether.impl.DependencyCollector} 083 * 084 * @since 1.8.0 085 */ 086@Singleton 087@Named(BfDependencyCollector.NAME) 088public class BfDependencyCollector extends DependencyCollectorDelegate { 089 public static final String NAME = "bf"; 090 091 private static final String CONFIG_PROPS_PREFIX = DefaultDependencyCollector.CONFIG_PROPS_PREFIX + NAME + "."; 092 093 /** 094 * The key in the repository session's {@link RepositorySystemSession#getConfigProperties() 095 * configuration properties} used to store a {@link String} flag controlling the resolver's skip mode. 096 * Supported modes are "versionless" (default), "versioned" and "false" to not use skipper. The first two modes 097 * are defining "function" how to map artifact coordinates to (String) key while deciding "skip" logic. 098 * The "versionless" uses {@code G:A:C:E} coordinate elements only (without version), while "versioned" uses 099 * all {@code G:A:C:E:V} artifact coordinates. 100 * 101 * @since 1.8.0 102 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 103 * @configurationType {@link java.lang.String} 104 * @configurationDefaultValue {@link #DEFAULT_SKIPPER} 105 */ 106 public static final String CONFIG_PROP_SKIPPER = CONFIG_PROPS_PREFIX + "skipper"; 107 108 public static final String NONE_SKIPPER = "false"; 109 public static final String VERSIONLESS_SKIPPER = "versionless"; 110 public static final String VERSIONED_SKIPPER = "versioned"; 111 112 /** 113 * The default value for {@link #CONFIG_PROP_SKIPPER}, {@code true}. 114 * 115 * @since 1.8.0 116 */ 117 public static final String DEFAULT_SKIPPER = VERSIONLESS_SKIPPER; 118 119 /** 120 * The count of threads to be used when collecting POMs in parallel. 121 * 122 * @since 1.9.0 123 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 124 * @configurationType {@link java.lang.Integer} 125 * @configurationDefaultValue {@link #DEFAULT_THREADS} 126 */ 127 public static final String CONFIG_PROP_THREADS = CONFIG_PROPS_PREFIX + "threads"; 128 129 /** 130 * The default value for {@link #CONFIG_PROP_THREADS}, default value 5. 131 * 132 * @since 1.9.0 133 */ 134 public static final int DEFAULT_THREADS = 5; 135 136 @Inject 137 public BfDependencyCollector( 138 RemoteRepositoryManager remoteRepositoryManager, 139 ArtifactDescriptorReader artifactDescriptorReader, 140 VersionRangeResolver versionRangeResolver, 141 Map<String, ArtifactDecoratorFactory> artifactDecoratorFactories) { 142 super(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver, artifactDecoratorFactories); 143 } 144 145 @SuppressWarnings("checkstyle:parameternumber") 146 @Override 147 protected void doCollectDependencies( 148 RepositorySystemSession session, 149 RequestTrace trace, 150 DataPool pool, 151 DefaultDependencyCollectionContext context, 152 DefaultVersionFilterContext versionContext, 153 CollectRequest request, 154 DependencyNode node, 155 List<RemoteRepository> repositories, 156 List<Dependency> dependencies, 157 List<Dependency> managedDependencies, 158 Results results) 159 throws DependencyCollectionException { 160 String skipperMode = ConfigUtils.getString(session, DEFAULT_SKIPPER, CONFIG_PROP_SKIPPER); 161 Supplier<DependencyResolutionSkipper> skipperSupplier; 162 if (NONE_SKIPPER.equals(skipperMode)) { 163 logger.debug("Collector skip mode disabled"); 164 skipperSupplier = DependencyResolutionSkipper::neverSkipper; 165 } else if (VERSIONLESS_SKIPPER.equals(skipperMode)) { 166 logger.debug("Collector skip mode enabled: {} (key function GACE)", skipperMode); 167 skipperSupplier = DependencyResolutionSkipper::defaultGACESkipper; 168 } else if (VERSIONED_SKIPPER.equals(skipperMode)) { 169 logger.debug("Collector skip mode enabled: {} (key function GACEV)", skipperMode); 170 skipperSupplier = DependencyResolutionSkipper::defaultGACEVSkipper; 171 } else { 172 throw new IllegalArgumentException("Unknown skipper mode: " + skipperMode + "; known are " 173 + Arrays.asList(VERSIONLESS_SKIPPER, VERSIONED_SKIPPER, NONE_SKIPPER)); 174 } 175 176 try (DependencyResolutionSkipper skipper = skipperSupplier.get(); 177 ParallelDescriptorResolver parallelDescriptorResolver = 178 new ParallelDescriptorResolver(SmartExecutorUtils.smartExecutor( 179 session, 180 null, // we don't know ahead of time; we want global executor 181 ConfigUtils.getInteger(session, DEFAULT_THREADS, CONFIG_PROP_THREADS), 182 getClass().getSimpleName() + "-"))) { 183 Args args = new Args(session, pool, context, versionContext, request, skipper, parallelDescriptorResolver); 184 185 DependencySelector rootDepSelector = session.getDependencySelector() != null 186 ? session.getDependencySelector().deriveChildSelector(context) 187 : null; 188 DependencyManager rootDepManager = session.getDependencyManager() != null 189 ? session.getDependencyManager().deriveChildManager(context) 190 : null; 191 DependencyTraverser rootDepTraverser = session.getDependencyTraverser() != null 192 ? session.getDependencyTraverser().deriveChildTraverser(context) 193 : null; 194 VersionFilter rootVerFilter = session.getVersionFilter() != null 195 ? session.getVersionFilter().deriveChildFilter(context) 196 : null; 197 198 List<DependencyNode> parents = Collections.singletonList(node); 199 for (Dependency dependency : dependencies) { 200 if (rootDepSelector != null && !rootDepSelector.selectDependency(dependency)) { 201 continue; 202 } 203 RequestTrace childTrace = 204 collectStepTrace(trace, args.request.getRequestContext(), parents, dependency); 205 DependencyProcessingContext processingContext = new DependencyProcessingContext( 206 rootDepSelector, 207 rootDepManager, 208 rootDepTraverser, 209 rootVerFilter, 210 childTrace, 211 repositories, 212 managedDependencies, 213 parents, 214 dependency, 215 PremanagedDependency.create(rootDepManager, dependency, false, args.premanagedState)); 216 processingContext.withDependency(processingContext.premanagedDependency.getManagedDependency()); 217 resolveArtifactDescriptorAsync(args, processingContext, results); 218 args.dependencyProcessingQueue.add(processingContext); 219 } 220 221 while (!args.dependencyProcessingQueue.isEmpty()) { 222 processDependency( 223 args, results, args.dependencyProcessingQueue.remove(), Collections.emptyList(), false); 224 } 225 226 if (args.interruptedException.get() != null) { 227 throw new DependencyCollectionException( 228 results.getResult(), "Collection interrupted", args.interruptedException.get()); 229 } 230 } 231 } 232 233 @SuppressWarnings("checkstyle:parameternumber") 234 private void processDependency( 235 Args args, 236 Results results, 237 DependencyProcessingContext context, 238 List<Artifact> relocations, 239 boolean disableVersionManagement) { 240 if (Thread.interrupted()) { 241 args.interruptedException.set(new InterruptedException()); 242 } 243 if (args.interruptedException.get() != null) { 244 return; 245 } 246 Dependency dependency = context.dependency; 247 PremanagedDependency preManaged = context.premanagedDependency; 248 249 boolean noDescriptor = isLackingDescriptor(args.session, dependency.getArtifact()); 250 boolean traverse = 251 !noDescriptor && (context.depTraverser == null || context.depTraverser.traverseDependency(dependency)); 252 253 Future<DescriptorResolutionResult> resolutionResultFuture = args.resolver.find(dependency.getArtifact()); 254 DescriptorResolutionResult resolutionResult; 255 VersionRangeResult rangeResult; 256 try { 257 resolutionResult = resolutionResultFuture.get(); 258 rangeResult = resolutionResult.rangeResult; 259 } catch (Exception e) { 260 results.addException(dependency, e, context.parents); 261 return; 262 } 263 264 Set<Version> versions = resolutionResult.descriptors.keySet(); 265 for (Version version : versions) { 266 Artifact originalArtifact = dependency.getArtifact().setVersion(version.toString()); 267 Dependency d = dependency.setArtifact(originalArtifact); 268 269 final ArtifactDescriptorResult descriptorResult = resolutionResult.descriptors.get(version); 270 if (descriptorResult != null) { 271 d = d.setArtifact(descriptorResult.getArtifact()); 272 273 int cycleEntry = find(context.parents, d.getArtifact()); 274 if (cycleEntry >= 0) { 275 results.addCycle(context.parents, cycleEntry, d); 276 DependencyNode cycleNode = context.parents.get(cycleEntry); 277 if (cycleNode.getDependency() != null) { 278 DefaultDependencyNode child = createDependencyNode( 279 relocations, preManaged, rangeResult, version, d, descriptorResult, cycleNode); 280 context.getParent().getChildren().add(child); 281 continue; 282 } 283 } 284 285 if (!descriptorResult.getRelocations().isEmpty()) { 286 if (context.depSelector == null || context.depSelector.selectDependency(d)) { 287 boolean disableVersionManagementSubsequently = originalArtifact 288 .getGroupId() 289 .equals(d.getArtifact().getGroupId()) 290 && originalArtifact 291 .getArtifactId() 292 .equals(d.getArtifact().getArtifactId()); 293 294 PremanagedDependency premanagedDependency = PremanagedDependency.create( 295 context.depManager, d, disableVersionManagementSubsequently, args.premanagedState); 296 DependencyProcessingContext relocatedContext = new DependencyProcessingContext( 297 context.depSelector, 298 context.depManager, 299 context.depTraverser, 300 context.verFilter, 301 context.trace, 302 context.repositories, 303 descriptorResult.getManagedDependencies(), 304 context.parents, 305 d, 306 premanagedDependency); 307 308 relocatedContext.withDependency(premanagedDependency.getManagedDependency()); 309 resolveArtifactDescriptorAsync(args, relocatedContext, results); 310 processDependency( 311 args, 312 results, 313 relocatedContext, 314 descriptorResult.getRelocations(), 315 disableVersionManagementSubsequently); 316 } 317 return; 318 } else { 319 d = args.pool.intern(d.setArtifact(args.pool.intern(d.getArtifact()))); 320 321 List<RemoteRepository> repos = 322 getRemoteRepositories(rangeResult.getRepository(version), context.repositories); 323 324 DefaultDependencyNode child = createDependencyNode( 325 relocations, 326 preManaged, 327 rangeResult, 328 version, 329 d, 330 descriptorResult.getAliases(), 331 repos, 332 args.request.getRequestContext()); 333 334 context.getParent().getChildren().add(child); 335 336 boolean recurse = 337 traverse && !descriptorResult.getDependencies().isEmpty(); 338 DependencyProcessingContext parentContext = context.withDependency(d); 339 if (recurse) { 340 doRecurse(args, parentContext, descriptorResult, child, results, disableVersionManagement); 341 } else if (!args.skipper.skipResolution(child, parentContext.parents)) { 342 List<DependencyNode> parents = new ArrayList<>(parentContext.parents.size() + 1); 343 parents.addAll(parentContext.parents); 344 parents.add(child); 345 args.skipper.cache(child, parents); 346 } 347 } 348 } else { 349 List<RemoteRepository> repos = 350 getRemoteRepositories(rangeResult.getRepository(version), context.repositories); 351 DefaultDependencyNode child = createDependencyNode( 352 relocations, 353 preManaged, 354 rangeResult, 355 version, 356 d, 357 null, 358 repos, 359 args.request.getRequestContext()); 360 context.getParent().getChildren().add(child); 361 } 362 } 363 } 364 365 @SuppressWarnings("checkstyle:parameternumber") 366 private void doRecurse( 367 Args args, 368 DependencyProcessingContext parentContext, 369 ArtifactDescriptorResult descriptorResult, 370 DefaultDependencyNode child, 371 Results results, 372 boolean disableVersionManagement) { 373 DefaultDependencyCollectionContext context = args.collectionContext.get(); 374 args.collectionContext.compareAndSet( 375 context, context.set(parentContext.dependency, descriptorResult.getManagedDependencies())); 376 context = args.collectionContext.get(); 377 378 DependencySelector childSelector = 379 parentContext.depSelector != null ? parentContext.depSelector.deriveChildSelector(context) : null; 380 DependencyTraverser childTraverser = 381 parentContext.depTraverser != null ? parentContext.depTraverser.deriveChildTraverser(context) : null; 382 VersionFilter childFilter = 383 parentContext.verFilter != null ? parentContext.verFilter.deriveChildFilter(context) : null; 384 385 final List<RemoteRepository> childRepos = args.ignoreRepos 386 ? parentContext.repositories 387 : remoteRepositoryManager.aggregateRepositories( 388 args.session, parentContext.repositories, descriptorResult.getRepositories(), true); 389 390 // Optimization: try pool cache with the parent manager as a speculative key BEFORE 391 // calling deriveChildManager. When deriveChildManager returns `this` (the common case — 392 // no new management data at this depth), the parent manager IS the child manager, so 393 // this speculative key matches any previously stored entry. On pool hit, we skip 394 // deriveChildManager entirely, saving even the memoization cache lookup. 395 Object speculativeKey = args.pool.toKey( 396 parentContext.dependency.getArtifact(), 397 childRepos, 398 childSelector, 399 parentContext.depManager, 400 childTraverser, 401 childFilter); 402 List<DependencyNode> children = args.pool.getChildren(speculativeKey); 403 if (children != null) { 404 child.setChildren(children); 405 return; 406 } 407 408 // Speculative miss — compute the actual derived manager 409 DependencyManager childManager = 410 parentContext.depManager != null ? parentContext.depManager.deriveChildManager(context) : null; 411 412 Object key; 413 if (childManager == parentContext.depManager) { 414 // Manager unchanged — speculative key was correct, already checked and missed 415 key = speculativeKey; 416 } else { 417 // Manager changed — recompute key and check pool again with the correct manager 418 key = args.pool.toKey( 419 parentContext.dependency.getArtifact(), 420 childRepos, 421 childSelector, 422 childManager, 423 childTraverser, 424 childFilter); 425 children = args.pool.getChildren(key); 426 if (children != null) { 427 child.setChildren(children); 428 return; 429 } 430 } 431 432 // True cache miss — do full resolution 433 boolean skipResolution = args.skipper.skipResolution(child, parentContext.parents); 434 if (!skipResolution) { 435 List<DependencyNode> parents = new ArrayList<>(parentContext.parents.size() + 1); 436 parents.addAll(parentContext.parents); 437 parents.add(child); 438 for (Dependency dependency : descriptorResult.getDependencies()) { 439 if (childSelector != null && !childSelector.selectDependency(dependency)) { 440 continue; 441 } 442 RequestTrace childTrace = 443 collectStepTrace(parentContext.trace, args.request.getRequestContext(), parents, dependency); 444 PremanagedDependency premanagedDependency = PremanagedDependency.create( 445 childManager, dependency, disableVersionManagement, args.premanagedState); 446 DependencyProcessingContext processingContext = new DependencyProcessingContext( 447 childSelector, 448 childManager, 449 childTraverser, 450 childFilter, 451 childTrace, 452 childRepos, 453 descriptorResult.getManagedDependencies(), 454 parents, 455 dependency, 456 premanagedDependency); 457 // resolve descriptors ahead for managed dependency 458 processingContext.withDependency(processingContext.premanagedDependency.getManagedDependency()); 459 resolveArtifactDescriptorAsync(args, processingContext, results); 460 args.dependencyProcessingQueue.add(processingContext); 461 } 462 args.pool.putChildren(key, child.getChildren()); 463 args.skipper.cache(child, parents); 464 } 465 } 466 467 private void resolveArtifactDescriptorAsync(Args args, DependencyProcessingContext context, Results results) { 468 Dependency dependency = context.dependency; 469 args.resolver.resolveDescriptors(dependency.getArtifact(), () -> { 470 VersionRangeRequest rangeRequest = createVersionRangeRequest( 471 args.request.getRequestContext(), context.trace, context.repositories, dependency); 472 VersionRangeResult rangeResult = cachedResolveRangeResult(rangeRequest, args.pool, args.session); 473 List<? extends Version> versions = 474 filterVersions(dependency, rangeResult, context.verFilter, args.versionContext); 475 476 // resolve newer version first to maximize benefits of skipper 477 Collections.reverse(versions); 478 479 Map<Version, ArtifactDescriptorResult> descriptors = new ConcurrentHashMap<>(versions.size()); 480 Stream<? extends Version> stream = versions.size() > 1 ? versions.parallelStream() : versions.stream(); 481 stream.forEach(version -> Optional.ofNullable( 482 resolveDescriptorForVersion(args, context, results, dependency, version)) 483 .ifPresent(r -> descriptors.put(version, r))); 484 485 DescriptorResolutionResult resolutionResult = 486 new DescriptorResolutionResult(dependency.getArtifact(), rangeResult); 487 // keep original sequence 488 versions.forEach(version -> resolutionResult.descriptors.put(version, descriptors.get(version))); 489 // populate for versions in version range 490 resolutionResult.flatten().forEach(dr -> args.resolver.cacheVersionRangeDescriptor(dr.artifact, dr)); 491 492 return resolutionResult; 493 }); 494 } 495 496 private ArtifactDescriptorResult resolveDescriptorForVersion( 497 Args args, DependencyProcessingContext context, Results results, Dependency dependency, Version version) { 498 Artifact original = dependency.getArtifact(); 499 Artifact newArtifact = original.setVersion(version.toString()); 500 Dependency newDependency = 501 new Dependency(newArtifact, dependency.getScope(), dependency.isOptional(), dependency.getExclusions()); 502 DependencyProcessingContext newContext = context.copy(); 503 504 ArtifactDescriptorRequest descriptorRequest = createArtifactDescriptorRequest( 505 args.request.getRequestContext(), context.trace, newContext.repositories, newDependency); 506 return isLackingDescriptor(args.session, newArtifact) 507 ? new ArtifactDescriptorResult(descriptorRequest) 508 : resolveCachedArtifactDescriptor( 509 args.pool, 510 descriptorRequest, 511 args.session, 512 newContext.withDependency(newDependency).dependency, 513 results, 514 context.parents); 515 } 516 517 static class ParallelDescriptorResolver implements Closeable { 518 private final SmartExecutor smartExecutor; 519 520 /** 521 * Artifact ID -> Future of DescriptorResolutionResult 522 */ 523 private final Map<String, Future<DescriptorResolutionResult>> results = new ConcurrentHashMap<>(256); 524 525 ParallelDescriptorResolver(SmartExecutor smartExecutor) { 526 this.smartExecutor = smartExecutor; 527 } 528 529 void resolveDescriptors(Artifact artifact, Callable<DescriptorResolutionResult> callable) { 530 results.computeIfAbsent(ArtifactIdUtils.toId(artifact), key -> smartExecutor.submit(callable)); 531 } 532 533 void cacheVersionRangeDescriptor(Artifact artifact, DescriptorResolutionResult resolutionResult) { 534 results.computeIfAbsent( 535 ArtifactIdUtils.toId(artifact), key -> CompletableFuture.completedFuture(resolutionResult)); 536 } 537 538 Future<DescriptorResolutionResult> find(Artifact artifact) { 539 return results.get(ArtifactIdUtils.toId(artifact)); 540 } 541 542 @Override 543 public void close() { 544 smartExecutor.close(); 545 } 546 } 547 548 static class DescriptorResolutionResult { 549 Artifact artifact; 550 551 VersionRangeResult rangeResult; 552 553 Map<Version, ArtifactDescriptorResult> descriptors; 554 555 DescriptorResolutionResult(Artifact artifact, VersionRangeResult rangeResult) { 556 this.artifact = artifact; 557 this.rangeResult = rangeResult; 558 this.descriptors = new LinkedHashMap<>(rangeResult.getVersions().size()); 559 } 560 561 DescriptorResolutionResult( 562 VersionRangeResult rangeResult, Version version, ArtifactDescriptorResult descriptor) { 563 // NOTE: In case of A1 -> A2 relocation this happens: 564 // ArtifactDescriptorResult read by ArtifactDescriptorResultReader for A1 565 // will return instance that will have artifact = A2 (as RelocatedArtifact). 566 // So to properly "key" this instance, we need to use "originally requested" A1 instead! 567 // In short: 568 // ArtifactDescriptorRequest.artifact != ArtifactDescriptorResult.artifact WHEN relocation in play 569 // otherwise (no relocation), they are EQUAL. 570 this(descriptor.getRequest().getArtifact(), rangeResult); 571 this.descriptors.put(version, descriptor); 572 } 573 574 List<DescriptorResolutionResult> flatten() { 575 if (descriptors.size() > 1) { 576 return descriptors.entrySet().stream() 577 .map(e -> new DescriptorResolutionResult(rangeResult, e.getKey(), e.getValue())) 578 .collect(Collectors.toList()); 579 } else { 580 return Collections.emptyList(); 581 } 582 } 583 } 584 585 static class Args { 586 587 final RepositorySystemSession session; 588 589 final boolean ignoreRepos; 590 591 final boolean premanagedState; 592 593 final DataPool pool; 594 595 final Queue<DependencyProcessingContext> dependencyProcessingQueue = new ArrayDeque<>(128); 596 597 final AtomicReference<DefaultDependencyCollectionContext> collectionContext; 598 599 final DefaultVersionFilterContext versionContext; 600 601 final CollectRequest request; 602 603 final DependencyResolutionSkipper skipper; 604 605 final ParallelDescriptorResolver resolver; 606 607 final AtomicReference<InterruptedException> interruptedException; 608 609 Args( 610 RepositorySystemSession session, 611 DataPool pool, 612 DefaultDependencyCollectionContext collectionContext, 613 DefaultVersionFilterContext versionContext, 614 CollectRequest request, 615 DependencyResolutionSkipper skipper, 616 ParallelDescriptorResolver resolver) { 617 this.session = session; 618 this.request = request; 619 this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories(); 620 this.premanagedState = ConfigUtils.getBoolean(session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE); 621 this.pool = pool; 622 this.collectionContext = new AtomicReference<>(collectionContext); 623 this.versionContext = versionContext; 624 this.skipper = skipper; 625 this.resolver = resolver; 626 this.interruptedException = new AtomicReference<>(null); 627 } 628 } 629}