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