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; 034import javax.inject.Singleton; 035 036import org.eclipse.aether.DefaultRepositorySystemSession; 037import org.eclipse.aether.RepositoryException; 038import org.eclipse.aether.RepositorySystemSession; 039import org.eclipse.aether.RequestTrace; 040import org.eclipse.aether.artifact.Artifact; 041import org.eclipse.aether.artifact.ArtifactProperties; 042import org.eclipse.aether.collection.CollectRequest; 043import org.eclipse.aether.collection.CollectResult; 044import org.eclipse.aether.collection.DependencyCollectionException; 045import org.eclipse.aether.collection.DependencyGraphTransformer; 046import org.eclipse.aether.collection.DependencyManagement; 047import org.eclipse.aether.collection.DependencyManager; 048import org.eclipse.aether.collection.DependencySelector; 049import org.eclipse.aether.collection.DependencyTraverser; 050import org.eclipse.aether.collection.VersionFilter; 051import org.eclipse.aether.graph.DefaultDependencyNode; 052import org.eclipse.aether.graph.Dependency; 053import org.eclipse.aether.graph.DependencyNode; 054import org.eclipse.aether.graph.Exclusion; 055import org.eclipse.aether.impl.ArtifactDescriptorReader; 056import org.eclipse.aether.impl.DependencyCollector; 057import org.eclipse.aether.impl.RemoteRepositoryManager; 058import org.eclipse.aether.impl.VersionRangeResolver; 059import org.eclipse.aether.repository.ArtifactRepository; 060import org.eclipse.aether.repository.RemoteRepository; 061import org.eclipse.aether.resolution.ArtifactDescriptorException; 062import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 063import org.eclipse.aether.resolution.ArtifactDescriptorResult; 064import org.eclipse.aether.resolution.VersionRangeRequest; 065import org.eclipse.aether.resolution.VersionRangeResolutionException; 066import org.eclipse.aether.resolution.VersionRangeResult; 067import org.eclipse.aether.spi.locator.Service; 068import org.eclipse.aether.spi.locator.ServiceLocator; 069import org.eclipse.aether.util.ConfigUtils; 070import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 071import org.eclipse.aether.util.graph.transformer.TransformationContextKeys; 072import org.eclipse.aether.version.Version; 073import org.slf4j.Logger; 074import org.slf4j.LoggerFactory; 075 076/** 077 */ 078@Singleton 079@Named 080public class DefaultDependencyCollector 081 implements DependencyCollector, Service 082{ 083 084 private static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions"; 085 086 private static final int CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT = 50; 087 088 private static final String CONFIG_PROP_MAX_CYCLES = "aether.dependencyCollector.maxCycles"; 089 090 private static final int CONFIG_PROP_MAX_CYCLES_DEFAULT = 10; 091 092 private static final Logger LOGGER = LoggerFactory.getLogger( DefaultDependencyCollector.class ); 093 094 private RemoteRepositoryManager remoteRepositoryManager; 095 096 private ArtifactDescriptorReader descriptorReader; 097 098 private VersionRangeResolver versionRangeResolver; 099 100 public DefaultDependencyCollector() 101 { 102 // enables default constructor 103 } 104 105 @Inject 106 DefaultDependencyCollector( RemoteRepositoryManager remoteRepositoryManager, 107 ArtifactDescriptorReader artifactDescriptorReader, 108 VersionRangeResolver versionRangeResolver ) 109 { 110 setRemoteRepositoryManager( remoteRepositoryManager ); 111 setArtifactDescriptorReader( artifactDescriptorReader ); 112 setVersionRangeResolver( versionRangeResolver ); 113 } 114 115 public void initService( ServiceLocator locator ) 116 { 117 setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) ); 118 setArtifactDescriptorReader( locator.getService( ArtifactDescriptorReader.class ) ); 119 setVersionRangeResolver( locator.getService( VersionRangeResolver.class ) ); 120 } 121 122 public DefaultDependencyCollector setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager ) 123 { 124 this.remoteRepositoryManager = 125 requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" ); 126 return this; 127 } 128 129 public DefaultDependencyCollector setArtifactDescriptorReader( ArtifactDescriptorReader artifactDescriptorReader ) 130 { 131 descriptorReader = requireNonNull( artifactDescriptorReader, "artifact descriptor reader cannot be null" ); 132 return this; 133 } 134 135 public DefaultDependencyCollector setVersionRangeResolver( VersionRangeResolver versionRangeResolver ) 136 { 137 this.versionRangeResolver = 138 requireNonNull( versionRangeResolver, "version range resolver cannot be null" ); 139 return this; 140 } 141 142 @SuppressWarnings( "checkstyle:methodlength" ) 143 public CollectResult collectDependencies( RepositorySystemSession session, CollectRequest request ) 144 throws DependencyCollectionException 145 { 146 requireNonNull( session, "session cannot be null" ); 147 requireNonNull( request, "request cannot be null" ); 148 session = optimizeSession( session ); 149 150 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); 151 152 CollectResult result = new CollectResult( request ); 153 154 DependencySelector depSelector = session.getDependencySelector(); 155 DependencyManager depManager = session.getDependencyManager(); 156 DependencyTraverser depTraverser = session.getDependencyTraverser(); 157 VersionFilter verFilter = session.getVersionFilter(); 158 159 Dependency root = request.getRoot(); 160 List<RemoteRepository> repositories = request.getRepositories(); 161 List<Dependency> dependencies = request.getDependencies(); 162 List<Dependency> managedDependencies = request.getManagedDependencies(); 163 164 Map<String, Object> stats = new LinkedHashMap<>(); 165 long time1 = System.nanoTime(); 166 167 DefaultDependencyNode node; 168 if ( root != null ) 169 { 170 List<? extends Version> versions; 171 VersionRangeResult rangeResult; 172 try 173 { 174 VersionRangeRequest rangeRequest = 175 new VersionRangeRequest( root.getArtifact(), request.getRepositories(), 176 request.getRequestContext() ); 177 rangeRequest.setTrace( trace ); 178 rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest ); 179 versions = filterVersions( root, rangeResult, verFilter, new DefaultVersionFilterContext( session ) ); 180 } 181 catch ( VersionRangeResolutionException e ) 182 { 183 result.addException( e ); 184 throw new DependencyCollectionException( result, e.getMessage() ); 185 } 186 187 Version version = versions.get( versions.size() - 1 ); 188 root = root.setArtifact( root.getArtifact().setVersion( version.toString() ) ); 189 190 ArtifactDescriptorResult descriptorResult; 191 try 192 { 193 ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(); 194 descriptorRequest.setArtifact( root.getArtifact() ); 195 descriptorRequest.setRepositories( request.getRepositories() ); 196 descriptorRequest.setRequestContext( request.getRequestContext() ); 197 descriptorRequest.setTrace( trace ); 198 if ( isLackingDescriptor( root.getArtifact() ) ) 199 { 200 descriptorResult = new ArtifactDescriptorResult( descriptorRequest ); 201 } 202 else 203 { 204 descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); 205 } 206 } 207 catch ( ArtifactDescriptorException e ) 208 { 209 result.addException( e ); 210 throw new DependencyCollectionException( result, e.getMessage() ); 211 } 212 213 root = root.setArtifact( descriptorResult.getArtifact() ); 214 215 if ( !session.isIgnoreArtifactDescriptorRepositories() ) 216 { 217 repositories = remoteRepositoryManager.aggregateRepositories( session, repositories, 218 descriptorResult.getRepositories(), 219 true ); 220 } 221 dependencies = mergeDeps( dependencies, descriptorResult.getDependencies() ); 222 managedDependencies = mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() ); 223 224 node = new DefaultDependencyNode( root ); 225 node.setRequestContext( request.getRequestContext() ); 226 node.setRelocations( descriptorResult.getRelocations() ); 227 node.setVersionConstraint( rangeResult.getVersionConstraint() ); 228 node.setVersion( version ); 229 node.setAliases( descriptorResult.getAliases() ); 230 node.setRepositories( request.getRepositories() ); 231 } 232 else 233 { 234 node = new DefaultDependencyNode( request.getRootArtifact() ); 235 node.setRequestContext( request.getRequestContext() ); 236 node.setRepositories( request.getRepositories() ); 237 } 238 239 result.setRoot( node ); 240 241 boolean traverse = root == null || depTraverser == null || depTraverser.traverseDependency( root ); 242 String errorPath = null; 243 if ( traverse && !dependencies.isEmpty() ) 244 { 245 DataPool pool = new DataPool( session ); 246 247 NodeStack nodes = new NodeStack(); 248 nodes.push( node ); 249 250 DefaultDependencyCollectionContext context = 251 new DefaultDependencyCollectionContext( session, request.getRootArtifact(), root, managedDependencies ); 252 253 DefaultVersionFilterContext versionContext = new DefaultVersionFilterContext( session ); 254 255 Args args = new Args( session, trace, pool, nodes, context, versionContext, request ); 256 Results results = new Results( result, session ); 257 258 process( args, results, dependencies, repositories, 259 depSelector != null ? depSelector.deriveChildSelector( context ) : null, 260 depManager != null ? depManager.deriveChildManager( context ) : null, 261 depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null, 262 verFilter != null ? verFilter.deriveChildFilter( context ) : null ); 263 264 errorPath = results.errorPath; 265 } 266 267 long time2 = System.nanoTime(); 268 269 DependencyGraphTransformer transformer = session.getDependencyGraphTransformer(); 270 if ( transformer != null ) 271 { 272 try 273 { 274 DefaultDependencyGraphTransformationContext context = 275 new DefaultDependencyGraphTransformationContext( session ); 276 context.put( TransformationContextKeys.STATS, stats ); 277 result.setRoot( transformer.transformGraph( node, context ) ); 278 } 279 catch ( RepositoryException e ) 280 { 281 result.addException( e ); 282 } 283 } 284 285 long time3 = System.nanoTime(); 286 stats.put( "DefaultDependencyCollector.collectTime", time2 - time1 ); 287 stats.put( "DefaultDependencyCollector.transformTime", time3 - time2 ); 288 LOGGER.debug( "Dependency collection stats {}", stats ); 289 290 if ( errorPath != null ) 291 { 292 throw new DependencyCollectionException( result, "Failed to collect dependencies at " + errorPath ); 293 } 294 if ( !result.getExceptions().isEmpty() ) 295 { 296 throw new DependencyCollectionException( result ); 297 } 298 299 return result; 300 } 301 302 private static RepositorySystemSession optimizeSession( RepositorySystemSession session ) 303 { 304 DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session ); 305 optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) ); 306 return optimized; 307 } 308 309 private List<Dependency> mergeDeps( List<Dependency> dominant, List<Dependency> recessive ) 310 { 311 List<Dependency> result; 312 if ( dominant == null || dominant.isEmpty() ) 313 { 314 result = recessive; 315 } 316 else if ( recessive == null || recessive.isEmpty() ) 317 { 318 result = dominant; 319 } 320 else 321 { 322 int initialCapacity = dominant.size() + recessive.size(); 323 result = new ArrayList<>( initialCapacity ); 324 Collection<String> ids = new HashSet<>( initialCapacity, 1.0f ); 325 for ( Dependency dependency : dominant ) 326 { 327 ids.add( getId( dependency.getArtifact() ) ); 328 result.add( dependency ); 329 } 330 for ( Dependency dependency : recessive ) 331 { 332 if ( !ids.contains( getId( dependency.getArtifact() ) ) ) 333 { 334 result.add( dependency ); 335 } 336 } 337 } 338 return result; 339 } 340 341 private static String getId( Artifact a ) 342 { 343 return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension(); 344 } 345 346 @SuppressWarnings( "checkstyle:parameternumber" ) 347 private void process( final Args args, Results results, List<Dependency> dependencies, 348 List<RemoteRepository> repositories, DependencySelector depSelector, 349 DependencyManager depManager, DependencyTraverser depTraverser, VersionFilter verFilter ) 350 { 351 for ( Dependency dependency : dependencies ) 352 { 353 processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, 354 dependency ); 355 } 356 } 357 358 @SuppressWarnings( "checkstyle:parameternumber" ) 359 private void processDependency( Args args, Results results, List<RemoteRepository> repositories, 360 DependencySelector depSelector, DependencyManager depManager, 361 DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency ) 362 { 363 364 List<Artifact> relocations = Collections.emptyList(); 365 processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency, 366 relocations, false ); 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}