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 }