package org.apache.maven.repository.legacy.resolver; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.metadata.ResolutionGroup; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.CyclicDependencyException; import org.apache.maven.artifact.resolver.ResolutionListener; import org.apache.maven.artifact.resolver.ResolutionListenerForDepMgmt; import org.apache.maven.artifact.resolver.ResolutionNode; import org.apache.maven.artifact.resolver.filter.AndArtifactFilter; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.ManagedVersionMap; import org.apache.maven.artifact.versioning.OverConstrainedVersionException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.LegacySupport; import org.apache.maven.repository.legacy.metadata.ArtifactMetadataRetrievalException; import org.apache.maven.repository.legacy.metadata.DefaultMetadataResolutionRequest; import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest; import org.apache.maven.repository.legacy.resolver.conflict.ConflictResolver; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; /** * @author <a href="mailto:brett@apache.org">Brett Porter</a> * @author Jason van Zyl */ @Component( role = LegacyArtifactCollector.class ) public class DefaultLegacyArtifactCollector implements LegacyArtifactCollector { @Requirement(hint="nearest") private ConflictResolver defaultConflictResolver; @Requirement private Logger logger; @Requirement private LegacySupport legacySupport; private void injectSession( ArtifactResolutionRequest request ) { MavenSession session = legacySupport.getSession(); if ( session != null ) { request.setOffline( session.isOffline() ); request.setForceUpdate( session.getRequest().isUpdateSnapshots() ); request.setServers( session.getRequest().getServers() ); request.setMirrors( session.getRequest().getMirrors() ); request.setProxies( session.getRequest().getProxies() ); } } public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, Map managedVersions, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories, ArtifactMetadataSource source, ArtifactFilter filter, List<ResolutionListener> listeners, List<ConflictResolver> conflictResolvers ) { ArtifactResolutionRequest request = new ArtifactResolutionRequest(); request.setLocalRepository( localRepository ); request.setRemoteRepositories( remoteRepositories ); injectSession( request ); return collect( artifacts, originatingArtifact, managedVersions, request, source, filter, listeners, conflictResolvers ); } public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, Map managedVersions, ArtifactResolutionRequest repositoryRequest, ArtifactMetadataSource source, ArtifactFilter filter, List<ResolutionListener> listeners, List<ConflictResolver> conflictResolvers ) { ArtifactResolutionResult result = new ArtifactResolutionResult(); result.setOriginatingArtifact( originatingArtifact ); if ( conflictResolvers == null ) { conflictResolvers = Collections.singletonList( defaultConflictResolver ); } Map<Object, List<ResolutionNode>> resolvedArtifacts = new LinkedHashMap<Object, List<ResolutionNode>>(); ResolutionNode root = new ResolutionNode( originatingArtifact, repositoryRequest.getRemoteRepositories() ); try { root.addDependencies( artifacts, repositoryRequest.getRemoteRepositories(), filter ); } catch ( CyclicDependencyException e ) { result.addCircularDependencyException( e ); return result; } catch ( OverConstrainedVersionException e ) { result.addVersionRangeViolation( e ); return result; } ManagedVersionMap versionMap = getManagedVersionsMap( originatingArtifact, managedVersions ); try { recurse( result, root, resolvedArtifacts, versionMap, repositoryRequest, source, filter, listeners, conflictResolvers ); } catch ( CyclicDependencyException e ) { logger.debug( "While recursing: " + e.getMessage(), e ); result.addCircularDependencyException( e ); } catch ( OverConstrainedVersionException e ) { logger.debug( "While recursing: " + e.getMessage(), e ); result.addVersionRangeViolation( e ); } catch ( ArtifactResolutionException e ) { logger.debug( "While recursing: " + e.getMessage(), e ); result.addErrorArtifactException( e ); } Set<ResolutionNode> set = new LinkedHashSet<ResolutionNode>(); for ( List<ResolutionNode> nodes : resolvedArtifacts.values() ) { for ( ResolutionNode node : nodes ) { if ( !node.equals( root ) && node.isActive() ) { Artifact artifact = node.getArtifact(); try { if ( node.filterTrail( filter ) ) { // If it was optional and not a direct dependency, // we don't add it or its children, just allow the update of the version and artifactScope if ( node.isChildOfRootNode() || !artifact.isOptional() ) { artifact.setDependencyTrail( node.getDependencyTrail() ); set.add( node ); // This is required right now. result.addArtifact( artifact ); } } } catch ( OverConstrainedVersionException e ) { result.addVersionRangeViolation( e ); } } } } result.setArtifactResolutionNodes( set ); return result; } /** * Get the map of managed versions, removing the originating artifact if it is also in managed versions * * @param originatingArtifact artifact we are processing * @param managedVersions original managed versions */ private ManagedVersionMap getManagedVersionsMap( Artifact originatingArtifact, Map managedVersions ) { ManagedVersionMap versionMap; if ( ( managedVersions != null ) && ( managedVersions instanceof ManagedVersionMap ) ) { versionMap = (ManagedVersionMap) managedVersions; } else { versionMap = new ManagedVersionMap( managedVersions ); } /* remove the originating artifact if it is also in managed versions to avoid being modified during resolution */ Artifact managedOriginatingArtifact = (Artifact) versionMap.get( originatingArtifact.getDependencyConflictId() ); if ( managedOriginatingArtifact != null ) { // TODO we probably want to warn the user that he is building an artifact with // different values than in dependencyManagement if ( managedVersions instanceof ManagedVersionMap ) { /* avoid modifying the managedVersions parameter creating a new map */ versionMap = new ManagedVersionMap( managedVersions ); } versionMap.remove( originatingArtifact.getDependencyConflictId() ); } return versionMap; } private void recurse( ArtifactResolutionResult result, ResolutionNode node, Map<Object, List<ResolutionNode>> resolvedArtifacts, ManagedVersionMap managedVersions, ArtifactResolutionRequest request, ArtifactMetadataSource source, ArtifactFilter filter, List<ResolutionListener> listeners, List<ConflictResolver> conflictResolvers ) throws ArtifactResolutionException { fireEvent( ResolutionListener.TEST_ARTIFACT, listeners, node ); Object key = node.getKey(); // TODO: Does this check need to happen here? Had to add the same call // below when we iterate on child nodes -- will that suffice? if ( managedVersions.containsKey( key ) ) { manageArtifact( node, managedVersions, listeners ); } List<ResolutionNode> previousNodes = resolvedArtifacts.get( key ); if ( previousNodes != null ) { for ( ResolutionNode previous : previousNodes ) { try { if ( previous.isActive() ) { // Version mediation VersionRange previousRange = previous.getArtifact().getVersionRange(); VersionRange currentRange = node.getArtifact().getVersionRange(); if ( ( previousRange != null ) && ( currentRange != null ) ) { // TODO: shouldn't need to double up on this work, only done for simplicity of handling // recommended // version but the restriction is identical VersionRange newRange = previousRange.restrict( currentRange ); // TODO: ick. this forces the OCE that should have come from the previous call. It is still // correct if ( newRange.isSelectedVersionKnown( previous.getArtifact() ) ) { fireEvent( ResolutionListener.RESTRICT_RANGE, listeners, node, previous.getArtifact(), newRange ); } previous.getArtifact().setVersionRange( newRange ); node.getArtifact().setVersionRange( currentRange.restrict( previousRange ) ); // Select an appropriate available version from the (now restricted) range // Note this version was selected before to get the appropriate POM // But it was reset by the call to setVersionRange on restricting the version ResolutionNode[] resetNodes = { previous, node }; for ( int j = 0; j < 2; j++ ) { Artifact resetArtifact = resetNodes[j].getArtifact(); // MNG-2123: if the previous node was not a range, then it wouldn't have any available // versions. We just clobbered the selected version above. (why? i have no idea.) // So since we are here and this is ranges we must go figure out the version (for a // third time...) if ( resetArtifact.getVersion() == null && resetArtifact.getVersionRange() != null ) { // go find the version. This is a total hack. See previous comment. List<ArtifactVersion> versions = resetArtifact.getAvailableVersions(); if ( versions == null ) { try { MetadataResolutionRequest metadataRequest = new DefaultMetadataResolutionRequest( request ); metadataRequest.setArtifact( resetArtifact ); versions = source.retrieveAvailableVersions( metadataRequest ); resetArtifact.setAvailableVersions( versions ); } catch ( ArtifactMetadataRetrievalException e ) { resetArtifact.setDependencyTrail( node.getDependencyTrail() ); throw new ArtifactResolutionException( "Unable to get dependency information: " + e.getMessage(), resetArtifact, request.getRemoteRepositories(), e ); } } // end hack // MNG-2861: match version can return null ArtifactVersion selectedVersion = resetArtifact.getVersionRange().matchVersion( resetArtifact.getAvailableVersions() ); if ( selectedVersion != null ) { resetArtifact.selectVersion( selectedVersion.toString() ); } else { throw new OverConstrainedVersionException( " Unable to find a version in " + resetArtifact.getAvailableVersions() + " to match the range " + resetArtifact.getVersionRange(), resetArtifact ); } fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, resetNodes[j] ); } } } // Conflict Resolution ResolutionNode resolved = null; for ( Iterator j = conflictResolvers.iterator(); ( resolved == null ) && j.hasNext(); ) { ConflictResolver conflictResolver = (ConflictResolver) j.next(); resolved = conflictResolver.resolveConflict( previous, node ); } if ( resolved == null ) { // TODO: add better exception that can detail the two conflicting artifacts ArtifactResolutionException are = new ArtifactResolutionException( "Cannot resolve artifact version conflict between " + previous.getArtifact().getVersion() + " and " + node.getArtifact().getVersion(), previous.getArtifact() ); result.addVersionRangeViolation( are ); } if ( ( resolved != previous ) && ( resolved != node ) ) { // TODO: add better exception result.addVersionRangeViolation( new ArtifactResolutionException( "Conflict resolver returned unknown resolution node: ", resolved.getArtifact() ) ); } // TODO: should this be part of mediation? // previous one is more dominant ResolutionNode nearest; ResolutionNode farthest; if ( resolved == previous ) { nearest = previous; farthest = node; } else { nearest = node; farthest = previous; } if ( checkScopeUpdate( farthest, nearest, listeners ) ) { // if we need to update artifactScope of nearest to use farthest artifactScope, use the // nearest version, but farthest artifactScope nearest.disable(); farthest.getArtifact().setVersion( nearest.getArtifact().getVersion() ); fireEvent( ResolutionListener.OMIT_FOR_NEARER, listeners, nearest, farthest.getArtifact() ); } else { farthest.disable(); fireEvent( ResolutionListener.OMIT_FOR_NEARER, listeners, farthest, nearest.getArtifact() ); } } } catch ( OverConstrainedVersionException e ) { result.addVersionRangeViolation( e ); } } } else { previousNodes = new ArrayList<ResolutionNode>(); resolvedArtifacts.put( key, previousNodes ); } previousNodes.add( node ); if ( node.isActive() ) { fireEvent( ResolutionListener.INCLUDE_ARTIFACT, listeners, node ); } // don't pull in the transitive deps of a system-scoped dependency. if ( node.isActive() && !Artifact.SCOPE_SYSTEM.equals( node.getArtifact().getScope() ) ) { fireEvent( ResolutionListener.PROCESS_CHILDREN, listeners, node ); Artifact parentArtifact = node.getArtifact(); for ( Iterator i = node.getChildrenIterator(); i.hasNext(); ) { ResolutionNode child = (ResolutionNode) i.next(); try { // We leave in optional ones, but don't pick up its dependencies if ( !child.isResolved() && ( !child.getArtifact().isOptional() || child.isChildOfRootNode() ) ) { Artifact artifact = child.getArtifact(); artifact.setDependencyTrail( node.getDependencyTrail() ); List<ArtifactRepository> childRemoteRepositories = child.getRemoteRepositories(); MetadataResolutionRequest metadataRequest = new DefaultMetadataResolutionRequest( request ); metadataRequest.setArtifact( artifact ); metadataRequest.setRemoteRepositories( childRemoteRepositories ); try { ResolutionGroup rGroup; Object childKey; do { childKey = child.getKey(); if ( managedVersions.containsKey( childKey ) ) { // If this child node is a managed dependency, ensure // we are using the dependency management version // of this child if applicable b/c we want to use the // managed version's POM, *not* any other version's POM. // We retrieve the POM below in the retrieval step. manageArtifact( child, managedVersions, listeners ); // Also, we need to ensure that any exclusions it presents are // added to the artifact before we retrive the metadata // for the artifact; otherwise we may end up with unwanted // dependencies. Artifact ma = (Artifact) managedVersions.get( childKey ); ArtifactFilter managedExclusionFilter = ma.getDependencyFilter(); if ( null != managedExclusionFilter ) { if ( null != artifact.getDependencyFilter() ) { AndArtifactFilter aaf = new AndArtifactFilter(); aaf.add( artifact.getDependencyFilter() ); aaf.add( managedExclusionFilter ); artifact.setDependencyFilter( aaf ); } else { artifact.setDependencyFilter( managedExclusionFilter ); } } } if ( artifact.getVersion() == null ) { // set the recommended version // TODO: maybe its better to just pass the range through to retrieval and use a // transformation? ArtifactVersion version; if ( !artifact.isSelectedVersionKnown() ) { List<ArtifactVersion> versions = artifact.getAvailableVersions(); if ( versions == null ) { versions = source.retrieveAvailableVersions( metadataRequest ); artifact.setAvailableVersions( versions ); } Collections.sort( versions ); VersionRange versionRange = artifact.getVersionRange(); version = versionRange.matchVersion( versions ); if ( version == null ) { if ( versions.isEmpty() ) { throw new OverConstrainedVersionException( "No versions are present in the repository for the artifact with a range " + versionRange, artifact, childRemoteRepositories ); } throw new OverConstrainedVersionException( "Couldn't find a version in " + versions + " to match range " + versionRange, artifact, childRemoteRepositories ); } } else { version = artifact.getSelectedVersion(); } artifact.selectVersion( version.toString() ); fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, child ); } rGroup = source.retrieve( metadataRequest ); if ( rGroup == null ) { break; } } while( !childKey.equals( child.getKey() ) ); if ( parentArtifact != null && parentArtifact.getDependencyFilter() != null && !parentArtifact.getDependencyFilter().include( artifact ) ) { // MNG-3769: the [probably relocated] artifact is excluded. // We could process exclusions on relocated artifact details in the // MavenMetadataSource.createArtifacts(..) step, BUT that would // require resolving the POM from the repository very early on in // the build. continue; } // TODO might be better to have source.retrieve() throw a specific exception for this // situation // and catch here rather than have it return null if ( rGroup == null ) { // relocated dependency artifact is declared excluded, no need to add and recurse // further continue; } child.addDependencies( rGroup.getArtifacts(), rGroup.getResolutionRepositories(), filter ); } catch ( CyclicDependencyException e ) { // would like to throw this, but we have crappy stuff in the repo fireEvent( ResolutionListener.OMIT_FOR_CYCLE, listeners, new ResolutionNode( e.getArtifact(), childRemoteRepositories, child ) ); } catch ( ArtifactMetadataRetrievalException e ) { artifact.setDependencyTrail( node.getDependencyTrail() ); throw new ArtifactResolutionException( "Unable to get dependency information for " + artifact.getId() + ": " + e.getMessage(), artifact, childRemoteRepositories, e ); } ArtifactResolutionRequest subRequest = new ArtifactResolutionRequest( metadataRequest ); subRequest.setServers( request.getServers() ); subRequest.setMirrors( request.getMirrors() ); subRequest.setProxies( request.getProxies() ); recurse( result, child, resolvedArtifacts, managedVersions, subRequest, source, filter, listeners, conflictResolvers ); } } catch ( OverConstrainedVersionException e ) { result.addVersionRangeViolation( e ); } catch ( ArtifactResolutionException e ) { result.addMetadataResolutionException( e ); } } fireEvent( ResolutionListener.FINISH_PROCESSING_CHILDREN, listeners, node ); } } private void manageArtifact( ResolutionNode node, ManagedVersionMap managedVersions, List<ResolutionListener> listeners ) { Artifact artifact = (Artifact) managedVersions.get( node.getKey() ); // Before we update the version of the artifact, we need to know // whether we are working on a transitive dependency or not. This // allows depMgmt to always override transitive dependencies, while // explicit child override depMgmt (viz. depMgmt should only // provide defaults to children, but should override transitives). // We can do this by calling isChildOfRootNode on the current node. if ( ( artifact.getVersion() != null ) && ( !node.isChildOfRootNode() || node.getArtifact().getVersion() == null ) ) { fireEvent( ResolutionListener.MANAGE_ARTIFACT_VERSION, listeners, node, artifact ); node.getArtifact().setVersion( artifact.getVersion() ); } if ( ( artifact.getScope() != null ) && ( !node.isChildOfRootNode() || node.getArtifact().getScope() == null ) ) { fireEvent( ResolutionListener.MANAGE_ARTIFACT_SCOPE, listeners, node, artifact ); node.getArtifact().setScope( artifact.getScope() ); } if ( Artifact.SCOPE_SYSTEM.equals( node.getArtifact().getScope() ) && ( node.getArtifact().getFile() == null ) && ( artifact.getFile() != null ) ) { fireEvent( ResolutionListener.MANAGE_ARTIFACT_SYSTEM_PATH, listeners, node, artifact ); node.getArtifact().setFile( artifact.getFile() ); } } /** * Check if the artifactScope needs to be updated. <a * href="http://docs.codehaus.org/x/IGU#DependencyMediationandConflictResolution-Scoperesolution">More info</a>. * * @param farthest farthest resolution node * @param nearest nearest resolution node * @param listeners */ boolean checkScopeUpdate( ResolutionNode farthest, ResolutionNode nearest, List<ResolutionListener> listeners ) { boolean updateScope = false; Artifact farthestArtifact = farthest.getArtifact(); Artifact nearestArtifact = nearest.getArtifact(); /* farthest is runtime and nearest has lower priority, change to runtime */ if ( Artifact.SCOPE_RUNTIME.equals( farthestArtifact.getScope() ) && ( Artifact.SCOPE_TEST.equals( nearestArtifact.getScope() ) || Artifact.SCOPE_PROVIDED.equals( nearestArtifact.getScope() ) ) ) { updateScope = true; } /* farthest is compile and nearest is not (has lower priority), change to compile */ if ( Artifact.SCOPE_COMPILE.equals( farthestArtifact.getScope() ) && !Artifact.SCOPE_COMPILE.equals( nearestArtifact.getScope() ) ) { updateScope = true; } /* current POM rules all, if nearest is in current pom, do not update its artifactScope */ if ( ( nearest.getDepth() < 2 ) && updateScope ) { updateScope = false; fireEvent( ResolutionListener.UPDATE_SCOPE_CURRENT_POM, listeners, nearest, farthestArtifact ); } if ( updateScope ) { fireEvent( ResolutionListener.UPDATE_SCOPE, listeners, nearest, farthestArtifact ); // previously we cloned the artifact, but it is more effecient to just update the artifactScope // if problems are later discovered that the original object needs its original artifactScope value, cloning // may // again be appropriate nearestArtifact.setScope( farthestArtifact.getScope() ); } return updateScope; } private void fireEvent( int event, List<ResolutionListener> listeners, ResolutionNode node ) { fireEvent( event, listeners, node, null ); } private void fireEvent( int event, List<ResolutionListener> listeners, ResolutionNode node, Artifact replacement ) { fireEvent( event, listeners, node, replacement, null ); } private void fireEvent( int event, List<ResolutionListener> listeners, ResolutionNode node, Artifact replacement, VersionRange newRange ) { for ( ResolutionListener listener : listeners ) { switch ( event ) { case ResolutionListener.TEST_ARTIFACT: listener.testArtifact( node.getArtifact() ); break; case ResolutionListener.PROCESS_CHILDREN: listener.startProcessChildren( node.getArtifact() ); break; case ResolutionListener.FINISH_PROCESSING_CHILDREN: listener.endProcessChildren( node.getArtifact() ); break; case ResolutionListener.INCLUDE_ARTIFACT: listener.includeArtifact( node.getArtifact() ); break; case ResolutionListener.OMIT_FOR_NEARER: listener.omitForNearer( node.getArtifact(), replacement ); break; case ResolutionListener.OMIT_FOR_CYCLE: listener.omitForCycle( node.getArtifact() ); break; case ResolutionListener.UPDATE_SCOPE: listener.updateScope( node.getArtifact(), replacement.getScope() ); break; case ResolutionListener.UPDATE_SCOPE_CURRENT_POM: listener.updateScopeCurrentPom( node.getArtifact(), replacement.getScope() ); break; case ResolutionListener.MANAGE_ARTIFACT_VERSION: if ( listener instanceof ResolutionListenerForDepMgmt ) { ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener; asImpl.manageArtifactVersion( node.getArtifact(), replacement ); } else { listener.manageArtifact( node.getArtifact(), replacement ); } break; case ResolutionListener.MANAGE_ARTIFACT_SCOPE: if ( listener instanceof ResolutionListenerForDepMgmt ) { ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener; asImpl.manageArtifactScope( node.getArtifact(), replacement ); } else { listener.manageArtifact( node.getArtifact(), replacement ); } break; case ResolutionListener.MANAGE_ARTIFACT_SYSTEM_PATH: if ( listener instanceof ResolutionListenerForDepMgmt ) { ResolutionListenerForDepMgmt asImpl = (ResolutionListenerForDepMgmt) listener; asImpl.manageArtifactSystemPath( node.getArtifact(), replacement ); } else { listener.manageArtifact( node.getArtifact(), replacement ); } break; case ResolutionListener.SELECT_VERSION_FROM_RANGE: listener.selectVersionFromRange( node.getArtifact() ); break; case ResolutionListener.RESTRICT_RANGE: if ( node.getArtifact().getVersionRange().hasRestrictions() || replacement.getVersionRange().hasRestrictions() ) { listener.restrictRange( node.getArtifact(), replacement, newRange ); } break; default: throw new IllegalStateException( "Unknown event: " + event ); } } } public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, Map managedVersions, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories, ArtifactMetadataSource source, ArtifactFilter filter, List<ResolutionListener> listeners ) { return collect( artifacts, originatingArtifact, managedVersions, localRepository, remoteRepositories, source, filter, listeners, null ); } public ArtifactResolutionResult collect( Set<Artifact> artifacts, Artifact originatingArtifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories, ArtifactMetadataSource source, ArtifactFilter filter, List<ResolutionListener> listeners ) { return collect( artifacts, originatingArtifact, null, localRepository, remoteRepositories, source, filter, listeners ); } }