This is an automated email from the ASF dual-hosted git repository. michaelo pushed a commit to branch MRESOLVER-7 in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
commit 9d3b324e82d9b934bf51bb8818c83caf776e6faf Author: Harald Wellmann <[email protected]> AuthorDate: Sun Jul 1 01:28:33 2018 +0200 [MRESOLVER-7] Download dependency POMs in parallel Dependencies are now processed asynchronously by an Executor This closes #30 --- .../eclipse/aether/internal/impl/collect/Args.java | 69 ++ .../aether/internal/impl/collect/DataPool.java | 118 +-- .../DefaultDependencyCollectionContext.java | 178 ++++- .../impl/collect/DefaultDependencyCollector.java | 869 ++++++++------------- .../impl/collect/DependencyCollectionUtils.java | 171 ++++ .../internal/impl/collect/DependencyContext.java | 74 ++ .../impl/collect/PremanagedDependency.java | 148 ++++ .../aether/internal/impl/collect/Results.java | 83 ++ .../aether/internal/impl/collect/DataPoolTest.java | 16 +- .../collect/DefaultDependencyCollectorTest.java | 51 +- .../artifact-descriptions/gid3_aid1_1.ini | 7 + .../artifact-descriptions/gid3_aid2_1.ini | 2 + .../artifact-descriptions/gid3_aid3_1.ini | 2 + .../artifact-descriptions/gid3_aid3_2.ini | 2 + .../aether/util/concurrency/FutureResult.java | 69 ++ 15 files changed, 1261 insertions(+), 598 deletions(-) diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/Args.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/Args.java new file mode 100644 index 0000000..7d5e96f --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/Args.java @@ -0,0 +1,69 @@ +package org.eclipse.aether.internal.impl.collect; + +/* + * 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.concurrent.ExecutorService; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.RequestTrace; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.util.ConfigUtils; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; + +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; + + final ExecutorService executor; + + Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, NodeStack nodes, + DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext, + CollectRequest request, ExecutorService executor ) + { + 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; + this.executor = executor; + } + +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java index a8a8e9e..b2390bb 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java @@ -19,12 +19,15 @@ package org.eclipse.aether.internal.impl.collect; * under the License. */ -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.eclipse.aether.RepositoryCache; import org.eclipse.aether.RepositorySystemSession; @@ -42,6 +45,7 @@ import org.eclipse.aether.resolution.ArtifactDescriptorRequest; import org.eclipse.aether.resolution.ArtifactDescriptorResult; import org.eclipse.aether.resolution.VersionRangeRequest; import org.eclipse.aether.resolution.VersionRangeResult; +import org.eclipse.aether.util.concurrency.FutureResult; import org.eclipse.aether.version.Version; import org.eclipse.aether.version.VersionConstraint; @@ -56,8 +60,8 @@ final class DataPool private static final String DESCRIPTORS = DataPool.class.getName() + "$Descriptors"; - public static final ArtifactDescriptorResult NO_DESCRIPTOR = - new ArtifactDescriptorResult( new ArtifactDescriptorRequest() ); + public static final Future<ArtifactDescriptorResult> NO_DESCRIPTOR = + new FutureResult<>( new ArtifactDescriptorResult( new ArtifactDescriptorRequest() ) ); private ObjectPool<Artifact> artifacts; @@ -65,9 +69,9 @@ final class DataPool private Map<Object, Descriptor> descriptors; - private Map<Object, Constraint> constraints = new HashMap<Object, Constraint>(); + private Map<Object, Constraint> constraints = new HashMap<>(); - private Map<Object, List<DependencyNode>> nodes = new HashMap<Object, List<DependencyNode>>( 256 ); + private Map<Object, List<DependencyNode>> nodes = new HashMap<>( 256 ); @SuppressWarnings( "unchecked" ) DataPool( RepositorySystemSession session ) @@ -83,7 +87,7 @@ final class DataPool if ( artifacts == null ) { - artifacts = new ObjectPool<Artifact>(); + artifacts = new ObjectPool<>(); if ( cache != null ) { cache.put( session, ARTIFACT_POOL, artifacts ); @@ -92,7 +96,7 @@ final class DataPool if ( dependencies == null ) { - dependencies = new ObjectPool<Dependency>(); + dependencies = new ObjectPool<>(); if ( cache != null ) { cache.put( session, DEPENDENCY_POOL, dependencies ); @@ -124,7 +128,7 @@ final class DataPool return request.getArtifact(); } - public ArtifactDescriptorResult getDescriptor( Object key, ArtifactDescriptorRequest request ) + public Future<ArtifactDescriptorResult> getDescriptor( Object key, ArtifactDescriptorRequest request ) { Descriptor descriptor = descriptors.get( key ); if ( descriptor != null ) @@ -134,12 +138,12 @@ final class DataPool return null; } - public void putDescriptor( Object key, ArtifactDescriptorResult result ) + public void putDescriptor( Object key, Future<ArtifactDescriptorResult> futureResult ) { - descriptors.put( key, new GoodDescriptor( result ) ); + descriptors.put( key, new GoodDescriptor( futureResult ) ); } - public void putDescriptor( Object key, ArtifactDescriptorException e ) + public void putDescriptor( Object key, ArtifactDescriptorException exception ) { descriptors.put( key, BadDescriptor.INSTANCE ); } @@ -164,10 +168,10 @@ final class DataPool constraints.put( key, new Constraint( result ) ); } - public Object toKey( Artifact artifact, List<RemoteRepository> repositories, DependencySelector selector, - DependencyManager manager, DependencyTraverser traverser, VersionFilter filter ) + public Object toKey( Artifact artifact, DefaultDependencyCollectionContext context ) { - return new GraphKey( artifact, repositories, selector, manager, traverser, filter ); + return new GraphKey( artifact, context.getRepositories(), context.getDepSelector(), + context.getDepManager(), context.getDepTraverser(), context.getVerFilter() ); } public List<DependencyNode> getChildren( Object key ) @@ -182,67 +186,79 @@ final class DataPool abstract static class Descriptor { - - public abstract ArtifactDescriptorResult toResult( ArtifactDescriptorRequest request ); - + public abstract Future<ArtifactDescriptorResult> toResult( ArtifactDescriptorRequest request ); } static final class GoodDescriptor extends Descriptor { + Future<ArtifactDescriptorResult> futureResult; - final Artifact artifact; - - final List<Artifact> relocations; - - final Collection<Artifact> aliases; + GoodDescriptor( Future<ArtifactDescriptorResult> futureResult ) + { + this.futureResult = futureResult; + } - final List<RemoteRepository> repositories; + public Future<ArtifactDescriptorResult> toResult( final ArtifactDescriptorRequest request ) + { + return new Future<ArtifactDescriptorResult>() + { + public boolean cancel( boolean mayInterruptIfRunning ) + { + return futureResult.cancel( mayInterruptIfRunning ); + } - final List<Dependency> dependencies; + public boolean isCancelled() + { + return futureResult.isCancelled(); + } - final List<Dependency> managedDependencies; + public boolean isDone() + { + return futureResult.isDone(); + } - GoodDescriptor( ArtifactDescriptorResult result ) - { - artifact = result.getArtifact(); - relocations = result.getRelocations(); - aliases = result.getAliases(); - dependencies = result.getDependencies(); - managedDependencies = result.getManagedDependencies(); - repositories = result.getRepositories(); + public ArtifactDescriptorResult get() + throws InterruptedException, ExecutionException + { + ArtifactDescriptorResult result = futureResult.get(); + return wrap( request, result ); + } + public ArtifactDescriptorResult get( long timeout, TimeUnit unit ) + throws InterruptedException, ExecutionException, TimeoutException + { + ArtifactDescriptorResult result = futureResult.get( timeout, unit ); + return wrap( request, result ); + } + }; } - public ArtifactDescriptorResult toResult( ArtifactDescriptorRequest request ) + private ArtifactDescriptorResult wrap( ArtifactDescriptorRequest request, ArtifactDescriptorResult result ) { - ArtifactDescriptorResult result = new ArtifactDescriptorResult( request ); - result.setArtifact( artifact ); - result.setRelocations( relocations ); - result.setAliases( aliases ); - result.setDependencies( dependencies ); - result.setManagedDependencies( managedDependencies ); - result.setRepositories( repositories ); - return result; + ArtifactDescriptorResult wrapped = new ArtifactDescriptorResult( request ); + wrapped.setArtifact( result.getArtifact() ); + wrapped.setRelocations( result.getRelocations() ); + wrapped.setAliases( result.getAliases() ); + wrapped.setDependencies( result.getDependencies() ); + wrapped.setManagedDependencies( result.getManagedDependencies() ); + wrapped.setRepositories( result.getRepositories() ); + return wrapped; } - } static final class BadDescriptor extends Descriptor { - static final BadDescriptor INSTANCE = new BadDescriptor(); - public ArtifactDescriptorResult toResult( ArtifactDescriptorRequest request ) + public Future<ArtifactDescriptorResult> toResult( ArtifactDescriptorRequest request ) { return NO_DESCRIPTOR; } - } static final class Constraint { - final VersionRepo[] repositories; final VersionConstraint versionConstraint; @@ -273,7 +289,6 @@ final class DataPool static final class VersionRepo { - final Version version; final ArtifactRepository repo; @@ -283,14 +298,11 @@ final class DataPool this.version = version; this.repo = repo; } - } - } static final class ConstraintKey { - private final Artifact artifact; private final List<RemoteRepository> repositories; @@ -361,12 +373,10 @@ final class DataPool { return hashCode; } - } static final class GraphKey { - private final Artifact artifact; private final List<RemoteRepository> repositories; @@ -382,7 +392,7 @@ final class DataPool private final int hashCode; GraphKey( Artifact artifact, List<RemoteRepository> repositories, DependencySelector selector, - DependencyManager manager, DependencyTraverser traverser, VersionFilter filter ) + DependencyManager manager, DependencyTraverser traverser, VersionFilter filter ) { this.artifact = artifact; this.repositories = repositories; diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectionContext.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectionContext.java index 3bf4fe1..6ea858b 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectionContext.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectionContext.java @@ -22,14 +22,22 @@ package org.eclipse.aether.internal.impl.collect; import java.util.List; import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.RequestTrace; import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.CollectResult; import org.eclipse.aether.collection.DependencyCollectionContext; +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.Dependency; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.version.Version; /** * @see DefaultDependencyCollector */ -final class DefaultDependencyCollectionContext +class DefaultDependencyCollectionContext implements DependencyCollectionContext { @@ -40,9 +48,31 @@ final class DefaultDependencyCollectionContext private Dependency dependency; private List<Dependency> managedDependencies; + private CollectResult collectResult; + + private RequestTrace trace; + + private Args args; + + private Results results; + + private List<Dependency> dependencies; + + private List<RemoteRepository> repositories; + + private DependencySelector depSelector; + + private DependencyManager depManager; + + private DependencyTraverser depTraverser; + + private VersionFilter verFilter; + + private Version version; + DefaultDependencyCollectionContext( RepositorySystemSession session, Artifact artifact, - Dependency dependency, List<Dependency> managedDependencies ) + Dependency dependency, List<Dependency> managedDependencies ) { this.session = session; this.artifact = ( dependency != null ) ? dependency.getArtifact() : artifact; @@ -50,6 +80,34 @@ final class DefaultDependencyCollectionContext this.managedDependencies = managedDependencies; } + public void prepareDescent() + { + DependencySelector dependencySelector = session.getDependencySelector(); + DependencyManager dependencyManager = session.getDependencyManager(); + VersionFilter versionFilter = session.getVersionFilter(); + setDepSelector( dependencySelector != null ? dependencySelector.deriveChildSelector( this ) : null ); + setDepManager( dependencyManager != null ? dependencyManager.deriveChildManager( this ) : null ); + setDepTraverser( depTraverser != null ? depTraverser.deriveChildTraverser( this ) : null ); + setVerFilter( versionFilter != null ? versionFilter.deriveChildFilter( this ) : null ); + + } + + public DefaultDependencyCollectionContext createChildContext() + { + DefaultDependencyCollectionContext childContext = + new DefaultDependencyCollectionContext( getSession(), getArtifact(), + getDependency(), getManagedDependencies() ); + childContext.depSelector = + getDepSelector() != null ? getDepSelector().deriveChildSelector( this ) : null; + childContext.depManager = + getDepManager() != null ? getDepManager().deriveChildManager( this ) : null; + childContext.depTraverser = + getDepTraverser() != null ? getDepTraverser().deriveChildTraverser( this ) : null; + childContext.verFilter = + getVerFilter() != null ? getVerFilter().deriveChildFilter( this ) : null; + return childContext; + } + public RepositorySystemSession getSession() { return session; @@ -70,13 +128,127 @@ final class DefaultDependencyCollectionContext return managedDependencies; } - public void set( Dependency dependency, List<Dependency> managedDependencies ) + public CollectResult getCollectResult() + { + return collectResult; + } + + public void setCollectResult( CollectResult collectResult ) + { + this.collectResult = collectResult; + } + + public Args getArgs() + { + return args; + } + + public void setArgs( Args args ) + { + this.args = args; + } + + public Results getResults() + { + return results; + } + + public void setResults( Results results ) + { + this.results = results; + } + + public List<Dependency> getDependencies() + { + return dependencies; + } + + public void setDependencies( List<Dependency> dependencies ) + { + this.dependencies = dependencies; + } + + public List<RemoteRepository> getRepositories() + { + return repositories; + } + + public void setRepositories( List<RemoteRepository> repositories ) + { + this.repositories = repositories; + } + + public DependencySelector getDepSelector() + { + return depSelector; + } + + public void setDepSelector( DependencySelector depSelector ) + { + this.depSelector = depSelector; + } + + public DependencyManager getDepManager() + { + return depManager; + } + + public void setDepManager( DependencyManager depManager ) + { + this.depManager = depManager; + } + + public DependencyTraverser getDepTraverser() + { + return depTraverser; + } + + public void setDepTraverser( DependencyTraverser depTraverser ) + { + this.depTraverser = depTraverser; + } + + public VersionFilter getVerFilter() + { + return verFilter; + } + + public void setVerFilter( VersionFilter verFilter ) + { + this.verFilter = verFilter; + } + + public void setDependency( Dependency dependency ) { artifact = dependency.getArtifact(); this.dependency = dependency; + } + + public void setManagedDependencies( List<Dependency> managedDependencies ) + { this.managedDependencies = managedDependencies; } + public RequestTrace getTrace() + { + return trace; + } + + public void setTrace( RequestTrace trace ) + { + this.trace = trace; + } + + public Version getVersion() + { + return version; + } + + public void setVersion( Version version ) + { + this.version = version; + } + @Override public String toString() { 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 d2ca7d4..e4fb051 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 @@ -8,9 +8,9 @@ package org.eclipse.aether.internal.impl.collect; * 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 @@ -19,20 +19,31 @@ 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; @@ -42,15 +53,10 @@ 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; @@ -66,7 +72,8 @@ 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.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.concurrency.FutureResult; +import org.eclipse.aether.util.concurrency.WorkerThreadFactory; import org.eclipse.aether.util.graph.transformer.TransformationContextKeys; import org.eclipse.aether.version.Version; import org.slf4j.Logger; @@ -79,9 +86,12 @@ public class DefaultDependencyCollector implements DependencyCollector, Service { - private static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions"; + static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions"; + + 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 Logger LOGGER = LoggerFactory.getLogger( DefaultDependencyCollector.class ); @@ -134,71 +144,52 @@ public class DefaultDependencyCollector public CollectResult collectDependencies( RepositorySystemSession session, CollectRequest request ) throws DependencyCollectionException { - session = optimizeSession( session ); + 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 ); 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() ) @@ -207,14 +198,14 @@ public class DefaultDependencyCollector descriptorResult.getRepositories(), true ); } - dependencies = mergeDeps( dependencies, descriptorResult.getDependencies() ); - managedDependencies = mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() ); + context.setDependencies( mergeDeps( context.getDependencies(), descriptorResult.getDependencies() ) ); + context.setManagedDependencies( mergeDeps( managedDependencies, descriptorResult.getManagedDependencies() ) ); node = new DefaultDependencyNode( root ); node.setRequestContext( request.getRequestContext() ); node.setRelocations( descriptorResult.getRelocations() ); node.setVersionConstraint( rangeResult.getVersionConstraint() ); - node.setVersion( version ); + node.setVersion( context.getVersion() ); node.setAliases( descriptorResult.getAliases() ); node.setRepositories( request.getRepositories() ); } @@ -227,56 +218,41 @@ public class DefaultDependencyCollector result.setRoot( node ); + DependencyTraverser depTraverser = session.getDependencyTraverser(); boolean traverse = root == null || depTraverser == null || depTraverser.traverseDependency( root ); String errorPath = null; - if ( traverse && !dependencies.isEmpty() ) + if ( traverse && !context.getDependencies().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 args = new Args( session, trace, pool, nodes, context, versionContext, request ); + args = new Args( session, trace, pool, nodes, context, versionContext, request, executor ); Results results = new Results( result, session ); + context.setArgs( args ); + context.setResults( results ); + context.setRepositories( repositories ); + context.setDepTraverser( depTraverser ); + context.prepareDescent(); - 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 ); + process( context ); errorPath = results.errorPath; } long time2 = System.nanoTime(); - 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 ); - } - } + transformDependencyGraph( context, stats ); 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 ) @@ -291,11 +267,80 @@ public class DefaultDependencyCollector return result; } - private static RepositorySystemSession optimizeSession( RepositorySystemSession session ) + private VersionRangeResult resolveRootVersionRange( DefaultDependencyCollectionContext context ) + throws DependencyCollectionException { - DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session ); - optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) ); - return optimized; + 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 ) + { + 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 ); + } + } } private List<Dependency> mergeDeps( List<Dependency> dominant, List<Dependency> recessive ) @@ -312,8 +357,8 @@ public class DefaultDependencyCollector else { int initialCapacity = dominant.size() + recessive.size(); - result = new ArrayList<Dependency>( initialCapacity ); - Collection<String> ids = new HashSet<String>( initialCapacity, 1.0f ); + result = new ArrayList<>( initialCapacity ); + Collection<String> ids = new HashSet<>( initialCapacity, 1.0f ); for ( Dependency dependency : dominant ) { ids.add( getId( dependency.getArtifact() ) ); @@ -335,158 +380,213 @@ public class DefaultDependencyCollector return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension(); } - private void process( final Args args, Results results, List<Dependency> dependencies, - List<RemoteRepository> repositories, DependencySelector depSelector, - DependencyManager depManager, DependencyTraverser depTraverser, VersionFilter verFilter ) + private void process( DefaultDependencyCollectionContext context ) { - for ( Dependency dependency : dependencies ) + List<DependencyContext> depContexts = new ArrayList<>(); + for ( Dependency d : context.getDependencies() ) { - processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, - dependency ); + 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++; } } - private void processDependency( Args args, Results results, List<RemoteRepository> repositories, - DependencySelector depSelector, DependencyManager depManager, - DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency ) + private Future<DependencyContext> asyncProcessDependency( final DependencyContext dc ) { + return dc.args.executor.submit( new Callable<DependencyContext>() + { - List<Artifact> relocations = Collections.emptyList(); - boolean disableVersionManagement = false; - processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency, - relocations, disableVersionManagement ); + public DependencyContext call() + throws Exception + { + return processDependency( dc ); + } + } ); } - 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 ) + private DependencyContext processDependency( DependencyContext dc ) { + DefaultDependencyCollectionContext context = dc.context; + Args args = context.getArgs(); + Results results = context.getResults(); - if ( depSelector != null && !depSelector.selectDependency( dependency ) ) + if ( context.getDepSelector() != null && !context.getDepSelector().selectDependency( dc.origDependency ) ) { - return; + return null; } PremanagedDependency preManaged = - PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState ); - dependency = preManaged.managedDependency; + PremanagedDependency.create( context.getDepManager(), dc.origDependency, dc.disableVersionManagement, + args.premanagedState ); + Dependency dependency = preManaged.managedDependency; boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() ); - boolean traverse = !noDescriptor && ( depTraverser == null || depTraverser.traverseDependency( dependency ) ); + boolean traverse = !noDescriptor + && ( context.getDepTraverser() == null || context.getDepTraverser().traverseDependency( dependency ) ); - List<? extends Version> versions; - VersionRangeResult rangeResult; try { - VersionRangeRequest rangeRequest = createVersionRangeRequest( args, repositories, dependency ); - - rangeResult = cachedResolveRangeResult( rangeRequest, args.pool, args.session ); + 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 ) ) + { - versions = filterVersions( dependency, rangeResult, verFilter, args.versionContext ); + 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 ); + } } catch ( VersionRangeResolutionException e ) { results.addException( dependency, e, args.nodes ); - return; } + return dc; + } - for ( Version version : versions ) + private void processDependencyNode( DependencyContext dc ) + { + if ( dc == null ) { - 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 ) + return; + } + try + { + boolean noResult = dc.futureDescriptorResult == null; + if ( !noResult ) + { + dc.descriptorResult = dc.futureDescriptorResult.get(); + noResult = dc.descriptorResult == null; + } + if ( noResult ) { - d = d.setArtifact( descriptorResult.getArtifact() ); + 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 + { + 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 ); + } + } - DependencyNode node = args.nodes.top(); + 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; - 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; - } - } + DependencyNode node = args.nodes.top(); - if ( !descriptorResult.getRelocations().isEmpty() ) - { - boolean disableVersionManagementSubsequently = - originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() ) - && originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() ); + 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; + } + } - 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() ) ) ); + if ( !dc.descriptorResult.getRelocations().isEmpty() ) + { + boolean disableVersionManagementSubsequently = + dc.originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() ) + && dc.originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() ); - List<RemoteRepository> repos = - getRemoteRepositories( rangeResult.getRepository( version ), repositories ); + 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 ); - DefaultDependencyNode child = - createDependencyNode( relocations, preManaged, rangeResult, version, d, - descriptorResult.getAliases(), repos, args.request.getRequestContext() ); + List<RemoteRepository> repos = + getRemoteRepositories( dc.rangeResult.getRepository( dc.version ), dc.context.getRepositories() ); - node.getChildren().add( child ); + DefaultDependencyNode child = + addDependencyNode( node, dc.relocations, dc.preManaged, dc.rangeResult, dc.version, d, + dc.descriptorResult.getAliases(), repos, args.request.getRequestContext() ); - boolean recurse = traverse && !descriptorResult.getDependencies().isEmpty(); - if ( recurse ) - { - doRecurse( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d, - descriptorResult, child ); - } - } - } - else + if ( dc.traverse && !dc.descriptorResult.getDependencies().isEmpty() ) { - 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 ); + doRecurse( dc.context, d, dc.descriptorResult, child ); } + return false; } } - private void doRecurse( Args args, Results results, List<RemoteRepository> repositories, - DependencySelector depSelector, DependencyManager depManager, - DependencyTraverser depTraverser, VersionFilter verFilter, Dependency d, + private void doRecurse( DefaultDependencyCollectionContext context, Dependency d, ArtifactDescriptorResult descriptorResult, DefaultDependencyNode child ) { - DefaultDependencyCollectionContext context = args.collectionContext; - context.set( d, descriptorResult.getManagedDependencies() ); + context.setDependency( d ); + context.setManagedDependencies( descriptorResult.getManagedDependencies() ); - 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; + DefaultDependencyCollectionContext childContext = context.createChildContext(); + Args args = context.getArgs(); - final List<RemoteRepository> childRepos = - args.ignoreRepos - ? repositories - : remoteRepositoryManager.aggregateRepositories( args.session, repositories, - descriptorResult.getRepositories(), true ); + final List<RemoteRepository> childRepos = args.ignoreRepos ? context.getRepositories() + : remoteRepositoryManager.aggregateRepositories( args.session, context.getRepositories(), + descriptorResult.getRepositories(), true ); + childContext.setRepositories( childRepos ); - Object key = - args.pool.toKey( d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter ); + Object key = args.pool.toKey( d.getArtifact(), childContext ); List<DependencyNode> children = args.pool.getChildren( key ); if ( children == null ) @@ -495,8 +595,11 @@ public class DefaultDependencyCollector args.nodes.push( child ); - process( args, results, descriptorResult.getDependencies(), childRepos, childSelector, childManager, - childTraverser, childFilter ); + childContext.setArgs( args ); + childContext.setResults( context.getResults() ); + childContext.setDependencies( descriptorResult.getDependencies() ); + + process( childContext ); args.nodes.pop(); } @@ -506,99 +609,54 @@ public class DefaultDependencyCollector } } - private ArtifactDescriptorResult getArtifactDescriptorResult( Args args, Results results, boolean noDescriptor, - Dependency d, - ArtifactDescriptorRequest descriptorRequest ) + private Future<ArtifactDescriptorResult> getArtifactDescriptorResult( Args args, Results results, + boolean noDescriptor, Dependency d, + ArtifactDescriptorRequest descriptorRequest ) { return noDescriptor - ? new ArtifactDescriptorResult( descriptorRequest ) - : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, args ); - + ? new FutureResult<ArtifactDescriptorResult>( new ArtifactDescriptorResult( descriptorRequest ) ) + : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, + args ); } - private ArtifactDescriptorResult resolveCachedArtifactDescriptor( DataPool pool, - ArtifactDescriptorRequest descriptorRequest, - RepositorySystemSession session, Dependency d, - Results results, Args args ) + private Future<ArtifactDescriptorResult> resolveCachedArtifactDescriptor( final DataPool pool, + final ArtifactDescriptorRequest descriptorRequest, + final RepositorySystemSession session, + final Dependency d, final Results results, + final Args args ) { - Object key = pool.toKey( descriptorRequest ); - ArtifactDescriptorResult descriptorResult = pool.getDescriptor( key, descriptorRequest ); + final Object key = pool.toKey( descriptorRequest ); + Future<ArtifactDescriptorResult> descriptorResult = pool.getDescriptor( key, descriptorRequest ); if ( descriptorResult == null ) { - try - { - descriptorResult = descriptorReader.readArtifactDescriptor( session, descriptorRequest ); - pool.putDescriptor( key, descriptorResult ); - } - catch ( ArtifactDescriptorException e ) + descriptorResult = args.executor.submit( new Callable<ArtifactDescriptorResult>() { - results.addException( d, e, args.nodes ); - pool.putDescriptor( key, e ); - return null; - } + public ArtifactDescriptorResult call() + throws Exception + { + try + { + return descriptorReader.readArtifactDescriptor( session, descriptorRequest ); + } + 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 null; + return new FutureResult<>( null ); } return descriptorResult; } - - 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 @@ -631,257 +689,4 @@ 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; - this.maxExceptions = ConfigUtils.getInteger( session, 50, CONFIG_PROP_MAX_EXCEPTIONS ); - this.maxCycles = ConfigUtils.getInteger( session, 10, 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; - - 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<Exclusion>( premanagedExclusions ) ) - : null; - - this.premanagedProperties = - premanagedProperties != null - ? Collections.unmodifiableMap( new HashMap<String, String>( 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 ); - } - } - - } - } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectionUtils.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectionUtils.java new file mode 100644 index 0000000..e5d777d --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectionUtils.java @@ -0,0 +1,171 @@ +package org.eclipse.aether.internal.impl.collect; + +/* + * 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.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositoryException; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.ArtifactProperties; +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.repository.ArtifactRepository; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactDescriptorRequest; +import org.eclipse.aether.resolution.ArtifactDescriptorResult; +import org.eclipse.aether.resolution.VersionRangeRequest; +import org.eclipse.aether.resolution.VersionRangeResolutionException; +import org.eclipse.aether.resolution.VersionRangeResult; +import org.eclipse.aether.version.Version; + +/** + * Utility methods for dependency collection. + * + */ +public class DependencyCollectionUtils +{ + + static DefaultDependencyNode addDependencyNode( DependencyNode parent, 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 ); + parent.getChildren().add( child ); + return child; + } + + static DefaultDependencyNode createDependencyNode( DependencyNode parent, List<Artifact> relocations, + PremanagedDependency preManaged, VersionRangeResult rangeResult, + Version version, Dependency d, + ArtifactDescriptorResult descriptorResult, + DependencyNode cycleNode ) + { + DefaultDependencyNode child = + addDependencyNode( parent, relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(), + cycleNode.getRepositories(), cycleNode.getRequestContext() ); + child.setChildren( cycleNode.getChildren() ); + return child; + } + + 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; + } + + 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; + } + + static boolean isLackingDescriptor( Artifact artifact ) + { + return artifact.getProperty( ArtifactProperties.LOCAL_PATH, null ) != null; + } + + static List<RemoteRepository> getRemoteRepositories( ArtifactRepository repository, + List<RemoteRepository> repositories ) + { + if ( repository instanceof RemoteRepository ) + { + return Collections.singletonList( (RemoteRepository) repository ); + } + if ( repository != null ) + { + return Collections.emptyList(); + } + return repositories; + } + + 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 RepositorySystemSession optimizeSession( RepositorySystemSession session ) + { + DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession( session ); + optimized.setArtifactTypeRegistry( CachingArtifactTypeRegistry.newInstance( session ) ); + return optimized; + } + + static String getId( Dependency d ) + { + Artifact a = d.getArtifact(); + return a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getClassifier() + ':' + a.getExtension(); + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyContext.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyContext.java new file mode 100644 index 0000000..48af70f --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyContext.java @@ -0,0 +1,74 @@ +package org.eclipse.aether.internal.impl.collect; + +/* + * 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.Collections; +import java.util.List; +import java.util.concurrent.Future; + +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.resolution.ArtifactDescriptorResult; +import org.eclipse.aether.resolution.VersionRangeResult; +import org.eclipse.aether.version.Version; + +class DependencyContext +{ + Dependency origDependency; + + DefaultDependencyCollectionContext context; + + List<Artifact> relocations; + + boolean disableVersionManagement; + + Args args; + + PremanagedDependency preManaged; + + boolean traverse; + + VersionRangeResult rangeResult; + + Version version; + + Artifact originalArtifact; + + Dependency managedDependency; + + Future<ArtifactDescriptorResult> futureDescriptorResult; + + ArtifactDescriptorResult descriptorResult; + + DependencyContext() + { + // empty + } + + DependencyContext( DefaultDependencyCollectionContext context, Dependency dependency ) + { + this.context = context; + this.origDependency = dependency; + this.relocations = Collections.emptyList(); + this.disableVersionManagement = false; + this.args = context.getArgs(); + } + +} \ No newline at end of file diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java new file mode 100644 index 0000000..222cfe3 --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java @@ -0,0 +1,148 @@ +package org.eclipse.aether.internal.impl.collect; + +/* + * 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.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.DependencyManagement; +import org.eclipse.aether.collection.DependencyManager; +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.util.graph.manager.DependencyManagerUtils; + +class PremanagedDependency +{ + final String premanagedVersion; + + final String premanagedScope; + + final Boolean premanagedOptional; + + /** + * @since 1.4.0 + */ + final Collection<Exclusion> premanagedExclusions; + + /** + * @since 1.4.0 + */ + final Map<String, String> premanagedProperties; + + final int managedBits; + + final Dependency managedDependency; + + final boolean premanagedState; + + 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 ); + } + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/Results.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/Results.java new file mode 100644 index 0000000..2d27c9d --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/Results.java @@ -0,0 +1,83 @@ +package org.eclipse.aether.internal.impl.collect; + +/* + * 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 org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.util.ConfigUtils; + +class Results +{ + + private final CollectResult result; + + private final int maxExceptions; + + private final int maxCycles; + + String errorPath; + + Results( CollectResult result, RepositorySystemSession session ) + { + this.result = result; + maxExceptions = ConfigUtils.getInteger( session, 50, DefaultDependencyCollector.CONFIG_PROP_MAX_EXCEPTIONS ); + maxCycles = ConfigUtils.getInteger( session, 10, DefaultDependencyCollector.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 ) ); + } + } + +} \ No newline at end of file diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java index 6b26f33..2ac1855 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java @@ -18,8 +18,11 @@ package org.eclipse.aether.internal.impl.collect; * specific language governing permissions and limitations * under the License. */ +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.artifact.DefaultArtifact; @@ -27,6 +30,7 @@ import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.resolution.ArtifactDescriptorRequest; import org.eclipse.aether.resolution.ArtifactDescriptorResult; +import org.eclipse.aether.util.concurrency.FutureResult; import org.junit.Test; public class DataPoolTest @@ -38,7 +42,7 @@ public class DataPoolTest } @Test - public void testArtifactDescriptorCaching() + public void testArtifactDescriptorCaching() throws InterruptedException, ExecutionException { ArtifactDescriptorRequest request = new ArtifactDescriptorRequest(); request.setArtifact( new DefaultArtifact( "gid:aid:1" ) ); @@ -49,12 +53,14 @@ public class DataPoolTest result.addManagedDependency( new Dependency( new DefaultArtifact( "gid:mdep:3" ), "runtime" ) ); result.addRepository( new RemoteRepository.Builder( "test", "default", "http://localhost" ).build() ); result.addAlias( new DefaultArtifact( "gid:alias:4" ) ); + Future<ArtifactDescriptorResult> futureResult = new FutureResult<>( result ); DataPool pool = newDataPool(); Object key = pool.toKey( request ); - pool.putDescriptor( key, result ); - ArtifactDescriptorResult cached = pool.getDescriptor( key, request ); - assertNotNull( cached ); + pool.putDescriptor( key, futureResult ); + Future<ArtifactDescriptorResult> futureCached = pool.getDescriptor( key, request ); + assertNotNull( futureCached ); + ArtifactDescriptorResult cached = futureCached.get(); assertEquals( result.getArtifact(), cached.getArtifact() ); assertEquals( result.getRelocations(), cached.getRelocations() ); assertEquals( result.getDependencies(), cached.getDependencies() ); diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java index 0e2d644..94c504e 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java @@ -8,9 +8,9 @@ package org.eclipse.aether.internal.impl.collect; * 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 @@ -18,8 +18,12 @@ package org.eclipse.aether.internal.impl.collect; * specific language governing permissions and limitations * under the License. */ - -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.IOException; import java.util.ArrayList; @@ -60,6 +64,7 @@ import org.eclipse.aether.resolution.ArtifactDescriptorResult; import org.eclipse.aether.util.artifact.ArtifactIdUtils; import org.eclipse.aether.util.graph.manager.ClassicDependencyManager; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.selector.ScopeDependencySelector; import org.eclipse.aether.util.graph.version.HighestVersionFilter; import org.junit.Before; import org.junit.Test; @@ -492,6 +497,44 @@ public class DefaultDependencyCollectorTest assertEquals( 1, result.getRoot().getChildren().size() ); } + /** + * Tests that scope based dependency selection happens before dependency management. + * <p> + * This is not really correct (see MRESOLVER-9), but there are a number of tests + * in the Maven and Maven Integration Testing projects that currently rely on this + * behaviour. + */ + @Test + public void testSelectionBeforeManagement() + throws IOException, DependencyCollectionException + { + session.setDependencySelector( new ScopeDependencySelector( "provided", "test" ) ); + session.setDependencyManager( new ClassicDependencyManager() ); + + Dependency dependency = newDep( "gid3:aid1:ext:1", "compile" ); + CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) ); + CollectResult result = collector.collectDependencies( session, request ); + + assertEquals( 0, result.getExceptions().size() ); + + DependencyNode root = result.getRoot(); + Dependency newDependency = root.getDependency(); + + assertEquals( dependency, newDependency ); + assertEquals( dependency.getArtifact(), newDependency.getArtifact() ); + + assertEquals( 1, root.getChildren().size() ); + + Dependency expect = newDep( "gid3:aid2:ext:1", "compile" ); + DependencyNode childLevel1 = root.getChildren().get( 0 ); + assertEquals( expect, childLevel1.getDependency() ); + + // With proper dependency management, the test scope of aid3 would + // be managed to compile, and we would get another child. + // Currently, the dependency gets filtered by ScopeDependencyManager. + assertEquals( 0, childLevel1.getChildren().size() ); + } + static class TestDependencyManager implements DependencyManager { diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid1_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid1_1.ini new file mode 100644 index 0000000..ffc6dbd --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid1_1.ini @@ -0,0 +1,7 @@ +[dependencies] +gid3:aid2:ext:1:compile + +[managed-dependencies] +gid3:aid3:ext:1:compile:!optional + + diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid2_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid2_1.ini new file mode 100644 index 0000000..8d64166 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid2_1.ini @@ -0,0 +1,2 @@ +[dependencies] +gid3:aid3:ext:2:test:optional diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid3_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid3_1.ini new file mode 100644 index 0000000..4322fc6 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid3_1.ini @@ -0,0 +1,2 @@ +[dependencies] + diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid3_2.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid3_2.ini new file mode 100644 index 0000000..4322fc6 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/gid3_aid3_2.ini @@ -0,0 +1,2 @@ +[dependencies] + diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/concurrency/FutureResult.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/concurrency/FutureResult.java new file mode 100644 index 0000000..dbbe1df --- /dev/null +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/concurrency/FutureResult.java @@ -0,0 +1,69 @@ +package org.eclipse.aether.util.concurrency; + +/* + * 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.concurrent.Future; +import java.util.concurrent.TimeUnit; + +/** + * Wraps a result value as a Future. + * + * @param <T> result type + */ +public class FutureResult<T> + implements Future<T> +{ + private final T value; + + public FutureResult( T value ) + { + this.value = value; + } + + @Override + public boolean cancel( boolean mayInterruptIfRunning ) + { + return false; + } + + @Override + public boolean isCancelled() + { + return false; + } + + @Override + public boolean isDone() + { + return true; + } + + @Override + public T get() + { + return value; + } + + @Override + public T get( long timeout, TimeUnit unit ) + { + return value; + } +}
