001 package org.apache.maven.repository.legacy.resolver; 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 022 import java.util.ArrayList; 023 import java.util.Collections; 024 import java.util.Iterator; 025 import java.util.LinkedHashMap; 026 import java.util.LinkedHashSet; 027 import java.util.List; 028 import java.util.Map; 029 import java.util.Set; 030 031 import org.apache.maven.artifact.Artifact; 032 import org.apache.maven.artifact.metadata.ArtifactMetadataSource; 033 import org.apache.maven.artifact.metadata.ResolutionGroup; 034 import org.apache.maven.artifact.repository.ArtifactRepository; 035 import org.apache.maven.artifact.resolver.ArtifactResolutionException; 036 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; 037 import org.apache.maven.artifact.resolver.ArtifactResolutionResult; 038 import org.apache.maven.artifact.resolver.CyclicDependencyException; 039 import org.apache.maven.artifact.resolver.ResolutionListener; 040 import org.apache.maven.artifact.resolver.ResolutionListenerForDepMgmt; 041 import org.apache.maven.artifact.resolver.ResolutionNode; 042 import org.apache.maven.artifact.resolver.filter.AndArtifactFilter; 043 import org.apache.maven.artifact.resolver.filter.ArtifactFilter; 044 import org.apache.maven.artifact.versioning.ArtifactVersion; 045 import org.apache.maven.artifact.versioning.ManagedVersionMap; 046 import org.apache.maven.artifact.versioning.OverConstrainedVersionException; 047 import org.apache.maven.artifact.versioning.VersionRange; 048 import org.apache.maven.execution.MavenSession; 049 import org.apache.maven.plugin.LegacySupport; 050 import org.apache.maven.repository.legacy.metadata.ArtifactMetadataRetrievalException; 051 import org.apache.maven.repository.legacy.metadata.DefaultMetadataResolutionRequest; 052 import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest; 053 import org.apache.maven.repository.legacy.resolver.conflict.ConflictResolver; 054 import org.codehaus.plexus.component.annotations.Component; 055 import org.codehaus.plexus.component.annotations.Requirement; 056 import org.codehaus.plexus.logging.Logger; 057 058 /** 059 * @author <a href="mailto:brett@apache.org">Brett Porter</a> 060 * @author Jason van Zyl 061 */ 062 @Component( role = LegacyArtifactCollector.class ) 063 public class DefaultLegacyArtifactCollector 064 implements LegacyArtifactCollector 065 { 066 @Requirement(hint="nearest") 067 private ConflictResolver defaultConflictResolver; 068 069 @Requirement 070 private Logger logger; 071 072 @Requirement 073 private LegacySupport legacySupport; 074 075 private void injectSession( ArtifactResolutionRequest request ) 076 { 077 MavenSession session = legacySupport.getSession(); 078 079 if ( session != null ) 080 { 081 request.setOffline( session.isOffline() ); 082 request.setForceUpdate( session.getRequest().isUpdateSnapshots() ); 083 request.setServers( session.getRequest().getServers() ); 084 request.setMirrors( session.getRequest().getMirrors() ); 085 request.setProxies( session.getRequest().getProxies() ); 086 } 087 } 088 089 public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, 090 Map managedVersions, ArtifactRepository localRepository, 091 List<ArtifactRepository> remoteRepositories, 092 ArtifactMetadataSource source, ArtifactFilter filter, 093 List<ResolutionListener> listeners, 094 List<ConflictResolver> conflictResolvers ) 095 { 096 ArtifactResolutionRequest request = new ArtifactResolutionRequest(); 097 request.setLocalRepository( localRepository ); 098 request.setRemoteRepositories( remoteRepositories ); 099 injectSession( request ); 100 return collect( artifacts, originatingArtifact, managedVersions, request, source, filter, listeners, 101 conflictResolvers ); 102 } 103 104 public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, 105 Map managedVersions, ArtifactResolutionRequest repositoryRequest, 106 ArtifactMetadataSource source, ArtifactFilter filter, 107 List<ResolutionListener> listeners, 108 List<ConflictResolver> conflictResolvers ) 109 { 110 ArtifactResolutionResult result = new ArtifactResolutionResult(); 111 112 result.setOriginatingArtifact( originatingArtifact ); 113 114 if ( conflictResolvers == null ) 115 { 116 conflictResolvers = Collections.singletonList( defaultConflictResolver ); 117 } 118 119 Map<Object, List<ResolutionNode>> resolvedArtifacts = new LinkedHashMap<Object, List<ResolutionNode>>(); 120 121 ResolutionNode root = new ResolutionNode( originatingArtifact, repositoryRequest.getRemoteRepositories() ); 122 123 try 124 { 125 root.addDependencies( artifacts, repositoryRequest.getRemoteRepositories(), filter ); 126 } 127 catch ( CyclicDependencyException e ) 128 { 129 result.addCircularDependencyException( e ); 130 131 return result; 132 } 133 catch ( OverConstrainedVersionException e ) 134 { 135 result.addVersionRangeViolation( e ); 136 137 return result; 138 } 139 140 ManagedVersionMap versionMap = getManagedVersionsMap( originatingArtifact, managedVersions ); 141 142 try 143 { 144 recurse( result, root, resolvedArtifacts, versionMap, repositoryRequest, source, filter, listeners, 145 conflictResolvers ); 146 } 147 catch ( CyclicDependencyException e ) 148 { 149 logger.debug( "While recursing: " + e.getMessage(), e ); 150 result.addCircularDependencyException( e ); 151 } 152 catch ( OverConstrainedVersionException e ) 153 { 154 logger.debug( "While recursing: " + e.getMessage(), e ); 155 result.addVersionRangeViolation( e ); 156 } 157 catch ( ArtifactResolutionException e ) 158 { 159 logger.debug( "While recursing: " + e.getMessage(), e ); 160 result.addErrorArtifactException( e ); 161 } 162 163 Set<ResolutionNode> set = new LinkedHashSet<ResolutionNode>(); 164 165 for ( List<ResolutionNode> nodes : resolvedArtifacts.values() ) 166 { 167 for ( ResolutionNode node : nodes ) 168 { 169 if ( !node.equals( root ) && node.isActive() ) 170 { 171 Artifact artifact = node.getArtifact(); 172 173 try 174 { 175 if ( node.filterTrail( filter ) ) 176 { 177 // If it was optional and not a direct dependency, 178 // we don't add it or its children, just allow the update of the version and artifactScope 179 if ( node.isChildOfRootNode() || !artifact.isOptional() ) 180 { 181 artifact.setDependencyTrail( node.getDependencyTrail() ); 182 183 set.add( node ); 184 185 // This is required right now. 186 result.addArtifact( artifact ); 187 } 188 } 189 } 190 catch ( OverConstrainedVersionException e ) 191 { 192 result.addVersionRangeViolation( e ); 193 } 194 } 195 } 196 } 197 198 result.setArtifactResolutionNodes( set ); 199 200 return result; 201 } 202 203 /** 204 * Get the map of managed versions, removing the originating artifact if it is also in managed versions 205 * 206 * @param originatingArtifact artifact we are processing 207 * @param managedVersions original managed versions 208 */ 209 private ManagedVersionMap getManagedVersionsMap( Artifact originatingArtifact, Map managedVersions ) 210 { 211 ManagedVersionMap versionMap; 212 if ( ( managedVersions != null ) && ( managedVersions instanceof ManagedVersionMap ) ) 213 { 214 versionMap = (ManagedVersionMap) managedVersions; 215 } 216 else 217 { 218 versionMap = new ManagedVersionMap( managedVersions ); 219 } 220 221 /* remove the originating artifact if it is also in managed versions to avoid being modified during resolution */ 222 Artifact managedOriginatingArtifact = (Artifact) versionMap.get( originatingArtifact.getDependencyConflictId() ); 223 224 if ( managedOriginatingArtifact != null ) 225 { 226 // TODO we probably want to warn the user that he is building an artifact with 227 // different values than in dependencyManagement 228 if ( managedVersions instanceof ManagedVersionMap ) 229 { 230 /* avoid modifying the managedVersions parameter creating a new map */ 231 versionMap = new ManagedVersionMap( managedVersions ); 232 } 233 versionMap.remove( originatingArtifact.getDependencyConflictId() ); 234 } 235 236 return versionMap; 237 } 238 239 private void recurse( ArtifactResolutionResult result, ResolutionNode node, 240 Map<Object, List<ResolutionNode>> resolvedArtifacts, ManagedVersionMap managedVersions, 241 ArtifactResolutionRequest request, ArtifactMetadataSource source, ArtifactFilter filter, 242 List<ResolutionListener> listeners, List<ConflictResolver> conflictResolvers ) 243 throws ArtifactResolutionException 244 { 245 fireEvent( ResolutionListener.TEST_ARTIFACT, listeners, node ); 246 247 Object key = node.getKey(); 248 249 // TODO: Does this check need to happen here? Had to add the same call 250 // below when we iterate on child nodes -- will that suffice? 251 if ( managedVersions.containsKey( key ) ) 252 { 253 manageArtifact( node, managedVersions, listeners ); 254 } 255 256 List<ResolutionNode> previousNodes = resolvedArtifacts.get( key ); 257 258 if ( previousNodes != null ) 259 { 260 for ( ResolutionNode previous : previousNodes ) 261 { 262 try 263 { 264 if ( previous.isActive() ) 265 { 266 // Version mediation 267 VersionRange previousRange = previous.getArtifact().getVersionRange(); 268 VersionRange currentRange = node.getArtifact().getVersionRange(); 269 270 if ( ( previousRange != null ) && ( currentRange != null ) ) 271 { 272 // TODO: shouldn't need to double up on this work, only done for simplicity of handling 273 // recommended 274 // version but the restriction is identical 275 VersionRange newRange = previousRange.restrict( currentRange ); 276 // TODO: ick. this forces the OCE that should have come from the previous call. It is still 277 // correct 278 if ( newRange.isSelectedVersionKnown( previous.getArtifact() ) ) 279 { 280 fireEvent( ResolutionListener.RESTRICT_RANGE, listeners, node, previous.getArtifact(), 281 newRange ); 282 } 283 previous.getArtifact().setVersionRange( newRange ); 284 node.getArtifact().setVersionRange( currentRange.restrict( previousRange ) ); 285 286 // Select an appropriate available version from the (now restricted) range 287 // Note this version was selected before to get the appropriate POM 288 // But it was reset by the call to setVersionRange on restricting the version 289 ResolutionNode[] resetNodes = { previous, node }; 290 for ( int j = 0; j < 2; j++ ) 291 { 292 Artifact resetArtifact = resetNodes[j].getArtifact(); 293 294 // MNG-2123: if the previous node was not a range, then it wouldn't have any available 295 // versions. We just clobbered the selected version above. (why? i have no idea.) 296 // So since we are here and this is ranges we must go figure out the version (for a 297 // third time...) 298 if ( resetArtifact.getVersion() == null && resetArtifact.getVersionRange() != null ) 299 { 300 301 // go find the version. This is a total hack. See previous comment. 302 List<ArtifactVersion> versions = resetArtifact.getAvailableVersions(); 303 if ( versions == null ) 304 { 305 try 306 { 307 MetadataResolutionRequest metadataRequest = 308 new DefaultMetadataResolutionRequest( request ); 309 metadataRequest.setArtifact( resetArtifact ); 310 versions = source.retrieveAvailableVersions( metadataRequest ); 311 resetArtifact.setAvailableVersions( versions ); 312 } 313 catch ( ArtifactMetadataRetrievalException e ) 314 { 315 resetArtifact.setDependencyTrail( node.getDependencyTrail() ); 316 throw new ArtifactResolutionException( 317 "Unable to get dependency information: " 318 + e.getMessage(), resetArtifact, 319 request.getRemoteRepositories(), e ); 320 } 321 } 322 // end hack 323 324 // MNG-2861: match version can return null 325 ArtifactVersion selectedVersion = 326 resetArtifact.getVersionRange().matchVersion( resetArtifact.getAvailableVersions() ); 327 if ( selectedVersion != null ) 328 { 329 resetArtifact.selectVersion( selectedVersion.toString() ); 330 } 331 else 332 { 333 throw new OverConstrainedVersionException( " Unable to find a version in " 334 + resetArtifact.getAvailableVersions() + " to match the range " 335 + resetArtifact.getVersionRange(), resetArtifact ); 336 } 337 338 fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, resetNodes[j] ); 339 } 340 } 341 } 342 343 // Conflict Resolution 344 ResolutionNode resolved = null; 345 for ( Iterator j = conflictResolvers.iterator(); ( resolved == null ) && j.hasNext(); ) 346 { 347 ConflictResolver conflictResolver = (ConflictResolver) j.next(); 348 349 resolved = conflictResolver.resolveConflict( previous, node ); 350 } 351 352 if ( resolved == null ) 353 { 354 // TODO: add better exception that can detail the two conflicting artifacts 355 ArtifactResolutionException are = 356 new ArtifactResolutionException( "Cannot resolve artifact version conflict between " 357 + previous.getArtifact().getVersion() + " and " + node.getArtifact().getVersion(), 358 previous.getArtifact() ); 359 result.addVersionRangeViolation( are ); 360 } 361 362 if ( ( resolved != previous ) && ( resolved != node ) ) 363 { 364 // TODO: add better exception 365 result.addVersionRangeViolation( new ArtifactResolutionException( 366 "Conflict resolver returned unknown resolution node: ", 367 resolved.getArtifact() ) ); 368 } 369 370 // TODO: should this be part of mediation? 371 // previous one is more dominant 372 ResolutionNode nearest; 373 ResolutionNode farthest; 374 375 if ( resolved == previous ) 376 { 377 nearest = previous; 378 farthest = node; 379 } 380 else 381 { 382 nearest = node; 383 farthest = previous; 384 } 385 386 if ( checkScopeUpdate( farthest, nearest, listeners ) ) 387 { 388 // if we need to update artifactScope of nearest to use farthest artifactScope, use the 389 // nearest version, but farthest artifactScope 390 nearest.disable(); 391 farthest.getArtifact().setVersion( nearest.getArtifact().getVersion() ); 392 fireEvent( ResolutionListener.OMIT_FOR_NEARER, listeners, nearest, farthest.getArtifact() ); 393 } 394 else 395 { 396 farthest.disable(); 397 fireEvent( ResolutionListener.OMIT_FOR_NEARER, listeners, farthest, nearest.getArtifact() ); 398 } 399 } 400 } 401 catch ( OverConstrainedVersionException e ) 402 { 403 result.addVersionRangeViolation( e ); 404 } 405 } 406 } 407 else 408 { 409 previousNodes = new ArrayList<ResolutionNode>(); 410 411 resolvedArtifacts.put( key, previousNodes ); 412 } 413 previousNodes.add( node ); 414 415 if ( node.isActive() ) 416 { 417 fireEvent( ResolutionListener.INCLUDE_ARTIFACT, listeners, node ); 418 } 419 420 // don't pull in the transitive deps of a system-scoped dependency. 421 if ( node.isActive() && !Artifact.SCOPE_SYSTEM.equals( node.getArtifact().getScope() ) ) 422 { 423 fireEvent( ResolutionListener.PROCESS_CHILDREN, listeners, node ); 424 425 Artifact parentArtifact = node.getArtifact(); 426 427 for ( Iterator i = node.getChildrenIterator(); i.hasNext(); ) 428 { 429 ResolutionNode child = (ResolutionNode) i.next(); 430 431 try 432 { 433 434 // We leave in optional ones, but don't pick up its dependencies 435 if ( !child.isResolved() && ( !child.getArtifact().isOptional() || child.isChildOfRootNode() ) ) 436 { 437 Artifact artifact = child.getArtifact(); 438 artifact.setDependencyTrail( node.getDependencyTrail() ); 439 List<ArtifactRepository> childRemoteRepositories = child.getRemoteRepositories(); 440 441 MetadataResolutionRequest metadataRequest = 442 new DefaultMetadataResolutionRequest( request ); 443 metadataRequest.setArtifact( artifact ); 444 metadataRequest.setRemoteRepositories( childRemoteRepositories ); 445 446 try 447 { 448 ResolutionGroup rGroup; 449 450 Object childKey; 451 do 452 { 453 childKey = child.getKey(); 454 455 if ( managedVersions.containsKey( childKey ) ) 456 { 457 // If this child node is a managed dependency, ensure 458 // we are using the dependency management version 459 // of this child if applicable b/c we want to use the 460 // managed version's POM, *not* any other version's POM. 461 // We retrieve the POM below in the retrieval step. 462 manageArtifact( child, managedVersions, listeners ); 463 464 // Also, we need to ensure that any exclusions it presents are 465 // added to the artifact before we retrive the metadata 466 // for the artifact; otherwise we may end up with unwanted 467 // dependencies. 468 Artifact ma = (Artifact) managedVersions.get( childKey ); 469 ArtifactFilter managedExclusionFilter = ma.getDependencyFilter(); 470 if ( null != managedExclusionFilter ) 471 { 472 if ( null != artifact.getDependencyFilter() ) 473 { 474 AndArtifactFilter aaf = new AndArtifactFilter(); 475 aaf.add( artifact.getDependencyFilter() ); 476 aaf.add( managedExclusionFilter ); 477 artifact.setDependencyFilter( aaf ); 478 } 479 else 480 { 481 artifact.setDependencyFilter( managedExclusionFilter ); 482 } 483 } 484 } 485 486 if ( artifact.getVersion() == null ) 487 { 488 // set the recommended version 489 // TODO: maybe its better to just pass the range through to retrieval and use a 490 // transformation? 491 ArtifactVersion version; 492 if ( !artifact.isSelectedVersionKnown() ) 493 { 494 List<ArtifactVersion> versions = artifact.getAvailableVersions(); 495 if ( versions == null ) 496 { 497 versions = source.retrieveAvailableVersions( metadataRequest ); 498 artifact.setAvailableVersions( versions ); 499 } 500 501 Collections.sort( versions ); 502 503 VersionRange versionRange = artifact.getVersionRange(); 504 505 version = versionRange.matchVersion( versions ); 506 507 if ( version == null ) 508 { 509 if ( versions.isEmpty() ) 510 { 511 throw new OverConstrainedVersionException( 512 "No versions are present in the repository for the artifact with a range " 513 + versionRange, 514 artifact, 515 childRemoteRepositories ); 516 } 517 518 throw new OverConstrainedVersionException( "Couldn't find a version in " 519 + versions + " to match range " + versionRange, artifact, 520 childRemoteRepositories ); 521 } 522 } 523 else 524 { 525 version = artifact.getSelectedVersion(); 526 } 527 528 artifact.selectVersion( version.toString() ); 529 fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, child ); 530 } 531 532 rGroup = source.retrieve( metadataRequest ); 533 534 if ( rGroup == null ) 535 { 536 break; 537 } 538 } 539 while( !childKey.equals( child.getKey() ) ); 540 541 if ( parentArtifact != null && parentArtifact.getDependencyFilter() != null 542 && !parentArtifact.getDependencyFilter().include( artifact ) ) 543 { 544 // MNG-3769: the [probably relocated] artifact is excluded. 545 // We could process exclusions on relocated artifact details in the 546 // MavenMetadataSource.createArtifacts(..) step, BUT that would 547 // require resolving the POM from the repository very early on in 548 // the build. 549 continue; 550 } 551 552 // TODO might be better to have source.retrieve() throw a specific exception for this 553 // situation 554 // and catch here rather than have it return null 555 if ( rGroup == null ) 556 { 557 // relocated dependency artifact is declared excluded, no need to add and recurse 558 // further 559 continue; 560 } 561 562 child.addDependencies( rGroup.getArtifacts(), rGroup.getResolutionRepositories(), filter ); 563 564 } 565 catch ( CyclicDependencyException e ) 566 { 567 // would like to throw this, but we have crappy stuff in the repo 568 569 fireEvent( ResolutionListener.OMIT_FOR_CYCLE, listeners, 570 new ResolutionNode( e.getArtifact(), childRemoteRepositories, child ) ); 571 } 572 catch ( ArtifactMetadataRetrievalException e ) 573 { 574 artifact.setDependencyTrail( node.getDependencyTrail() ); 575 576 throw new ArtifactResolutionException( "Unable to get dependency information for " 577 + artifact.getId() + ": " + e.getMessage(), artifact, childRemoteRepositories, e ); 578 } 579 580 ArtifactResolutionRequest subRequest = new ArtifactResolutionRequest( metadataRequest ); 581 subRequest.setServers( request.getServers() ); 582 subRequest.setMirrors( request.getMirrors() ); 583 subRequest.setProxies( request.getProxies() ); 584 recurse( result, child, resolvedArtifacts, managedVersions, subRequest, source, filter, 585 listeners, conflictResolvers ); 586 } 587 } 588 catch ( OverConstrainedVersionException e ) 589 { 590 result.addVersionRangeViolation( e ); 591 } 592 catch ( ArtifactResolutionException e ) 593 { 594 result.addMetadataResolutionException( e ); 595 } 596 } 597 598 fireEvent( ResolutionListener.FINISH_PROCESSING_CHILDREN, listeners, node ); 599 } 600 } 601 602 private void manageArtifact( ResolutionNode node, ManagedVersionMap managedVersions, 603 List<ResolutionListener> listeners ) 604 { 605 Artifact artifact = (Artifact) managedVersions.get( node.getKey() ); 606 607 // Before we update the version of the artifact, we need to know 608 // whether we are working on a transitive dependency or not. This 609 // allows depMgmt to always override transitive dependencies, while 610 // explicit child override depMgmt (viz. depMgmt should only 611 // provide defaults to children, but should override transitives). 612 // We can do this by calling isChildOfRootNode on the current node. 613 614 if ( ( artifact.getVersion() != null ) 615 && ( !node.isChildOfRootNode() || node.getArtifact().getVersion() == null ) ) 616 { 617 fireEvent( ResolutionListener.MANAGE_ARTIFACT_VERSION, listeners, node, artifact ); 618 node.getArtifact().setVersion( artifact.getVersion() ); 619 } 620 621 if ( ( artifact.getScope() != null ) && ( !node.isChildOfRootNode() || node.getArtifact().getScope() == null ) ) 622 { 623 fireEvent( ResolutionListener.MANAGE_ARTIFACT_SCOPE, listeners, node, artifact ); 624 node.getArtifact().setScope( artifact.getScope() ); 625 } 626 627 if ( Artifact.SCOPE_SYSTEM.equals( node.getArtifact().getScope() ) && ( node.getArtifact().getFile() == null ) 628 && ( artifact.getFile() != null ) ) 629 { 630 fireEvent( ResolutionListener.MANAGE_ARTIFACT_SYSTEM_PATH, listeners, node, artifact ); 631 node.getArtifact().setFile( artifact.getFile() ); 632 } 633 } 634 635 /** 636 * Check if the artifactScope needs to be updated. <a 637 * href="http://docs.codehaus.org/x/IGU#DependencyMediationandConflictResolution-Scoperesolution">More info</a>. 638 * 639 * @param farthest farthest resolution node 640 * @param nearest nearest resolution node 641 * @param listeners 642 */ 643 boolean checkScopeUpdate( ResolutionNode farthest, ResolutionNode nearest, List<ResolutionListener> listeners ) 644 { 645 boolean updateScope = false; 646 Artifact farthestArtifact = farthest.getArtifact(); 647 Artifact nearestArtifact = nearest.getArtifact(); 648 649 /* farthest is runtime and nearest has lower priority, change to runtime */ 650 if ( Artifact.SCOPE_RUNTIME.equals( farthestArtifact.getScope() ) 651 && ( Artifact.SCOPE_TEST.equals( nearestArtifact.getScope() ) 652 || Artifact.SCOPE_PROVIDED.equals( nearestArtifact.getScope() ) ) ) 653 { 654 updateScope = true; 655 } 656 657 /* farthest is compile and nearest is not (has lower priority), change to compile */ 658 if ( Artifact.SCOPE_COMPILE.equals( farthestArtifact.getScope() ) 659 && !Artifact.SCOPE_COMPILE.equals( nearestArtifact.getScope() ) ) 660 { 661 updateScope = true; 662 } 663 664 /* current POM rules all, if nearest is in current pom, do not update its artifactScope */ 665 if ( ( nearest.getDepth() < 2 ) && updateScope ) 666 { 667 updateScope = false; 668 669 fireEvent( ResolutionListener.UPDATE_SCOPE_CURRENT_POM, listeners, nearest, farthestArtifact ); 670 } 671 672 if ( updateScope ) 673 { 674 fireEvent( ResolutionListener.UPDATE_SCOPE, listeners, nearest, farthestArtifact ); 675 676 // previously we cloned the artifact, but it is more effecient to just update the artifactScope 677 // if problems are later discovered that the original object needs its original artifactScope value, cloning 678 // may 679 // again be appropriate 680 nearestArtifact.setScope( farthestArtifact.getScope() ); 681 } 682 683 return updateScope; 684 } 685 686 private void fireEvent( int event, List<ResolutionListener> listeners, ResolutionNode node ) 687 { 688 fireEvent( event, listeners, node, null ); 689 } 690 691 private void fireEvent( int event, List<ResolutionListener> listeners, ResolutionNode node, Artifact replacement ) 692 { 693 fireEvent( event, listeners, node, replacement, null ); 694 } 695 696 private void fireEvent( int event, List<ResolutionListener> listeners, ResolutionNode node, Artifact replacement, 697 VersionRange newRange ) 698 { 699 for ( ResolutionListener listener : listeners ) 700 { 701 switch ( event ) 702 { 703 case ResolutionListener.TEST_ARTIFACT: 704 listener.testArtifact( node.getArtifact() ); 705 break; 706 case ResolutionListener.PROCESS_CHILDREN: 707 listener.startProcessChildren( node.getArtifact() ); 708 break; 709 case ResolutionListener.FINISH_PROCESSING_CHILDREN: 710 listener.endProcessChildren( node.getArtifact() ); 711 break; 712 case ResolutionListener.INCLUDE_ARTIFACT: 713 listener.includeArtifact( node.getArtifact() ); 714 break; 715 case ResolutionListener.OMIT_FOR_NEARER: 716 listener.omitForNearer( node.getArtifact(), replacement ); 717 break; 718 case ResolutionListener.OMIT_FOR_CYCLE: 719 listener.omitForCycle( node.getArtifact() ); 720 break; 721 case ResolutionListener.UPDATE_SCOPE: 722 listener.updateScope( node.getArtifact(), replacement.getScope() ); 723 break; 724 case ResolutionListener.UPDATE_SCOPE_CURRENT_POM: 725 listener.updateScopeCurrentPom( node.getArtifact(), replacement.getScope() ); 726 break; 727 case ResolutionListener.MANAGE_ARTIFACT_VERSION: 728 if ( listener instanceof ResolutionListenerForDepMgmt ) 729 { 730 ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener; 731 asImpl.manageArtifactVersion( node.getArtifact(), replacement ); 732 } 733 else 734 { 735 listener.manageArtifact( node.getArtifact(), replacement ); 736 } 737 break; 738 case ResolutionListener.MANAGE_ARTIFACT_SCOPE: 739 if ( listener instanceof ResolutionListenerForDepMgmt ) 740 { 741 ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener; 742 asImpl.manageArtifactScope( node.getArtifact(), replacement ); 743 } 744 else 745 { 746 listener.manageArtifact( node.getArtifact(), replacement ); 747 } 748 break; 749 case ResolutionListener.MANAGE_ARTIFACT_SYSTEM_PATH: 750 if ( listener instanceof ResolutionListenerForDepMgmt ) 751 { 752 ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener; 753 asImpl.manageArtifactSystemPath( node.getArtifact(), replacement ); 754 } 755 else 756 { 757 listener.manageArtifact( node.getArtifact(), replacement ); 758 } 759 break; 760 case ResolutionListener.SELECT_VERSION_FROM_RANGE: 761 listener.selectVersionFromRange( node.getArtifact() ); 762 break; 763 case ResolutionListener.RESTRICT_RANGE: 764 if ( node.getArtifact().getVersionRange().hasRestrictions() 765 || replacement.getVersionRange().hasRestrictions() ) 766 { 767 listener.restrictRange( node.getArtifact(), replacement, newRange ); 768 } 769 break; 770 default: 771 throw new IllegalStateException( "Unknown event: " + event ); 772 } 773 } 774 } 775 776 public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, 777 Map managedVersions, ArtifactRepository localRepository, 778 List<ArtifactRepository> remoteRepositories, 779 ArtifactMetadataSource source, ArtifactFilter filter, 780 List<ResolutionListener> listeners ) 781 { 782 return collect( artifacts, originatingArtifact, managedVersions, localRepository, remoteRepositories, source, 783 filter, listeners, null ); 784 } 785 786 public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, 787 ArtifactRepository localRepository, 788 List<ArtifactRepository> remoteRepositories, 789 ArtifactMetadataSource source, ArtifactFilter filter, 790 List<ResolutionListener> listeners ) 791 { 792 return collect( artifacts, originatingArtifact, null, localRepository, remoteRepositories, source, filter, 793 listeners ); 794 } 795 796 }