Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.eclipse.aether.impl;

/*
* 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.graph.DependencyNode;

import java.util.List;

/**
* A skipper that determines whether to skip resolving given node during the dependency collection.
*
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
* @provisional This type is provisional and can be changed, moved or removed without prior notice.
* @since 1.8.0
*/
public interface DependencyResolutionSkipper
{
/**
* Check whether the resolution of current node can be skipped before resolving.
*
* @param node Current node
* @param parents All parent nodes of current node
*
* @return {@code true} if the node can be skipped for resolution, {@code false} if resolution required.
*/
boolean skipResolution( DependencyNode node, List<DependencyNode> parents );

/**
* Cache the resolution result when a node is resolved by @See DependencyCollector after resolution.
*
* @param node Current node
* @param parents All parent nodes of current node
*/
void cache( DependencyNode node, List<DependencyNode> parents );

/**
* Print the skip/resolve status report for all nodes.
*/
void report();

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.impl.ArtifactDescriptorReader;
import org.eclipse.aether.impl.DependencyCollector;
import org.eclipse.aether.impl.DependencyResolutionSkipper;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.impl.VersionRangeResolver;
import org.eclipse.aether.repository.ArtifactRepository;
Expand Down Expand Up @@ -85,6 +86,21 @@ public class DefaultDependencyCollector
implements DependencyCollector, Service
{

/**
* The key in the repository session's {@link org.eclipse.aether.RepositorySystemSession#getConfigProperties()
* configuration properties} used to store a {@link Boolean} flag controlling the resolver's skip mode.
*
* @since 1.8.0
*/
public static final String CONFIG_PROP_USE_SKIP = "aether.dependencyCollector.useSkip";

/**
* The default value for {@link #CONFIG_PROP_USE_SKIP}, {@code true}.
*
* @since 1.8.0
*/
public static final boolean CONFIG_PROP_USE_SKIP_DEFAULT = true;

private static final String CONFIG_PROP_MAX_EXCEPTIONS = "aether.dependencyCollector.maxExceptions";

private static final int CONFIG_PROP_MAX_EXCEPTIONS_DEFAULT = 50;
Expand Down Expand Up @@ -151,6 +167,14 @@ public CollectResult collectDependencies( RepositorySystemSession session, Colle
requireNonNull( request, "request cannot be null" );
session = optimizeSession( session );

boolean useSkip = ConfigUtils.getBoolean(
session, CONFIG_PROP_USE_SKIP_DEFAULT, CONFIG_PROP_USE_SKIP
);
if ( useSkip )
{
LOGGER.debug( "Collector skip mode enabled" );
}

RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );

CollectResult result = new CollectResult( request );
Expand Down Expand Up @@ -253,7 +277,10 @@ public CollectResult collectDependencies( RepositorySystemSession session, Colle

DefaultVersionFilterContext versionContext = new DefaultVersionFilterContext( session );

Args args = new Args( session, trace, pool, context, versionContext, request );
Args args =
new Args( session, trace, pool, context, versionContext, request,
useSkip ? new DefaultDependencyResolutionSkipper()
: NeverDependencyResolutionSkipper.INSTANCE );
Results results = new Results( result, session );

DependencySelector rootDepSelector =
Expand All @@ -263,11 +290,12 @@ public CollectResult collectDependencies( RepositorySystemSession session, Colle
depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null;
VersionFilter rootVerFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null;

List<DependencyNode> parents = Collections.singletonList( node );
for ( Dependency dependency : dependencies )
{
args.dependencyProcessingQueue.add(
new DependencyProcessingContext( rootDepSelector, rootDepManager, rootDepTraverser,
rootVerFilter, repositories, managedDependencies, Collections.singletonList( node ),
rootVerFilter, repositories, managedDependencies, parents,
dependency ) );
}

Expand All @@ -277,6 +305,7 @@ public CollectResult collectDependencies( RepositorySystemSession session, Colle
false );
}

args.skipper.report();
errorPath = results.errorPath;
}

Expand Down Expand Up @@ -396,6 +425,8 @@ private void processDependency( Args args, Results results, DependencyProcessing
return;
}

//Resolve newer version first to maximize benefits of skipper
Collections.reverse( versions );
for ( Version version : versions )
{
Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() );
Expand Down Expand Up @@ -500,15 +531,20 @@ private void doRecurse( Args args, DependencyProcessingContext parentContext,
List<DependencyNode> children = args.pool.getChildren( key );
if ( children == null )
{
args.pool.putChildren( key, child.getChildren() );

List<DependencyNode> parents = new ArrayList<>( parentContext.parents );
parents.add( child );
for ( Dependency dependency : descriptorResult.getDependencies() )
boolean skipResolution = args.skipper.skipResolution( child, parentContext.parents );
if ( !skipResolution )
{
args.dependencyProcessingQueue.add(
new DependencyProcessingContext( childSelector, childManager, childTraverser, childFilter,
childRepos, descriptorResult.getManagedDependencies(), parents, dependency ) );
List<DependencyNode> parents = new ArrayList<>( parentContext.parents.size() + 1 );
parents.addAll( parentContext.parents );
parents.add( child );
for ( Dependency dependency : descriptorResult.getDependencies() )
{
args.dependencyProcessingQueue.add(
new DependencyProcessingContext( childSelector, childManager, childTraverser, childFilter,
childRepos, descriptorResult.getManagedDependencies(), parents, dependency ) );
}
args.pool.putChildren( key, child.getChildren() );
args.skipper.cache( child, parents );
}
}
else
Expand Down Expand Up @@ -689,17 +725,19 @@ static class Args

final DataPool pool;

final Queue<DependencyProcessingContext> dependencyProcessingQueue = new ArrayDeque<>();
final Queue<DependencyProcessingContext> dependencyProcessingQueue = new ArrayDeque<>( 128 );

final DefaultDependencyCollectionContext collectionContext;

final DefaultVersionFilterContext versionContext;

final CollectRequest request;

final DependencyResolutionSkipper skipper;

Args( RepositorySystemSession session, RequestTrace trace, DataPool pool,
DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext,
CollectRequest request )
CollectRequest request, DependencyResolutionSkipper skipper )
{
this.session = session;
this.request = request;
Expand All @@ -709,6 +747,7 @@ static class Args
this.pool = pool;
this.collectionContext = collectionContext;
this.versionContext = versionContext;
this.skipper = skipper;
}

}
Expand Down
Loading