001package org.eclipse.aether.internal.impl.collect.bf; 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 javax.inject.Inject; 023import javax.inject.Named; 024import javax.inject.Singleton; 025 026import java.util.ArrayDeque; 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.HashMap; 031import java.util.HashSet; 032import java.util.LinkedHashMap; 033import java.util.List; 034import java.util.Map; 035import java.util.Queue; 036 037import org.eclipse.aether.DefaultRepositorySystemSession; 038import org.eclipse.aether.RepositoryException; 039import org.eclipse.aether.RepositorySystemSession; 040import org.eclipse.aether.RequestTrace; 041import org.eclipse.aether.artifact.Artifact; 042import org.eclipse.aether.artifact.ArtifactProperties; 043import org.eclipse.aether.collection.CollectRequest; 044import org.eclipse.aether.collection.CollectResult; 045import org.eclipse.aether.collection.DependencyCollectionException; 046import org.eclipse.aether.collection.DependencyGraphTransformer; 047import org.eclipse.aether.collection.DependencyManagement; 048import org.eclipse.aether.collection.DependencyManager; 049import org.eclipse.aether.collection.DependencySelector; 050import org.eclipse.aether.collection.DependencyTraverser; 051import org.eclipse.aether.collection.VersionFilter; 052import org.eclipse.aether.graph.DefaultDependencyNode; 053import org.eclipse.aether.graph.Dependency; 054import org.eclipse.aether.graph.DependencyNode; 055import org.eclipse.aether.graph.Exclusion; 056import org.eclipse.aether.impl.ArtifactDescriptorReader; 057import org.eclipse.aether.impl.RemoteRepositoryManager; 058import org.eclipse.aether.impl.VersionRangeResolver; 059import org.eclipse.aether.internal.impl.collect.CachingArtifactTypeRegistry; 060import org.eclipse.aether.internal.impl.collect.DataPool; 061import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext; 062import org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle; 063import org.eclipse.aether.internal.impl.collect.DefaultDependencyGraphTransformationContext; 064import org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext; 065import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; 066import org.eclipse.aether.repository.ArtifactRepository; 067import org.eclipse.aether.repository.RemoteRepository; 068import org.eclipse.aether.resolution.ArtifactDescriptorException; 069import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 070import org.eclipse.aether.resolution.ArtifactDescriptorResult; 071import org.eclipse.aether.resolution.VersionRangeRequest; 072import org.eclipse.aether.resolution.VersionRangeResolutionException; 073import org.eclipse.aether.resolution.VersionRangeResult; 074import org.eclipse.aether.spi.locator.Service; 075import org.eclipse.aether.util.ConfigUtils; 076import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 077import org.eclipse.aether.util.graph.transformer.TransformationContextKeys; 078import org.eclipse.aether.version.Version; 079 080import static java.util.Objects.requireNonNull; 081import static org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle.find; 082 083/** 084 * Breadth-first {@link org.eclipse.aether.impl.DependencyCollector} 085 * 086 * @since 1.8.0 087 */ 088@Singleton 089@Named( BfDependencyCollector.NAME ) 090public class BfDependencyCollector 091 extends DependencyCollectorDelegate implements Service 092{ 093 public static final String NAME = "bf"; 094 095 /** 096 * The key in the repository session's {@link RepositorySystemSession#getConfigProperties() 097 * configuration properties} used to store a {@link Boolean} flag controlling the resolver's skip mode. 098 * 099 * @since 1.8.0 100 */ 101 public static final String CONFIG_PROP_SKIPPER = "aether.dependencyCollector.bf.skipper"; 102 103 /** 104 * The default value for {@link #CONFIG_PROP_SKIPPER}, {@code true}. 105 * 106 * @since 1.8.0 107 */ 108 public static final boolean CONFIG_PROP_SKIPPER_DEFAULT = true; 109 110 public BfDependencyCollector() 111 { 112 // enables default constructor 113 } 114 115 @Inject 116 BfDependencyCollector( RemoteRepositoryManager remoteRepositoryManager, 117 ArtifactDescriptorReader artifactDescriptorReader, 118 VersionRangeResolver versionRangeResolver ) 119 { 120 super( remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver ); 121 } 122 123 @SuppressWarnings( "checkstyle:methodlength" ) 124 public CollectResult collectDependencies( RepositorySystemSession session, CollectRequest request ) 125 throws DependencyCollectionException 126 { 127 requireNonNull( session, "session cannot be null" ); 128 requireNonNull( request, "request cannot be null" ); 129 session = optimizeSession( session ); 130 131 boolean useSkip = ConfigUtils.getBoolean( 132 session, CONFIG_PROP_SKIPPER_DEFAULT, CONFIG_PROP_SKIPPER 133 ); 134 if ( useSkip ) 135 { 136 logger.debug( "Collector skip mode enabled" ); 137 } 138 139 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); 140 141 CollectResult result = new CollectResult( request ); 142 143 DependencySelector depSelector = session.getDependencySelector(); 144 DependencyManager depManager = session.getDependencyManager(); 145 DependencyTraverser depTraverser = session.getDependencyTraverser(); 146 VersionFilter verFilter = session.getVersionFilter(); 147 148 Dependency root = request.getRoot(); 149 List<RemoteRepository> repositories = request.getRepositories(); 150 List<Dependency> dependencies = request.getDependencies(); 151 List<Dependency> managedDependencies = request.getManagedDependencies(); 152 153 Map<String, Object> stats = new LinkedHashMap<>(); 154 long time1 = System.nanoTime(); 155 156 DefaultDependencyNode node; 157 if ( root != null ) 158 { 159 List<? extends Version> versions; 160 VersionRangeResult rangeResult; 161 try 162 { 163 VersionRangeRequest rangeRequest = 164 new VersionRangeRequest( root.getArtifact(), request.getRepositories(), 165 request.getRequestContext() ); 166 rangeRequest.setTrace( trace ); 167 rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest ); 168 versions = filterVersions( root, rangeResult, verFilter, new DefaultVersionFilterContext( session ) ); 169 } 170 catch ( VersionRangeResolutionException e ) 171 { 172 result.addException( e ); 173 throw new DependencyCollectionException( result, e.getMessage() ); 174 } 175 176 Version version = versions.get( versions.size() - 1 ); 177 root = root.setArtifact( root.getArtifact().setVersion( version.toString() ) ); 178 179 ArtifactDescriptorResult descriptorResult; 180 try 181 { 182 ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(); 183 descriptorRequest.setArtifact( root.getArtifact() ); 184 descriptorRequest.setRepositories( request.getRepositories() ); 185 descriptorRequest.setRequestContext( request.getRequestContext() ); 186 descriptorRequest.setTrace( trace ); 187 if ( isLackingDescriptor( root.getArtifact() ) ) 188 { 189 descriptorResult = new ArtifactDescriptorResult( descriptorRequest ); 190 } 191 else 192 { 193 descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); 194 } 195 } 196 catch ( ArtifactDescriptorException e ) 197 { 198 result.addException( e ); 199 throw new DependencyCollectionException( result, e.getMessage() ); 200 } 201 202 root = root.setArtifact( descriptorResult.getArtifact() ); 203 204 if ( !session.isIgnoreArtifactDescriptorRepositories() ) 205 { 206 repositories = remoteRepositoryManager.aggregateRepositories( session, repositories, 207 descriptorResult.getRepositories(), 208 true ); 209 } 210 dependencies = mergeDeps( dependencies, descriptorResult.getDependencies() ); 211 managedDependencies = mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() ); 212 213 node = new DefaultDependencyNode( root ); 214 node.setRequestContext( request.getRequestContext() ); 215 node.setRelocations( descriptorResult.getRelocations() ); 216 node.setVersionConstraint( rangeResult.getVersionConstraint() ); 217 node.setVersion( version ); 218 node.setAliases( descriptorResult.getAliases() ); 219 node.setRepositories( request.getRepositories() ); 220 } 221 else 222 { 223 node = new DefaultDependencyNode( request.getRootArtifact() ); 224 node.setRequestContext( request.getRequestContext() ); 225 node.setRepositories( request.getRepositories() ); 226 } 227 228 result.setRoot( node ); 229 230 boolean traverse = root == null || depTraverser == null || depTraverser.traverseDependency( root ); 231 String errorPath = null; 232 if ( traverse && !dependencies.isEmpty() ) 233 { 234 DataPool pool = new DataPool( session ); 235 236 DefaultDependencyCollectionContext context = 237 new DefaultDependencyCollectionContext( session, request.getRootArtifact(), root, managedDependencies ); 238 239 DefaultVersionFilterContext versionContext = new DefaultVersionFilterContext( session ); 240 241 Args args = 242 new Args( session, trace, pool, context, versionContext, request, 243 useSkip ? DependencyResolutionSkipper.defaultSkipper() 244 : DependencyResolutionSkipper.neverSkipper() ); 245 Results results = new Results( result, session ); 246 247 DependencySelector rootDepSelector = 248 depSelector != null ? depSelector.deriveChildSelector( context ) : null; 249 DependencyManager rootDepManager = depManager != null ? depManager.deriveChildManager( context ) : null; 250 DependencyTraverser rootDepTraverser = 251 depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null; 252 VersionFilter rootVerFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null; 253 254 List<DependencyNode> parents = Collections.singletonList( node ); 255 for ( Dependency dependency : dependencies ) 256 { 257 args.dependencyProcessingQueue.add( 258 new DependencyProcessingContext( rootDepSelector, rootDepManager, rootDepTraverser, 259 rootVerFilter, repositories, managedDependencies, parents, 260 dependency ) ); 261 } 262 263 while ( !args.dependencyProcessingQueue.isEmpty() ) 264 { 265 processDependency( args, results, args.dependencyProcessingQueue.remove(), Collections.emptyList(), 266 false ); 267 } 268 269 args.skipper.report(); 270 errorPath = results.errorPath; 271 } 272 273 long time2 = System.nanoTime(); 274 275 DependencyGraphTransformer transformer = session.getDependencyGraphTransformer(); 276 if ( transformer != null ) 277 { 278 try 279 { 280 DefaultDependencyGraphTransformationContext context = 281 new DefaultDependencyGraphTransformationContext( session ); 282 context.put( TransformationContextKeys.STATS, stats ); 283 result.setRoot( transformer.transformGraph( node, context ) ); 284 } 285 catch ( RepositoryException e ) 286 { 287 result.addException( e ); 288 } 289 } 290 291 long time3 = System.nanoTime(); 292 if ( logger.isDebugEnabled() ) 293 { 294 stats.put( "BfDependencyCollector.collectTime", time2 - time1 ); 295 stats.put( "BfDependencyCollector.transformTime", time3 - time2 ); 296 logger.debug( "Dependency collection stats {}", stats ); 297 } 298 299 if ( errorPath != null ) 300 { 301 throw new DependencyCollectionException( result, "Failed to collect dependencies at " + errorPath ); 302 } 303 if ( !result.getExceptions().isEmpty() ) 304 { 305 throw new DependencyCollectionException( result ); 306 } 307 308 return result; 309 } 310 311 private static RepositorySystemSession optimizeSession( RepositorySystemSession session ) 312 { 313 DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session ); 314 optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) ); 315 return optimized; 316 } 317 318 private List<Dependency> mergeDeps( List<Dependency> dominant, List<Dependency> recessive ) 319 { 320 List<Dependency> result; 321 if ( dominant == null || dominant.isEmpty() ) 322 { 323 result = recessive; 324 } 325 else if ( recessive == null || recessive.isEmpty() ) 326 { 327 result = dominant; 328 } 329 else 330 { 331 int initialCapacity = dominant.size() + recessive.size(); 332 result = new ArrayList<>( initialCapacity ); 333 Collection<String> ids = new HashSet<>( initialCapacity, 1.0f ); 334 for ( Dependency dependency : dominant ) 335 { 336 ids.add( getId( dependency.getArtifact() ) ); 337 result.add( dependency ); 338 } 339 for ( Dependency dependency : recessive ) 340 { 341 if ( !ids.contains( getId( dependency.getArtifact() ) ) ) 342 { 343 result.add( dependency ); 344 } 345 } 346 } 347 return result; 348 } 349 350 private static String getId( Artifact a ) 351 { 352 return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension(); 353 } 354 355 @SuppressWarnings( "checkstyle:parameternumber" ) 356 private void processDependency( Args args, Results results, DependencyProcessingContext context, 357 List<Artifact> relocations, boolean disableVersionManagement ) 358 { 359 360 if ( context.depSelector != null && !context.depSelector.selectDependency( context.dependency ) ) 361 { 362 return; 363 } 364 365 PremanagedDependency preManaged = 366 PremanagedDependency.create( context.depManager, context.dependency, disableVersionManagement, 367 args.premanagedState ); 368 Dependency dependency = preManaged.managedDependency; 369 370 boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() ); 371 372 boolean traverse = 373 !noDescriptor && ( context.depTraverser == null || context.depTraverser.traverseDependency( 374 dependency ) ); 375 376 List<? extends Version> versions; 377 VersionRangeResult rangeResult; 378 try 379 { 380 VersionRangeRequest rangeRequest = createVersionRangeRequest( args, context.repositories, dependency ); 381 382 rangeResult = cachedResolveRangeResult( rangeRequest, args.pool, args.session ); 383 384 versions = filterVersions( dependency, rangeResult, context.verFilter, args.versionContext ); 385 } 386 catch ( VersionRangeResolutionException e ) 387 { 388 results.addException( dependency, e, context.parents ); 389 return; 390 } 391 392 //Resolve newer version first to maximize benefits of skipper 393 Collections.reverse( versions ); 394 for ( Version version : versions ) 395 { 396 Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() ); 397 Dependency d = dependency.setArtifact( originalArtifact ); 398 399 ArtifactDescriptorRequest descriptorRequest = 400 createArtifactDescriptorRequest( args, context.repositories, d ); 401 402 final ArtifactDescriptorResult descriptorResult = 403 noDescriptor 404 ? new ArtifactDescriptorResult( descriptorRequest ) 405 : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, 406 context.withDependency( d ), results ); 407 408 if ( descriptorResult != null ) 409 { 410 d = d.setArtifact( descriptorResult.getArtifact() ); 411 412 int cycleEntry = find( context.parents, d.getArtifact() ); 413 if ( cycleEntry >= 0 ) 414 { 415 results.addCycle( context.parents, cycleEntry, d ); 416 DependencyNode cycleNode = context.parents.get( cycleEntry ); 417 if ( cycleNode.getDependency() != null ) 418 { 419 DefaultDependencyNode child = 420 createDependencyNode( relocations, preManaged, rangeResult, version, d, 421 descriptorResult, cycleNode ); 422 context.getParent().getChildren().add( child ); 423 continue; 424 } 425 } 426 427 if ( !descriptorResult.getRelocations().isEmpty() ) 428 { 429 boolean disableVersionManagementSubsequently = 430 originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() ) 431 && originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() ); 432 433 processDependency( args, results, context.withDependency( d ), descriptorResult.getRelocations(), 434 disableVersionManagementSubsequently ); 435 return; 436 } 437 else 438 { 439 d = args.pool.intern( d.setArtifact( args.pool.intern( d.getArtifact() ) ) ); 440 441 List<RemoteRepository> repos = 442 getRemoteRepositories( rangeResult.getRepository( version ), context.repositories ); 443 444 DefaultDependencyNode child = 445 createDependencyNode( relocations, preManaged, rangeResult, version, d, 446 descriptorResult.getAliases(), repos, args.request.getRequestContext() ); 447 448 context.getParent().getChildren().add( child ); 449 450 boolean recurse = traverse && !descriptorResult.getDependencies().isEmpty(); 451 if ( recurse ) 452 { 453 doRecurse( args, context.withDependency( d ), descriptorResult, child ); 454 } 455 } 456 } 457 else 458 { 459 List<RemoteRepository> repos = 460 getRemoteRepositories( rangeResult.getRepository( version ), context.repositories ); 461 DefaultDependencyNode child = 462 createDependencyNode( relocations, preManaged, rangeResult, version, d, null, repos, 463 args.request.getRequestContext() ); 464 context.getParent().getChildren().add( child ); 465 } 466 } 467 } 468 469 @SuppressWarnings( "checkstyle:parameternumber" ) 470 private void doRecurse( Args args, DependencyProcessingContext parentContext, 471 ArtifactDescriptorResult descriptorResult, DefaultDependencyNode child ) 472 { 473 DefaultDependencyCollectionContext context = args.collectionContext; 474 context.set( parentContext.dependency, descriptorResult.getManagedDependencies() ); 475 476 DependencySelector childSelector = 477 parentContext.depSelector != null ? parentContext.depSelector.deriveChildSelector( context ) : null; 478 DependencyManager childManager = 479 parentContext.depManager != null ? parentContext.depManager.deriveChildManager( context ) : null; 480 DependencyTraverser childTraverser = 481 parentContext.depTraverser != null ? parentContext.depTraverser.deriveChildTraverser( context ) : null; 482 VersionFilter childFilter = 483 parentContext.verFilter != null ? parentContext.verFilter.deriveChildFilter( context ) : null; 484 485 final List<RemoteRepository> childRepos = 486 args.ignoreRepos 487 ? parentContext.repositories 488 : remoteRepositoryManager.aggregateRepositories( args.session, parentContext.repositories, 489 descriptorResult.getRepositories(), true ); 490 491 Object key = 492 args.pool.toKey( parentContext.dependency.getArtifact(), childRepos, childSelector, childManager, 493 childTraverser, childFilter ); 494 495 List<DependencyNode> children = args.pool.getChildren( key ); 496 if ( children == null ) 497 { 498 boolean skipResolution = args.skipper.skipResolution( child, parentContext.parents ); 499 if ( !skipResolution ) 500 { 501 List<DependencyNode> parents = new ArrayList<>( parentContext.parents.size() + 1 ); 502 parents.addAll( parentContext.parents ); 503 parents.add( child ); 504 for ( Dependency dependency : descriptorResult.getDependencies() ) 505 { 506 args.dependencyProcessingQueue.add( 507 new DependencyProcessingContext( childSelector, childManager, childTraverser, childFilter, 508 childRepos, descriptorResult.getManagedDependencies(), parents, dependency ) ); 509 } 510 args.pool.putChildren( key, child.getChildren() ); 511 args.skipper.cache( child, parents ); 512 } 513 } 514 else 515 { 516 child.setChildren( children ); 517 } 518 } 519 520 private ArtifactDescriptorResult resolveCachedArtifactDescriptor( DataPool pool, 521 ArtifactDescriptorRequest descriptorRequest, 522 RepositorySystemSession session, 523 DependencyProcessingContext context, 524 Results results ) 525 { 526 Object key = pool.toKey( descriptorRequest ); 527 ArtifactDescriptorResult descriptorResult = pool.getDescriptor( key, descriptorRequest ); 528 if ( descriptorResult == null ) 529 { 530 try 531 { 532 descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); 533 pool.putDescriptor( key, descriptorResult ); 534 } 535 catch ( ArtifactDescriptorException e ) 536 { 537 results.addException( context.dependency, e, context.parents ); 538 pool.putDescriptor( key, e ); 539 return null; 540 } 541 542 } 543 else if ( descriptorResult == DataPool.NO_DESCRIPTOR ) 544 { 545 return null; 546 } 547 548 return descriptorResult; 549 } 550 551 @SuppressWarnings( "checkstyle:parameternumber" ) 552 private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations, 553 PremanagedDependency preManaged, 554 VersionRangeResult rangeResult, Version version, 555 Dependency d, Collection<Artifact> aliases, 556 List<RemoteRepository> repos, String requestContext ) 557 { 558 DefaultDependencyNode child = new DefaultDependencyNode( d ); 559 preManaged.applyTo( child ); 560 child.setRelocations( relocations ); 561 child.setVersionConstraint( rangeResult.getVersionConstraint() ); 562 child.setVersion( version ); 563 child.setAliases( aliases ); 564 child.setRepositories( repos ); 565 child.setRequestContext( requestContext ); 566 return child; 567 } 568 569 private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations, 570 PremanagedDependency preManaged, 571 VersionRangeResult rangeResult, Version version, 572 Dependency d, ArtifactDescriptorResult descriptorResult, 573 DependencyNode cycleNode ) 574 { 575 DefaultDependencyNode child = 576 createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(), 577 cycleNode.getRepositories(), cycleNode.getRequestContext() ); 578 child.setChildren( cycleNode.getChildren() ); 579 return child; 580 } 581 582 private static ArtifactDescriptorRequest createArtifactDescriptorRequest( Args args, 583 List<RemoteRepository> repositories, 584 Dependency d ) 585 { 586 ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(); 587 descriptorRequest.setArtifact( d.getArtifact() ); 588 descriptorRequest.setRepositories( repositories ); 589 descriptorRequest.setRequestContext( args.request.getRequestContext() ); 590 descriptorRequest.setTrace( args.trace ); 591 return descriptorRequest; 592 } 593 594 private static VersionRangeRequest createVersionRangeRequest( Args args, List<RemoteRepository> repositories, 595 Dependency dependency ) 596 { 597 VersionRangeRequest rangeRequest = new VersionRangeRequest(); 598 rangeRequest.setArtifact( dependency.getArtifact() ); 599 rangeRequest.setRepositories( repositories ); 600 rangeRequest.setRequestContext( args.request.getRequestContext() ); 601 rangeRequest.setTrace( args.trace ); 602 return rangeRequest; 603 } 604 605 private VersionRangeResult cachedResolveRangeResult( VersionRangeRequest rangeRequest, DataPool pool, 606 RepositorySystemSession session ) 607 throws VersionRangeResolutionException 608 { 609 Object key = pool.toKey( rangeRequest ); 610 VersionRangeResult rangeResult = pool.getConstraint( key, rangeRequest ); 611 if ( rangeResult == null ) 612 { 613 rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest ); 614 pool.putConstraint( key, rangeResult ); 615 } 616 return rangeResult; 617 } 618 619 private static boolean isLackingDescriptor( Artifact artifact ) 620 { 621 return artifact.getProperty( ArtifactProperties.LOCAL_PATH, null ) != null; 622 } 623 624 private static List<RemoteRepository> getRemoteRepositories( ArtifactRepository repository, 625 List<RemoteRepository> repositories ) 626 { 627 if ( repository instanceof RemoteRepository ) 628 { 629 return Collections.singletonList( (RemoteRepository) repository ); 630 } 631 if ( repository != null ) 632 { 633 return Collections.emptyList(); 634 } 635 return repositories; 636 } 637 638 private static List<? extends Version> filterVersions( Dependency dependency, VersionRangeResult rangeResult, 639 VersionFilter verFilter, 640 DefaultVersionFilterContext verContext ) 641 throws VersionRangeResolutionException 642 { 643 if ( rangeResult.getVersions().isEmpty() ) 644 { 645 throw new VersionRangeResolutionException( rangeResult, 646 "No versions available for " + dependency.getArtifact() 647 + " within specified range" ); 648 } 649 650 List<? extends Version> versions; 651 if ( verFilter != null && rangeResult.getVersionConstraint().getRange() != null ) 652 { 653 verContext.set( dependency, rangeResult ); 654 try 655 { 656 verFilter.filterVersions( verContext ); 657 } 658 catch ( RepositoryException e ) 659 { 660 throw new VersionRangeResolutionException( rangeResult, 661 "Failed to filter versions for " + dependency.getArtifact(), e ); 662 } 663 versions = verContext.get(); 664 if ( versions.isEmpty() ) 665 { 666 throw new VersionRangeResolutionException( rangeResult, 667 "No acceptable versions for " + dependency.getArtifact() + ": " + rangeResult.getVersions() ); 668 } 669 } 670 else 671 { 672 versions = rangeResult.getVersions(); 673 } 674 return versions; 675 } 676 677 static class Args 678 { 679 680 final RepositorySystemSession session; 681 682 final boolean ignoreRepos; 683 684 final boolean premanagedState; 685 686 final RequestTrace trace; 687 688 final DataPool pool; 689 690 final Queue<DependencyProcessingContext> dependencyProcessingQueue = new ArrayDeque<>( 128 ); 691 692 final DefaultDependencyCollectionContext collectionContext; 693 694 final DefaultVersionFilterContext versionContext; 695 696 final CollectRequest request; 697 698 final DependencyResolutionSkipper skipper; 699 700 Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, 701 DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext, 702 CollectRequest request, DependencyResolutionSkipper skipper ) 703 { 704 this.session = session; 705 this.request = request; 706 this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories(); 707 this.premanagedState = ConfigUtils.getBoolean( session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE ); 708 this.trace = trace; 709 this.pool = pool; 710 this.collectionContext = collectionContext; 711 this.versionContext = versionContext; 712 this.skipper = skipper; 713 } 714 715 } 716 717 static class Results 718 { 719 720 private final CollectResult result; 721 722 final int maxExceptions; 723 724 final int maxCycles; 725 726 String errorPath; 727 728 Results( CollectResult result, RepositorySystemSession session ) 729 { 730 this.result = result; 731 732 maxExceptions = 733 ConfigUtils.getInteger( session, CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT, CONFIG_PROP_MAX_EXCEPTIONS ); 734 735 maxCycles = ConfigUtils.getInteger( session, CONFIG_PROP_MAX_CYCLES_DEFAULT, CONFIG_PROP_MAX_CYCLES ); 736 } 737 738 public void addException( Dependency dependency, Exception e, List<DependencyNode> nodes ) 739 { 740 if ( maxExceptions < 0 || result.getExceptions().size() < maxExceptions ) 741 { 742 result.addException( e ); 743 if ( errorPath == null ) 744 { 745 StringBuilder buffer = new StringBuilder( 256 ); 746 for ( DependencyNode node : nodes ) 747 { 748 if ( buffer.length() > 0 ) 749 { 750 buffer.append( " -> " ); 751 } 752 Dependency dep = node.getDependency(); 753 if ( dep != null ) 754 { 755 buffer.append( dep.getArtifact() ); 756 } 757 } 758 if ( buffer.length() > 0 ) 759 { 760 buffer.append( " -> " ); 761 } 762 buffer.append( dependency.getArtifact() ); 763 errorPath = buffer.toString(); 764 } 765 } 766 } 767 768 public void addCycle( List<DependencyNode> nodes, int cycleEntry, Dependency dependency ) 769 { 770 if ( maxCycles < 0 || result.getCycles().size() < maxCycles ) 771 { 772 result.addCycle( new DefaultDependencyCycle( nodes, cycleEntry, dependency ) ); 773 } 774 } 775 776 } 777 778 static class PremanagedDependency 779 { 780 781 final String premanagedVersion; 782 783 final String premanagedScope; 784 785 final Boolean premanagedOptional; 786 787 /** 788 * @since 1.1.0 789 */ 790 final Collection<Exclusion> premanagedExclusions; 791 792 /** 793 * @since 1.1.0 794 */ 795 final Map<String, String> premanagedProperties; 796 797 final int managedBits; 798 799 final Dependency managedDependency; 800 801 final boolean premanagedState; 802 803 @SuppressWarnings( "checkstyle:parameternumber" ) 804 PremanagedDependency( String premanagedVersion, String premanagedScope, Boolean premanagedOptional, 805 Collection<Exclusion> premanagedExclusions, Map<String, String> premanagedProperties, 806 int managedBits, Dependency managedDependency, boolean premanagedState ) 807 { 808 this.premanagedVersion = premanagedVersion; 809 this.premanagedScope = premanagedScope; 810 this.premanagedOptional = premanagedOptional; 811 this.premanagedExclusions = 812 premanagedExclusions != null 813 ? Collections.unmodifiableCollection( new ArrayList<>( premanagedExclusions ) ) 814 : null; 815 816 this.premanagedProperties = 817 premanagedProperties != null 818 ? Collections.unmodifiableMap( new HashMap<>( premanagedProperties ) ) 819 : null; 820 821 this.managedBits = managedBits; 822 this.managedDependency = managedDependency; 823 this.premanagedState = premanagedState; 824 } 825 826 static PremanagedDependency create( DependencyManager depManager, Dependency dependency, 827 boolean disableVersionManagement, boolean premanagedState ) 828 { 829 DependencyManagement depMngt = depManager != null ? depManager.manageDependency( dependency ) : null; 830 831 int managedBits = 0; 832 String premanagedVersion = null; 833 String premanagedScope = null; 834 Boolean premanagedOptional = null; 835 Collection<Exclusion> premanagedExclusions = null; 836 Map<String, String> premanagedProperties = null; 837 838 if ( depMngt != null ) 839 { 840 if ( depMngt.getVersion() != null && !disableVersionManagement ) 841 { 842 Artifact artifact = dependency.getArtifact(); 843 premanagedVersion = artifact.getVersion(); 844 dependency = dependency.setArtifact( artifact.setVersion( depMngt.getVersion() ) ); 845 managedBits |= DependencyNode.MANAGED_VERSION; 846 } 847 if ( depMngt.getProperties() != null ) 848 { 849 Artifact artifact = dependency.getArtifact(); 850 premanagedProperties = artifact.getProperties(); 851 dependency = dependency.setArtifact( artifact.setProperties( depMngt.getProperties() ) ); 852 managedBits |= DependencyNode.MANAGED_PROPERTIES; 853 } 854 if ( depMngt.getScope() != null ) 855 { 856 premanagedScope = dependency.getScope(); 857 dependency = dependency.setScope( depMngt.getScope() ); 858 managedBits |= DependencyNode.MANAGED_SCOPE; 859 } 860 if ( depMngt.getOptional() != null ) 861 { 862 premanagedOptional = dependency.isOptional(); 863 dependency = dependency.setOptional( depMngt.getOptional() ); 864 managedBits |= DependencyNode.MANAGED_OPTIONAL; 865 } 866 if ( depMngt.getExclusions() != null ) 867 { 868 premanagedExclusions = dependency.getExclusions(); 869 dependency = dependency.setExclusions( depMngt.getExclusions() ); 870 managedBits |= DependencyNode.MANAGED_EXCLUSIONS; 871 } 872 } 873 return new PremanagedDependency( premanagedVersion, premanagedScope, premanagedOptional, 874 premanagedExclusions, premanagedProperties, managedBits, dependency, 875 premanagedState ); 876 877 } 878 879 public void applyTo( DefaultDependencyNode child ) 880 { 881 child.setManagedBits( managedBits ); 882 if ( premanagedState ) 883 { 884 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION, premanagedVersion ); 885 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE, premanagedScope ); 886 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_OPTIONAL, premanagedOptional ); 887 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_EXCLUSIONS, premanagedExclusions ); 888 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_PROPERTIES, premanagedProperties ); 889 } 890 } 891 892 } 893 894}