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.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.spi.log.Logger; 069import org.eclipse.aether.spi.log.LoggerFactory; 070import org.eclipse.aether.spi.log.NullLoggerFactory; 071import org.eclipse.aether.util.ConfigUtils; 072import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; 073import org.eclipse.aether.util.graph.transformer.TransformationContextKeys; 074import org.eclipse.aether.version.Version; 075 076/** 077 */ 078@Named 079public class DefaultDependencyCollector 080 implements DependencyCollector, Service 081{ 082 083 private static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions"; 084 085 private static final String CONFIG_PROP_MAX_CYCLES = "aether.dependencyCollector.maxCycles"; 086 087 private Logger logger = NullLoggerFactory.LOGGER; 088 089 private RemoteRepositoryManager remoteRepositoryManager; 090 091 private ArtifactDescriptorReader descriptorReader; 092 093 private VersionRangeResolver versionRangeResolver; 094 095 public DefaultDependencyCollector() 096 { 097 // enables default constructor 098 } 099 100 @Inject 101 DefaultDependencyCollector( RemoteRepositoryManager remoteRepositoryManager, 102 ArtifactDescriptorReader artifactDescriptorReader, 103 VersionRangeResolver versionRangeResolver, LoggerFactory loggerFactory ) 104 { 105 setRemoteRepositoryManager( remoteRepositoryManager ); 106 setArtifactDescriptorReader( artifactDescriptorReader ); 107 setVersionRangeResolver( versionRangeResolver ); 108 setLoggerFactory( loggerFactory ); 109 } 110 111 public void initService( ServiceLocator locator ) 112 { 113 setLoggerFactory( locator.getService( LoggerFactory.class ) ); 114 setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) ); 115 setArtifactDescriptorReader( locator.getService( ArtifactDescriptorReader.class ) ); 116 setVersionRangeResolver( locator.getService( VersionRangeResolver.class ) ); 117 } 118 119 public DefaultDependencyCollector setLoggerFactory( LoggerFactory loggerFactory ) 120 { 121 this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() ); 122 return this; 123 } 124 125 public DefaultDependencyCollector setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager ) 126 { 127 this.remoteRepositoryManager = requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" ); 128 return this; 129 } 130 131 public DefaultDependencyCollector setArtifactDescriptorReader( ArtifactDescriptorReader artifactDescriptorReader ) 132 { 133 descriptorReader = requireNonNull( artifactDescriptorReader, "artifact descriptor reader cannot be null" ); 134 return this; 135 } 136 137 public DefaultDependencyCollector setVersionRangeResolver( VersionRangeResolver versionRangeResolver ) 138 { 139 this.versionRangeResolver = requireNonNull( versionRangeResolver, "version range resolver cannot be null" ); 140 return this; 141 } 142 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 = logger.isDebugEnabled() ? new LinkedHashMap<String, Object>() : null; 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 if ( stats != null ) 284 { 285 long time3 = System.nanoTime(); 286 stats.put( "DefaultDependencyCollector.collectTime", time2 - time1 ); 287 stats.put( "DefaultDependencyCollector.transformTime", time3 - time2 ); 288 logger.debug( "Dependency collection stats: " + stats ); 289 } 290 291 if ( errorPath != null ) 292 { 293 throw new DependencyCollectionException( result, "Failed to collect dependencies at " + errorPath ); 294 } 295 if ( !result.getExceptions().isEmpty() ) 296 { 297 throw new DependencyCollectionException( result ); 298 } 299 300 return result; 301 } 302 303 private static RepositorySystemSession optimizeSession( RepositorySystemSession session ) 304 { 305 DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session ); 306 optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) ); 307 return optimized; 308 } 309 310 private List<Dependency> mergeDeps( List<Dependency> dominant, List<Dependency> recessive ) 311 { 312 List<Dependency> result; 313 if ( dominant == null || dominant.isEmpty() ) 314 { 315 result = recessive; 316 } 317 else if ( recessive == null || recessive.isEmpty() ) 318 { 319 result = dominant; 320 } 321 else 322 { 323 int initialCapacity = dominant.size() + recessive.size(); 324 result = new ArrayList<Dependency>( initialCapacity ); 325 Collection<String> ids = new HashSet<String>( initialCapacity, 1.0f ); 326 for ( Dependency dependency : dominant ) 327 { 328 ids.add( getId( dependency.getArtifact() ) ); 329 result.add( dependency ); 330 } 331 for ( Dependency dependency : recessive ) 332 { 333 if ( !ids.contains( getId( dependency.getArtifact() ) ) ) 334 { 335 result.add( dependency ); 336 } 337 } 338 } 339 return result; 340 } 341 342 private static String getId( Artifact a ) 343 { 344 return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension(); 345 } 346 347 private void process( final Args args, Results results, List<Dependency> dependencies, 348 List<RemoteRepository> repositories, DependencySelector depSelector, 349 DependencyManager depManager, DependencyTraverser depTraverser, VersionFilter verFilter ) 350 { 351 for ( Dependency dependency : dependencies ) 352 { 353 processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, 354 dependency ); 355 } 356 } 357 358 private void processDependency( Args args, Results results, List<RemoteRepository> repositories, 359 DependencySelector depSelector, DependencyManager depManager, 360 DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency ) 361 { 362 363 List<Artifact> relocations = Collections.emptyList(); 364 boolean disableVersionManagement = false; 365 processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency, 366 relocations, disableVersionManagement ); 367 } 368 369 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 private void doRecurse( Args args, Results results, List<RemoteRepository> repositories, 479 DependencySelector depSelector, DependencyManager depManager, 480 DependencyTraverser depTraverser, VersionFilter verFilter, Dependency d, 481 ArtifactDescriptorResult descriptorResult, DefaultDependencyNode child ) 482 { 483 DefaultDependencyCollectionContext context = args.collectionContext; 484 context.set( d, descriptorResult.getManagedDependencies() ); 485 486 DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector( context ) : null; 487 DependencyManager childManager = depManager != null ? depManager.deriveChildManager( context ) : null; 488 DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null; 489 VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null; 490 491 final List<RemoteRepository> childRepos = 492 args.ignoreRepos 493 ? repositories 494 : remoteRepositoryManager.aggregateRepositories( args.session, repositories, 495 descriptorResult.getRepositories(), true ); 496 497 Object key = 498 args.pool.toKey( d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter ); 499 500 List<DependencyNode> children = args.pool.getChildren( key ); 501 if ( children == null ) 502 { 503 args.pool.putChildren( key, child.getChildren() ); 504 505 args.nodes.push( child ); 506 507 process( args, results, descriptorResult.getDependencies(), childRepos, childSelector, childManager, 508 childTraverser, childFilter ); 509 510 args.nodes.pop(); 511 } 512 else 513 { 514 child.setChildren( children ); 515 } 516 } 517 518 private ArtifactDescriptorResult getArtifactDescriptorResult( Args args, Results results, boolean noDescriptor, 519 Dependency d, 520 ArtifactDescriptorRequest descriptorRequest ) 521 { 522 return noDescriptor 523 ? new ArtifactDescriptorResult( descriptorRequest ) 524 : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, args ); 525 526 } 527 528 private ArtifactDescriptorResult resolveCachedArtifactDescriptor( DataPool pool, 529 ArtifactDescriptorRequest descriptorRequest, 530 RepositorySystemSession session, Dependency d, 531 Results results, Args args ) 532 { 533 Object key = pool.toKey( descriptorRequest ); 534 ArtifactDescriptorResult descriptorResult = pool.getDescriptor( key, descriptorRequest ); 535 if ( descriptorResult == null ) 536 { 537 try 538 { 539 descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); 540 pool.putDescriptor( key, descriptorResult ); 541 } 542 catch ( ArtifactDescriptorException e ) 543 { 544 results.addException( d, e, args.nodes ); 545 pool.putDescriptor( key, e ); 546 return null; 547 } 548 549 } 550 else if ( descriptorResult == DataPool.NO_DESCRIPTOR ) 551 { 552 return null; 553 } 554 555 return descriptorResult; 556 } 557 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 this.maxExceptions = ConfigUtils.getInteger( session, 50, CONFIG_PROP_MAX_EXCEPTIONS ); 738 this.maxCycles = ConfigUtils.getInteger( session, 10, CONFIG_PROP_MAX_CYCLES ); 739 } 740 741 public void addException( Dependency dependency, Exception e, NodeStack nodes ) 742 { 743 if ( maxExceptions < 0 || result.getExceptions().size() < maxExceptions ) 744 { 745 result.addException( e ); 746 if ( errorPath == null ) 747 { 748 StringBuilder buffer = new StringBuilder( 256 ); 749 for ( int i = 0; i < nodes.size(); i++ ) 750 { 751 if ( buffer.length() > 0 ) 752 { 753 buffer.append( " -> " ); 754 } 755 Dependency dep = nodes.get( i ).getDependency(); 756 if ( dep != null ) 757 { 758 buffer.append( dep.getArtifact() ); 759 } 760 } 761 if ( buffer.length() > 0 ) 762 { 763 buffer.append( " -> " ); 764 } 765 buffer.append( dependency.getArtifact() ); 766 errorPath = buffer.toString(); 767 } 768 } 769 } 770 771 public void addCycle( NodeStack nodes, int cycleEntry, Dependency dependency ) 772 { 773 if ( maxCycles < 0 || result.getCycles().size() < maxCycles ) 774 { 775 result.addCycle( new DefaultDependencyCycle( nodes, cycleEntry, dependency ) ); 776 } 777 } 778 779 } 780 781 static class PremanagedDependency 782 { 783 784 final String premanagedVersion; 785 786 final String premanagedScope; 787 788 final Boolean premanagedOptional; 789 790 /** 791 * @since 1.1.0 792 */ 793 final Collection<Exclusion> premanagedExclusions; 794 795 /** 796 * @since 1.1.0 797 */ 798 final Map<String, String> premanagedProperties; 799 800 final int managedBits; 801 802 final Dependency managedDependency; 803 804 final boolean premanagedState; 805 806 PremanagedDependency( String premanagedVersion, String premanagedScope, Boolean premanagedOptional, 807 Collection<Exclusion> premanagedExclusions, Map<String, String> premanagedProperties, 808 int managedBits, Dependency managedDependency, boolean premanagedState ) 809 { 810 this.premanagedVersion = premanagedVersion; 811 this.premanagedScope = premanagedScope; 812 this.premanagedOptional = premanagedOptional; 813 this.premanagedExclusions = 814 premanagedExclusions != null 815 ? Collections.unmodifiableCollection( new ArrayList<Exclusion>( premanagedExclusions ) ) 816 : null; 817 818 this.premanagedProperties = 819 premanagedProperties != null 820 ? Collections.unmodifiableMap( new HashMap<String, String>( premanagedProperties ) ) 821 : null; 822 823 this.managedBits = managedBits; 824 this.managedDependency = managedDependency; 825 this.premanagedState = premanagedState; 826 } 827 828 static PremanagedDependency create( DependencyManager depManager, Dependency dependency, 829 boolean disableVersionManagement, boolean premanagedState ) 830 { 831 DependencyManagement depMngt = depManager != null ? depManager.manageDependency( dependency ) : null; 832 833 int managedBits = 0; 834 String premanagedVersion = null; 835 String premanagedScope = null; 836 Boolean premanagedOptional = null; 837 Collection<Exclusion> premanagedExclusions = null; 838 Map<String, String> premanagedProperties = null; 839 840 if ( depMngt != null ) 841 { 842 if ( depMngt.getVersion() != null && !disableVersionManagement ) 843 { 844 Artifact artifact = dependency.getArtifact(); 845 premanagedVersion = artifact.getVersion(); 846 dependency = dependency.setArtifact( artifact.setVersion( depMngt.getVersion() ) ); 847 managedBits |= DependencyNode.MANAGED_VERSION; 848 } 849 if ( depMngt.getProperties() != null ) 850 { 851 Artifact artifact = dependency.getArtifact(); 852 premanagedProperties = artifact.getProperties(); 853 dependency = dependency.setArtifact( artifact.setProperties( depMngt.getProperties() ) ); 854 managedBits |= DependencyNode.MANAGED_PROPERTIES; 855 } 856 if ( depMngt.getScope() != null ) 857 { 858 premanagedScope = dependency.getScope(); 859 dependency = dependency.setScope( depMngt.getScope() ); 860 managedBits |= DependencyNode.MANAGED_SCOPE; 861 } 862 if ( depMngt.getOptional() != null ) 863 { 864 premanagedOptional = dependency.isOptional(); 865 dependency = dependency.setOptional( depMngt.getOptional() ); 866 managedBits |= DependencyNode.MANAGED_OPTIONAL; 867 } 868 if ( depMngt.getExclusions() != null ) 869 { 870 premanagedExclusions = dependency.getExclusions(); 871 dependency = dependency.setExclusions( depMngt.getExclusions() ); 872 managedBits |= DependencyNode.MANAGED_EXCLUSIONS; 873 } 874 } 875 return new PremanagedDependency( premanagedVersion, premanagedScope, premanagedOptional, 876 premanagedExclusions, premanagedProperties, managedBits, dependency, 877 premanagedState ); 878 879 } 880 881 public void applyTo( DefaultDependencyNode child ) 882 { 883 child.setManagedBits( managedBits ); 884 if ( premanagedState ) 885 { 886 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION, premanagedVersion ); 887 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE, premanagedScope ); 888 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_OPTIONAL, premanagedOptional ); 889 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_EXCLUSIONS, premanagedExclusions ); 890 child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_PROPERTIES, premanagedProperties ); 891 } 892 } 893 894 } 895 896}