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