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