This is an automated email from the ASF dual-hosted git repository. tibordigana pushed a commit to branch pre-MRESOLVER-92 in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/pre-MRESOLVER-92 by this push: new 3096fc9 solved DefaultDependencyCollector 3096fc9 is described below commit 3096fc9095a8c684417fd6b6fe4c5e6c23faba5c Author: tibordigana <tibordig...@apache.org> AuthorDate: Sun Aug 11 15:21:47 2019 +0200 solved DefaultDependencyCollector --- .../impl/collect/DefaultDependencyCollector.java | 880 +++++++++++++-------- 1 file changed, 547 insertions(+), 333 deletions(-) diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java index 9d37435..34bcb39 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java @@ -19,31 +19,20 @@ package org.eclipse.aether.internal.impl.collect; * under the License. */ -import static org.eclipse.aether.internal.impl.collect.DependencyCollectionUtils.addDependencyNode; -import static org.eclipse.aether.internal.impl.collect.DependencyCollectionUtils.createArtifactDescriptorRequest; -import static org.eclipse.aether.internal.impl.collect.DependencyCollectionUtils.createDependencyNode; -import static org.eclipse.aether.internal.impl.collect.DependencyCollectionUtils.createVersionRangeRequest; -import static org.eclipse.aether.internal.impl.collect.DependencyCollectionUtils.filterVersions; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import static java.util.Objects.requireNonNull; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; +import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositoryException; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.RequestTrace; @@ -53,10 +42,15 @@ import org.eclipse.aether.collection.CollectRequest; import org.eclipse.aether.collection.CollectResult; import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.collection.DependencyGraphTransformer; +import org.eclipse.aether.collection.DependencyManagement; +import org.eclipse.aether.collection.DependencyManager; +import org.eclipse.aether.collection.DependencySelector; import org.eclipse.aether.collection.DependencyTraverser; +import org.eclipse.aether.collection.VersionFilter; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.Exclusion; import org.eclipse.aether.impl.ArtifactDescriptorReader; import org.eclipse.aether.impl.DependencyCollector; import org.eclipse.aether.impl.RemoteRepositoryManager; @@ -72,8 +66,7 @@ import org.eclipse.aether.resolution.VersionRangeResult; import org.eclipse.aether.spi.locator.Service; import org.eclipse.aether.spi.locator.ServiceLocator; import org.eclipse.aether.util.ConfigUtils; -import org.eclipse.aether.util.concurrency.FutureResult; -import org.eclipse.aether.util.concurrency.WorkerThreadFactory; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; import org.eclipse.aether.util.graph.transformer.TransformationContextKeys; import org.eclipse.aether.version.Version; import org.slf4j.Logger; @@ -86,12 +79,13 @@ public class DefaultDependencyCollector implements DependencyCollector, Service { - static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions"; + private static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions"; + + private static final int CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT = 50; - static final String CONFIG_PROP_MAX_CYCLES = "aether.dependencyCollector.maxCycles"; + private static final String CONFIG_PROP_MAX_CYCLES = "aether.dependencyCollector.maxCycles"; - private static final String CONFIG_PROP_THREADS = "aether.artifactDescriptor.threads"; - private static final int DEFAULT_THREADS = 5; + private static final int CONFIG_PROP_MAX_CYCLES_DEFAULT = 10; private static final Logger LOGGER = LoggerFactory.getLogger( DefaultDependencyCollector.class ); @@ -125,8 +119,8 @@ public class DefaultDependencyCollector public DefaultDependencyCollector setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager ) { - this.remoteRepositoryManager = requireNonNull( - remoteRepositoryManager, "remote repository provider cannot be null" ); + this.remoteRepositoryManager = + requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" ); return this; } @@ -138,60 +132,80 @@ public class DefaultDependencyCollector public DefaultDependencyCollector setVersionRangeResolver( VersionRangeResolver versionRangeResolver ) { - this.versionRangeResolver = requireNonNull( versionRangeResolver, "version range resolver cannot be null" ); + this.versionRangeResolver = + requireNonNull( versionRangeResolver, "version range resolver cannot be null" ); return this; } + @SuppressWarnings( "checkstyle:methodlength" ) public CollectResult collectDependencies( RepositorySystemSession session, CollectRequest request ) throws DependencyCollectionException { - int numThreads = ConfigUtils.getInteger( session, DEFAULT_THREADS, CONFIG_PROP_THREADS ); - LOGGER.debug( "{} = {} ", CONFIG_PROP_THREADS, numThreads ); - ThreadPoolExecutor executor = new ThreadPoolExecutor( - numThreads, numThreads, 3L, TimeUnit.SECONDS, - new LinkedBlockingQueue<Runnable>(), new WorkerThreadFactory( "artifact-descriptor-resolver" ) ); - try - { - return collectDependenciesWithExecutor( session, request, executor ); - } - finally - { - executor.shutdown(); - } - } - - private CollectResult collectDependenciesWithExecutor( RepositorySystemSession session, CollectRequest request, - ExecutorService executor ) - throws DependencyCollectionException - { - session = DependencyCollectionUtils.optimizeSession( session ); + session = optimizeSession( session ); RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); CollectResult result = new CollectResult( request ); + DependencySelector depSelector = session.getDependencySelector(); + DependencyManager depManager = session.getDependencyManager(); + DependencyTraverser depTraverser = session.getDependencyTraverser(); + VersionFilter verFilter = session.getVersionFilter(); + Dependency root = request.getRoot(); List<RemoteRepository> repositories = request.getRepositories(); + List<Dependency> dependencies = request.getDependencies(); List<Dependency> managedDependencies = request.getManagedDependencies(); - DefaultDependencyCollectionContext context = - new DefaultDependencyCollectionContext( session, request.getRootArtifact(), root, managedDependencies ); - context.setDependencies( request.getDependencies() ); - context.setCollectResult( result ); - context.setTrace( trace ); - - Args args = new Args( session, trace, null, null, context, null, request, executor ); - context.setArgs( args ); - Map<String, Object> stats = LOGGER.isDebugEnabled() ? new LinkedHashMap<String, Object>() : null; long time1 = System.nanoTime(); DefaultDependencyNode node; if ( root != null ) { + List<? extends Version> versions; + VersionRangeResult rangeResult; + try + { + VersionRangeRequest rangeRequest = + new VersionRangeRequest( root.getArtifact(), request.getRepositories(), + request.getRequestContext() ); + rangeRequest.setTrace( trace ); + rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest ); + versions = filterVersions( root, rangeResult, verFilter, new DefaultVersionFilterContext( session ) ); + } + catch ( VersionRangeResolutionException e ) + { + result.addException( e ); + throw new DependencyCollectionException( result, e.getMessage() ); + } + + Version version = versions.get( versions.size() - 1 ); + root = root.setArtifact( root.getArtifact().setVersion( version.toString() ) ); + + ArtifactDescriptorResult descriptorResult; + try + { + ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(); + descriptorRequest.setArtifact( root.getArtifact() ); + descriptorRequest.setRepositories( request.getRepositories() ); + descriptorRequest.setRequestContext( request.getRequestContext() ); + descriptorRequest.setTrace( trace ); + if ( isLackingDescriptor( root.getArtifact() ) ) + { + descriptorResult = new ArtifactDescriptorResult( descriptorRequest ); + } + else + { + descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); + } + } + catch ( ArtifactDescriptorException e ) + { + result.addException( e ); + throw new DependencyCollectionException( result, e.getMessage() ); + } - VersionRangeResult rangeResult = resolveRootVersionRange( context ); - ArtifactDescriptorResult descriptorResult = readRootArtifactDescriptor( context ); root = root.setArtifact( descriptorResult.getArtifact() ); if ( !session.isIgnoreArtifactDescriptorRepositories() ) @@ -200,15 +214,14 @@ public class DefaultDependencyCollector descriptorResult.getRepositories(), true ); } - context.setDependencies( mergeDeps( context.getDependencies(), descriptorResult.getDependencies() ) ); - context.setManagedDependencies( mergeDeps( managedDependencies, - descriptorResult.getManagedDependencies() ) ); + dependencies = mergeDeps( dependencies, descriptorResult.getDependencies() ); + managedDependencies = mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() ); node = new DefaultDependencyNode( root ); node.setRequestContext( request.getRequestContext() ); node.setRelocations( descriptorResult.getRelocations() ); node.setVersionConstraint( rangeResult.getVersionConstraint() ); - node.setVersion( context.getVersion() ); + node.setVersion( version ); node.setAliases( descriptorResult.getAliases() ); node.setRepositories( request.getRepositories() ); } @@ -221,41 +234,56 @@ public class DefaultDependencyCollector result.setRoot( node ); - DependencyTraverser depTraverser = session.getDependencyTraverser(); boolean traverse = root == null || depTraverser == null || depTraverser.traverseDependency( root ); String errorPath = null; - if ( traverse && !context.getDependencies().isEmpty() ) + if ( traverse && !dependencies.isEmpty() ) { DataPool pool = new DataPool( session ); NodeStack nodes = new NodeStack(); nodes.push( node ); + DefaultDependencyCollectionContext context = + new DefaultDependencyCollectionContext( session, request.getRootArtifact(), root, managedDependencies ); + DefaultVersionFilterContext versionContext = new DefaultVersionFilterContext( session ); - args = new Args( session, trace, pool, nodes, context, versionContext, request, executor ); + Args args = new Args( session, trace, pool, nodes, context, versionContext, request ); Results results = new Results( result, session ); - context.setArgs( args ); - context.setResults( results ); - context.setRepositories( repositories ); - context.setDepTraverser( depTraverser ); - context.prepareDescent(); - process( context ); + process( args, results, dependencies, repositories, + depSelector != null ? depSelector.deriveChildSelector( context ) : null, + depManager != null ? depManager.deriveChildManager( context ) : null, + depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null, + verFilter != null ? verFilter.deriveChildFilter( context ) : null ); errorPath = results.errorPath; } long time2 = System.nanoTime(); - transformDependencyGraph( context, stats ); + DependencyGraphTransformer transformer = session.getDependencyGraphTransformer(); + if ( transformer != null ) + { + try + { + DefaultDependencyGraphTransformationContext context = + new DefaultDependencyGraphTransformationContext( session ); + context.put( TransformationContextKeys.STATS, stats ); + result.setRoot( transformer.transformGraph( node, context ) ); + } + catch ( RepositoryException e ) + { + result.addException( e ); + } + } if ( stats != null ) { long time3 = System.nanoTime(); stats.put( "DefaultDependencyCollector.collectTime", time2 - time1 ); stats.put( "DefaultDependencyCollector.transformTime", time3 - time2 ); - LOGGER.debug( "Dependency collection stats: {}", stats ); + LOGGER.debug( "Dependency collection stats: " + stats ); } if ( errorPath != null ) @@ -270,80 +298,11 @@ public class DefaultDependencyCollector return result; } - private VersionRangeResult resolveRootVersionRange( DefaultDependencyCollectionContext context ) - throws DependencyCollectionException - { - CollectRequest request = context.getArgs().request; - RepositorySystemSession session = context.getSession(); - List<? extends Version> versions; - VersionRangeResult rangeResult; - Artifact artifact = request.getRoot().getArtifact(); - try - { - VersionRangeRequest rangeRequest = - new VersionRangeRequest( artifact, request.getRepositories(), request.getRequestContext() ); - rangeRequest.setTrace( context.getTrace() ); - rangeResult = versionRangeResolver.resolveVersionRange( session, rangeRequest ); - versions = filterVersions( context.getDependency(), rangeResult, context.getVerFilter(), - new DefaultVersionFilterContext( session ) ); - } - catch ( VersionRangeResolutionException e ) - { - context.getCollectResult().addException( e ); - throw new DependencyCollectionException( context.getCollectResult(), e.getMessage() ); - } - - Version version = versions.get( versions.size() - 1 ); - context.setVersion( version ); - context.setDependency( request.getRoot().setArtifact( artifact.setVersion( version.toString() ) ) ); - return rangeResult; - } - - private ArtifactDescriptorResult readRootArtifactDescriptor( DefaultDependencyCollectionContext context ) - throws DependencyCollectionException - { - CollectRequest request = context.getArgs().request; - Artifact artifact = request.getRoot().getArtifact(); - try - { - ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(); - descriptorRequest.setArtifact( artifact ); - descriptorRequest.setRepositories( request.getRepositories() ); - descriptorRequest.setRequestContext( request.getRequestContext() ); - descriptorRequest.setTrace( context.getTrace() ); - - ArtifactDescriptorResult descriptorResult = - isLackingDescriptor( artifact ) ? new ArtifactDescriptorResult( descriptorRequest ) - : descriptorReader.readArtifactDescriptor( context.getSession(), descriptorRequest ); - context.setDependency( request.getRoot().setArtifact( descriptorResult.getArtifact() ) ); - return descriptorResult; - } - catch ( ArtifactDescriptorException e ) - { - context.getCollectResult().addException( e ); - throw new DependencyCollectionException( context.getCollectResult(), e.getMessage() ); - } - } - - private void transformDependencyGraph( DefaultDependencyCollectionContext context, Map<String, Object> stats ) + private static RepositorySystemSession optimizeSession( RepositorySystemSession session ) { - RepositorySystemSession session = context.getSession(); - DependencyGraphTransformer transformer = session.getDependencyGraphTransformer(); - if ( transformer != null ) - { - try - { - DefaultDependencyGraphTransformationContext tfContext = - new DefaultDependencyGraphTransformationContext( session ); - tfContext.put( TransformationContextKeys.STATS, stats ); - context.getCollectResult().setRoot( transformer.transformGraph( context.getCollectResult().getRoot(), - tfContext ) ); - } - catch ( RepositoryException e ) - { - context.getCollectResult().addException( e ); - } - } + DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session ); + optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) ); + return optimized; } private List<Dependency> mergeDeps( List<Dependency> dominant, List<Dependency> recessive ) @@ -361,7 +320,7 @@ public class DefaultDependencyCollector { int initialCapacity = dominant.size() + recessive.size(); result = new ArrayList<>( initialCapacity ); - Collection<String> ids = new HashSet<>( initialCapacity, 1.0f ); + Collection<String> ids = new HashSet<String>( initialCapacity, 1.0f ); for ( Dependency dependency : dominant ) { ids.add( getId( dependency.getArtifact() ) ); @@ -383,211 +342,162 @@ public class DefaultDependencyCollector return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension(); } - private void process( DefaultDependencyCollectionContext context ) + @SuppressWarnings( "checkstyle:parameternumber" ) + private void process( final Args args, Results results, List<Dependency> dependencies, + List<RemoteRepository> repositories, DependencySelector depSelector, + DependencyManager depManager, DependencyTraverser depTraverser, VersionFilter verFilter ) { - List<DependencyContext> depContexts = new ArrayList<>(); - for ( Dependency d : context.getDependencies() ) + for ( Dependency dependency : dependencies ) { - depContexts.add( new DependencyContext( context, d ) ); - } - - List<Future<DependencyContext>> futures = new ArrayList<>(); - for ( DependencyContext dc : depContexts ) - { - futures.add( asyncProcessDependency( dc ) ); - } - int pos = 0; - for ( Future<DependencyContext> future : futures ) - { - try - { - processDependencyNode( future.get() ); - } - catch ( ExecutionException e ) - { - context.getResults().addException( context.getDependencies().get( pos ), (Exception) e.getCause(), - context.getArgs().nodes ); - } - catch ( InterruptedException e ) - { - context.getResults().addException( context.getDependencies().get( pos ), e, context.getArgs().nodes ); - } - pos++; + processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, + dependency ); } } - private Future<DependencyContext> asyncProcessDependency( final DependencyContext dc ) + @SuppressWarnings( "checkstyle:parameternumber" ) + private void processDependency( Args args, Results results, List<RemoteRepository> repositories, + DependencySelector depSelector, DependencyManager depManager, + DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency ) { - return dc.args.executor.submit( new Callable<DependencyContext>() - { - public DependencyContext call() - { - return processDependency( dc ); - } - } ); + + List<Artifact> relocations = Collections.emptyList(); + boolean disableVersionManagement = false; + processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency, + relocations, disableVersionManagement ); } - private DependencyContext processDependency( DependencyContext dc ) + @SuppressWarnings( "checkstyle:parameternumber" ) + private void processDependency( Args args, Results results, List<RemoteRepository> repositories, + DependencySelector depSelector, DependencyManager depManager, + DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency, + List<Artifact> relocations, boolean disableVersionManagement ) { - DefaultDependencyCollectionContext context = dc.context; - Args args = context.getArgs(); - Results results = context.getResults(); - if ( context.getDepSelector() != null && !context.getDepSelector().selectDependency( dc.origDependency ) ) + if ( depSelector != null && !depSelector.selectDependency( dependency ) ) { - return null; + return; } PremanagedDependency preManaged = - PremanagedDependency.create( context.getDepManager(), dc.origDependency, dc.disableVersionManagement, - args.premanagedState ); - Dependency dependency = preManaged.managedDependency; + PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState ); + dependency = preManaged.managedDependency; boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() ); - boolean traverse = !noDescriptor - && ( context.getDepTraverser() == null || context.getDepTraverser().traverseDependency( dependency ) ); + boolean traverse = !noDescriptor && ( depTraverser == null || depTraverser.traverseDependency( dependency ) ); + List<? extends Version> versions; + VersionRangeResult rangeResult; try { - VersionRangeRequest rangeRequest = createVersionRangeRequest( args, context.getRepositories(), dependency ); - VersionRangeResult rangeResult = cachedResolveRangeResult( rangeRequest, args.pool, args.session ); - for ( Version version : filterVersions( dependency, rangeResult, context.getVerFilter(), - args.versionContext ) ) - { + VersionRangeRequest rangeRequest = createVersionRangeRequest( args, repositories, dependency ); - Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() ); - Dependency d = dependency.setArtifact( originalArtifact ); - - ArtifactDescriptorRequest descriptorRequest = - createArtifactDescriptorRequest( args, context.getRepositories(), d ); - - dc.args = args; - dc.preManaged = preManaged; - dc.traverse = traverse; - dc.rangeResult = rangeResult; - dc.version = version; - dc.originalArtifact = originalArtifact; - dc.managedDependency = d; - dc.futureDescriptorResult = - getArtifactDescriptorResult( args, results, noDescriptor, d, descriptorRequest ); - } + rangeResult = cachedResolveRangeResult( rangeRequest, args.pool, args.session ); + + versions = filterVersions( dependency, rangeResult, verFilter, args.versionContext ); } catch ( VersionRangeResolutionException e ) { results.addException( dependency, e, args.nodes ); - } - return dc; - } - - private void processDependencyNode( DependencyContext dc ) - { - if ( dc == null ) - { return; } - try + + for ( Version version : versions ) { - boolean noResult = dc.futureDescriptorResult == null; - if ( !noResult ) - { - dc.descriptorResult = dc.futureDescriptorResult.get(); - noResult = dc.descriptorResult == null; - } - if ( noResult ) - { - List<RemoteRepository> repos = - getRemoteRepositories( dc.rangeResult.getRepository( dc.version ), dc.context.getRepositories() ); - addDependencyNode( dc.args.nodes.top(), dc.relocations, dc.preManaged, dc.rangeResult, dc.version, - dc.managedDependency, null, repos, dc.args.request.getRequestContext() ); - } - else + Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() ); + Dependency d = dependency.setArtifact( originalArtifact ); + + ArtifactDescriptorRequest descriptorRequest = createArtifactDescriptorRequest( args, repositories, d ); + + final ArtifactDescriptorResult descriptorResult = + getArtifactDescriptorResult( args, results, noDescriptor, d, descriptorRequest ); + if ( descriptorResult != null ) { - processDependencyVersion( dc ); - } - } - catch ( InterruptedException e ) - { - dc.context.getResults().addException( dc.preManaged.managedDependency, e, dc.args.nodes ); - } - catch ( ExecutionException e ) - { - dc.context.getResults().addException( dc.preManaged.managedDependency, (Exception) e.getCause(), - dc.args.nodes ); - } - } + d = d.setArtifact( descriptorResult.getArtifact() ); - private boolean processDependencyVersion( DependencyContext dc ) - { - Args args = dc.context.getArgs(); - Results results = dc.context.getResults(); - Dependency d = dc.managedDependency.setArtifact( dc.descriptorResult.getArtifact() ); - dc.managedDependency = d; + DependencyNode node = args.nodes.top(); - DependencyNode node = args.nodes.top(); + int cycleEntry = args.nodes.find( d.getArtifact() ); + if ( cycleEntry >= 0 ) + { + results.addCycle( args.nodes, cycleEntry, d ); + DependencyNode cycleNode = args.nodes.get( cycleEntry ); + if ( cycleNode.getDependency() != null ) + { + DefaultDependencyNode child = + createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult, + cycleNode ); + node.getChildren().add( child ); + continue; + } + } - int cycleEntry = args.nodes.find( d.getArtifact() ); - if ( cycleEntry >= 0 ) - { - results.addCycle( args.nodes, cycleEntry, d ); - DependencyNode cycleNode = args.nodes.get( cycleEntry ); - if ( cycleNode.getDependency() != null ) - { - createDependencyNode( node, dc.relocations, dc.preManaged, dc.rangeResult, dc.version, d, - dc.descriptorResult, cycleNode ); - return true; - } - } + if ( !descriptorResult.getRelocations().isEmpty() ) + { + boolean disableVersionManagementSubsequently = + originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() ) + && originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() ); - if ( !dc.descriptorResult.getRelocations().isEmpty() ) - { - boolean disableVersionManagementSubsequently = - dc.originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() ) - && dc.originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() ); + processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d, + descriptorResult.getRelocations(), disableVersionManagementSubsequently ); + return; + } + else + { + d = args.pool.intern( d.setArtifact( args.pool.intern( d.getArtifact() ) ) ); - DependencyContext dc2 = new DependencyContext(); - dc2.context = dc.context; - dc2.origDependency = d; - dc2.relocations = dc.descriptorResult.getRelocations(); - dc2.disableVersionManagement = disableVersionManagementSubsequently; - dc2 = processDependency( dc2 ); - processDependencyNode( dc2 ); - return true; - } - else - { - d = args.pool.intern( d ); + List<RemoteRepository> repos = + getRemoteRepositories( rangeResult.getRepository( version ), repositories ); - List<RemoteRepository> repos = - getRemoteRepositories( dc.rangeResult.getRepository( dc.version ), dc.context.getRepositories() ); + DefaultDependencyNode child = + createDependencyNode( relocations, preManaged, rangeResult, version, d, + descriptorResult.getAliases(), repos, args.request.getRequestContext() ); - DefaultDependencyNode child = - addDependencyNode( node, dc.relocations, dc.preManaged, dc.rangeResult, dc.version, d, - dc.descriptorResult.getAliases(), repos, args.request.getRequestContext() ); + node.getChildren().add( child ); - if ( dc.traverse && !dc.descriptorResult.getDependencies().isEmpty() ) + boolean recurse = traverse && !descriptorResult.getDependencies().isEmpty(); + if ( recurse ) + { + doRecurse( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d, + descriptorResult, child ); + } + } + } + else { - doRecurse( dc.context, d, dc.descriptorResult, child ); + DependencyNode node = args.nodes.top(); + List<RemoteRepository> repos = + getRemoteRepositories( rangeResult.getRepository( version ), repositories ); + DefaultDependencyNode child = + createDependencyNode( relocations, preManaged, rangeResult, version, d, null, repos, + args.request.getRequestContext() ); + node.getChildren().add( child ); } - return false; } } - private void doRecurse( DefaultDependencyCollectionContext context, Dependency d, + @SuppressWarnings( "checkstyle:parameternumber" ) + private void doRecurse( Args args, Results results, List<RemoteRepository> repositories, + DependencySelector depSelector, DependencyManager depManager, + DependencyTraverser depTraverser, VersionFilter verFilter, Dependency d, ArtifactDescriptorResult descriptorResult, DefaultDependencyNode child ) { - context.setDependency( d ); - context.setManagedDependencies( descriptorResult.getManagedDependencies() ); + DefaultDependencyCollectionContext context = args.collectionContext; + context.set( d, descriptorResult.getManagedDependencies() ); - DefaultDependencyCollectionContext childContext = context.createChildContext(); - Args args = context.getArgs(); + DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector( context ) : null; + DependencyManager childManager = depManager != null ? depManager.deriveChildManager( context ) : null; + DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null; + VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null; - final List<RemoteRepository> childRepos = args.ignoreRepos ? context.getRepositories() - : remoteRepositoryManager.aggregateRepositories( args.session, context.getRepositories(), - descriptorResult.getRepositories(), true ); - childContext.setRepositories( childRepos ); + final List<RemoteRepository> childRepos = + args.ignoreRepos + ? repositories + : remoteRepositoryManager.aggregateRepositories( args.session, repositories, + descriptorResult.getRepositories(), true ); - Object key = args.pool.toKey( d.getArtifact(), childContext ); + Object key = + args.pool.toKey( d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter ); List<DependencyNode> children = args.pool.getChildren( key ); if ( children == null ) @@ -596,11 +506,8 @@ public class DefaultDependencyCollector args.nodes.push( child ); - childContext.setArgs( args ); - childContext.setResults( context.getResults() ); - childContext.setDependencies( descriptorResult.getDependencies() ); - - process( childContext ); + process( args, results, descriptorResult.getDependencies(), childRepos, childSelector, childManager, + childTraverser, childFilter ); args.nodes.pop(); } @@ -610,50 +517,100 @@ public class DefaultDependencyCollector } } - private Future<ArtifactDescriptorResult> getArtifactDescriptorResult( Args args, Results results, - boolean noDescriptor, Dependency d, - ArtifactDescriptorRequest descriptorRequest ) + private ArtifactDescriptorResult getArtifactDescriptorResult( Args args, Results results, boolean noDescriptor, + Dependency d, + ArtifactDescriptorRequest descriptorRequest ) { return noDescriptor - ? new FutureResult<>( new ArtifactDescriptorResult( descriptorRequest ) ) - : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, - args ); + ? new ArtifactDescriptorResult( descriptorRequest ) + : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, args ); + } - private Future<ArtifactDescriptorResult> resolveCachedArtifactDescriptor( - final DataPool pool, final ArtifactDescriptorRequest descriptorRequest, - final RepositorySystemSession session, final Dependency d, final Results results, final Args args ) + private ArtifactDescriptorResult resolveCachedArtifactDescriptor( DataPool pool, + ArtifactDescriptorRequest descriptorRequest, + RepositorySystemSession session, Dependency d, + Results results, Args args ) { - final Object key = pool.toKey( descriptorRequest ); - Future<ArtifactDescriptorResult> descriptorResult = pool.getDescriptor( key, descriptorRequest ); + Object key = pool.toKey( descriptorRequest ); + ArtifactDescriptorResult descriptorResult = pool.getDescriptor( key, descriptorRequest ); if ( descriptorResult == null ) { - descriptorResult = args.executor.submit( new Callable<ArtifactDescriptorResult>() + try { - public ArtifactDescriptorResult call() - { - try - { - return descriptorReader.readArtifactDescriptor( session, descriptorRequest ); - } - catch ( ArtifactDescriptorException e ) - { - results.addException( d, e, args.nodes ); - pool.putDescriptor( key, e ); - return null; - } - } - } ); + descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); + pool.putDescriptor( key, descriptorResult ); + } + catch ( ArtifactDescriptorException e ) + { + results.addException( d, e, args.nodes ); + pool.putDescriptor( key, e ); + return null; + } - pool.putDescriptor( key, descriptorResult ); } else if ( descriptorResult == DataPool.NO_DESCRIPTOR ) { - return new FutureResult<>( null ); + return null; } return descriptorResult; } + + @SuppressWarnings( "checkstyle:parameternumber" ) + private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations, + PremanagedDependency preManaged, + VersionRangeResult rangeResult, Version version, + Dependency d, Collection<Artifact> aliases, + List<RemoteRepository> repos, String requestContext ) + { + DefaultDependencyNode child = new DefaultDependencyNode( d ); + preManaged.applyTo( child ); + child.setRelocations( relocations ); + child.setVersionConstraint( rangeResult.getVersionConstraint() ); + child.setVersion( version ); + child.setAliases( aliases ); + child.setRepositories( repos ); + child.setRequestContext( requestContext ); + return child; + } + + private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations, + PremanagedDependency preManaged, + VersionRangeResult rangeResult, Version version, + Dependency d, ArtifactDescriptorResult descriptorResult, + DependencyNode cycleNode ) + { + DefaultDependencyNode child = + createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(), + cycleNode.getRepositories(), cycleNode.getRequestContext() ); + child.setChildren( cycleNode.getChildren() ); + return child; + } + + private static ArtifactDescriptorRequest createArtifactDescriptorRequest( Args args, + List<RemoteRepository> repositories, + Dependency d ) + { + ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest(); + descriptorRequest.setArtifact( d.getArtifact() ); + descriptorRequest.setRepositories( repositories ); + descriptorRequest.setRequestContext( args.request.getRequestContext() ); + descriptorRequest.setTrace( args.trace ); + return descriptorRequest; + } + + private static VersionRangeRequest createVersionRangeRequest( Args args, List<RemoteRepository> repositories, + Dependency dependency ) + { + VersionRangeRequest rangeRequest = new VersionRangeRequest(); + rangeRequest.setArtifact( dependency.getArtifact() ); + rangeRequest.setRepositories( repositories ); + rangeRequest.setRequestContext( args.request.getRequestContext() ); + rangeRequest.setTrace( args.trace ); + return rangeRequest; + } + private VersionRangeResult cachedResolveRangeResult( VersionRangeRequest rangeRequest, DataPool pool, RepositorySystemSession session ) throws VersionRangeResolutionException @@ -686,4 +643,261 @@ public class DefaultDependencyCollector } return repositories; } + + private static List<? extends Version> filterVersions( Dependency dependency, VersionRangeResult rangeResult, + VersionFilter verFilter, + DefaultVersionFilterContext verContext ) + throws VersionRangeResolutionException + { + if ( rangeResult.getVersions().isEmpty() ) + { + throw new VersionRangeResolutionException( rangeResult, + "No versions available for " + dependency.getArtifact() + + " within specified range" ); + } + + List<? extends Version> versions; + if ( verFilter != null && rangeResult.getVersionConstraint().getRange() != null ) + { + verContext.set( dependency, rangeResult ); + try + { + verFilter.filterVersions( verContext ); + } + catch ( RepositoryException e ) + { + throw new VersionRangeResolutionException( rangeResult, + "Failed to filter versions for " + dependency.getArtifact() + + ": " + e.getMessage(), e ); + } + versions = verContext.get(); + if ( versions.isEmpty() ) + { + throw new VersionRangeResolutionException( rangeResult, + "No acceptable versions for " + dependency.getArtifact() + + ": " + rangeResult.getVersions() ); + } + } + else + { + versions = rangeResult.getVersions(); + } + return versions; + } + + static class Args + { + + final RepositorySystemSession session; + + final boolean ignoreRepos; + + final boolean premanagedState; + + final RequestTrace trace; + + final DataPool pool; + + final NodeStack nodes; + + final DefaultDependencyCollectionContext collectionContext; + + final DefaultVersionFilterContext versionContext; + + final CollectRequest request; + + Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, NodeStack nodes, + DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext, + CollectRequest request ) + { + this.session = session; + this.request = request; + this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories(); + this.premanagedState = ConfigUtils.getBoolean( session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE ); + this.trace = trace; + this.pool = pool; + this.nodes = nodes; + this.collectionContext = collectionContext; + this.versionContext = versionContext; + } + + } + + static class Results + { + + private final CollectResult result; + + final int maxExceptions; + + final int maxCycles; + + String errorPath; + + Results( CollectResult result, RepositorySystemSession session ) + { + this.result = result; + + maxExceptions = + ConfigUtils.getInteger( session, CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT, CONFIG_PROP_MAX_EXCEPTIONS ); + + maxCycles = ConfigUtils.getInteger( session, CONFIG_PROP_MAX_CYCLES_DEFAULT, CONFIG_PROP_MAX_CYCLES ); + } + + public void addException( Dependency dependency, Exception e, NodeStack nodes ) + { + if ( maxExceptions < 0 || result.getExceptions().size() < maxExceptions ) + { + result.addException( e ); + if ( errorPath == null ) + { + StringBuilder buffer = new StringBuilder( 256 ); + for ( int i = 0; i < nodes.size(); i++ ) + { + if ( buffer.length() > 0 ) + { + buffer.append( " -> " ); + } + Dependency dep = nodes.get( i ).getDependency(); + if ( dep != null ) + { + buffer.append( dep.getArtifact() ); + } + } + if ( buffer.length() > 0 ) + { + buffer.append( " -> " ); + } + buffer.append( dependency.getArtifact() ); + errorPath = buffer.toString(); + } + } + } + + public void addCycle( NodeStack nodes, int cycleEntry, Dependency dependency ) + { + if ( maxCycles < 0 || result.getCycles().size() < maxCycles ) + { + result.addCycle( new DefaultDependencyCycle( nodes, cycleEntry, dependency ) ); + } + } + + } + + static class PremanagedDependency + { + + final String premanagedVersion; + + final String premanagedScope; + + final Boolean premanagedOptional; + + /** + * @since 1.1.0 + */ + final Collection<Exclusion> premanagedExclusions; + + /** + * @since 1.1.0 + */ + final Map<String, String> premanagedProperties; + + final int managedBits; + + final Dependency managedDependency; + + final boolean premanagedState; + + @SuppressWarnings( "checkstyle:parameternumber" ) + PremanagedDependency( String premanagedVersion, String premanagedScope, Boolean premanagedOptional, + Collection<Exclusion> premanagedExclusions, Map<String, String> premanagedProperties, + int managedBits, Dependency managedDependency, boolean premanagedState ) + { + this.premanagedVersion = premanagedVersion; + this.premanagedScope = premanagedScope; + this.premanagedOptional = premanagedOptional; + this.premanagedExclusions = + premanagedExclusions != null + ? Collections.unmodifiableCollection( new ArrayList<>( premanagedExclusions ) ) + : null; + + this.premanagedProperties = + premanagedProperties != null + ? Collections.unmodifiableMap( new HashMap<>( premanagedProperties ) ) + : null; + + this.managedBits = managedBits; + this.managedDependency = managedDependency; + this.premanagedState = premanagedState; + } + + static PremanagedDependency create( DependencyManager depManager, Dependency dependency, + boolean disableVersionManagement, boolean premanagedState ) + { + DependencyManagement depMngt = depManager != null ? depManager.manageDependency( dependency ) : null; + + int managedBits = 0; + String premanagedVersion = null; + String premanagedScope = null; + Boolean premanagedOptional = null; + Collection<Exclusion> premanagedExclusions = null; + Map<String, String> premanagedProperties = null; + + if ( depMngt != null ) + { + if ( depMngt.getVersion() != null && !disableVersionManagement ) + { + Artifact artifact = dependency.getArtifact(); + premanagedVersion = artifact.getVersion(); + dependency = dependency.setArtifact( artifact.setVersion( depMngt.getVersion() ) ); + managedBits |= DependencyNode.MANAGED_VERSION; + } + if ( depMngt.getProperties() != null ) + { + Artifact artifact = dependency.getArtifact(); + premanagedProperties = artifact.getProperties(); + dependency = dependency.setArtifact( artifact.setProperties( depMngt.getProperties() ) ); + managedBits |= DependencyNode.MANAGED_PROPERTIES; + } + if ( depMngt.getScope() != null ) + { + premanagedScope = dependency.getScope(); + dependency = dependency.setScope( depMngt.getScope() ); + managedBits |= DependencyNode.MANAGED_SCOPE; + } + if ( depMngt.getOptional() != null ) + { + premanagedOptional = dependency.isOptional(); + dependency = dependency.setOptional( depMngt.getOptional() ); + managedBits |= DependencyNode.MANAGED_OPTIONAL; + } + if ( depMngt.getExclusions() != null ) + { + premanagedExclusions = dependency.getExclusions(); + dependency = dependency.setExclusions( depMngt.getExclusions() ); + managedBits |= DependencyNode.MANAGED_EXCLUSIONS; + } + } + return new PremanagedDependency( premanagedVersion, premanagedScope, premanagedOptional, + premanagedExclusions, premanagedProperties, managedBits, dependency, + premanagedState ); + + } + + public void applyTo( DefaultDependencyNode child ) + { + child.setManagedBits( managedBits ); + if ( premanagedState ) + { + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION, premanagedVersion ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE, premanagedScope ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_OPTIONAL, premanagedOptional ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_EXCLUSIONS, premanagedExclusions ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_PROPERTIES, premanagedProperties ); + } + } + + } + }