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