blob: d4a0ee0b47470529ea329ea9ff856feffddaa78a [file] [log] [blame]
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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
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;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.ArtifactProperties;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.DependencyCollectionException;
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.DependencyCycle;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.impl.ArtifactDescriptorReader;
import org.eclipse.aether.internal.impl.IniArtifactDescriptorReader;
import org.eclipse.aether.internal.impl.StubRemoteRepositoryManager;
import org.eclipse.aether.internal.impl.StubVersionRangeResolver;
import org.eclipse.aether.internal.test.util.DependencyGraphParser;
import org.eclipse.aether.internal.test.util.TestUtils;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorException;
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
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.DefaultDependencyManager;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.eclipse.aether.util.graph.version.HighestVersionFilter;
import org.junit.Before;
import org.junit.Test;
/**
*/
public class DefaultDependencyCollectorTest
{
private DefaultDependencyCollector collector;
private DefaultRepositorySystemSession session;
private DependencyGraphParser parser;
private RemoteRepository repository;
private IniArtifactDescriptorReader newReader( String prefix )
{
return new IniArtifactDescriptorReader( "artifact-descriptions/" + prefix );
}
private Dependency newDep( String coords )
{
return newDep( coords, "" );
}
private Dependency newDep( String coords, String scope )
{
return new Dependency( new DefaultArtifact( coords ), scope );
}
@Before
public void setup()
{
session = TestUtils.newSession();
collector = new DefaultDependencyCollector();
collector.setArtifactDescriptorReader( newReader( "" ) );
collector.setVersionRangeResolver( new StubVersionRangeResolver() );
collector.setRemoteRepositoryManager( new StubRemoteRepositoryManager() );
parser = new DependencyGraphParser( "artifact-descriptions/" );
repository = new RemoteRepository.Builder( "id", "default", "file:///" ).build();
}
private static void assertEqualSubtree( DependencyNode expected, DependencyNode actual )
{
assertEqualSubtree( expected, actual, new LinkedList<DependencyNode>() );
}
private static void assertEqualSubtree( DependencyNode expected, DependencyNode actual,
LinkedList<DependencyNode> parents )
{
assertEquals( "path: " + parents, expected.getDependency(), actual.getDependency() );
if ( actual.getDependency() != null )
{
Artifact artifact = actual.getDependency().getArtifact();
for ( DependencyNode parent : parents )
{
if ( parent.getDependency() != null && artifact.equals( parent.getDependency().getArtifact() ) )
{
return;
}
}
}
parents.addLast( expected );
assertEquals( "path: " + parents + ", expected: " + expected.getChildren() + ", actual: "
+ actual.getChildren(), expected.getChildren().size(), actual.getChildren().size() );
Iterator<DependencyNode> iterator1 = expected.getChildren().iterator();
Iterator<DependencyNode> iterator2 = actual.getChildren().iterator();
while ( iterator1.hasNext() )
{
assertEqualSubtree( iterator1.next(), iterator2.next(), parents );
}
parents.removeLast();
}
private Dependency dep( DependencyNode root, int... coords )
{
return path( root, coords ).getDependency();
}
private DependencyNode path( DependencyNode root, int... coords )
{
try
{
DependencyNode node = root;
for ( int coord : coords )
{
node = node.getChildren().get( coord );
}
return node;
}
catch ( IndexOutOfBoundsException | NullPointerException e )
{
throw new IllegalArgumentException( "illegal coordinates for child", e );
}
}
@Test
public void testSimpleCollection()
throws DependencyCollectionException
{
Dependency dependency = newDep( "gid:aid:ext:ver", "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( "gid:aid2:ext:ver", "compile" );
assertEquals( expect, root.getChildren().get( 0 ).getDependency() );
}
@Test
public void testMissingDependencyDescription()
{
CollectRequest request =
new CollectRequest( newDep( "missing:description:ext:ver" ), Arrays.asList( repository ) );
try
{
collector.collectDependencies( session, request );
fail( "expected exception" );
}
catch ( DependencyCollectionException e )
{
CollectResult result = e.getResult();
assertSame( request, result.getRequest() );
assertNotNull( result.getExceptions() );
assertEquals( 1, result.getExceptions().size() );
assertTrue( result.getExceptions().get( 0 ) instanceof ArtifactDescriptorException );
assertEquals( request.getRoot(), result.getRoot().getDependency() );
}
}
@Test
public void testDuplicates()
throws DependencyCollectionException
{
Dependency dependency = newDep( "duplicate:transitive:ext:dependency" );
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( 2, root.getChildren().size() );
Dependency dep = newDep( "gid:aid:ext:ver", "compile" );
assertEquals( dep, dep( root, 0 ) );
dep = newDep( "gid:aid2:ext:ver", "compile" );
assertEquals( dep, dep( root, 1 ) );
assertEquals( dep, dep( root, 0, 0 ) );
assertEquals( dep( root, 1 ), dep( root, 0, 0 ) );
}
@Test
public void testEqualSubtree()
throws IOException, DependencyCollectionException
{
DependencyNode root = parser.parseResource( "expectedSubtreeComparisonResult.txt" );
Dependency dependency = root.getDependency();
CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );
CollectResult result = collector.collectDependencies( session, request );
assertEqualSubtree( root, result.getRoot() );
}
@Test
public void testCyclicDependencies()
throws Exception
{
DependencyNode root = parser.parseResource( "cycle.txt" );
CollectRequest request = new CollectRequest( root.getDependency(), Arrays.asList( repository ) );
CollectResult result = collector.collectDependencies( session, request );
assertEqualSubtree( root, result.getRoot() );
}
@Test
public void testCyclicDependenciesBig()
throws Exception
{
CollectRequest request = new CollectRequest( newDep( "1:2:pom:5.50-SNAPSHOT" ), Arrays.asList( repository ) );
collector.setArtifactDescriptorReader( newReader( "cycle-big/" ) );
CollectResult result = collector.collectDependencies( session, request );
assertNotNull( result.getRoot() );
// we only care about the performance here, this test must not hang or run out of mem
}
@Test
public void testCyclicProjects()
throws Exception
{
CollectRequest request = new CollectRequest( newDep( "test:a:2" ), Arrays.asList( repository ) );
collector.setArtifactDescriptorReader( newReader( "versionless-cycle/" ) );
CollectResult result = collector.collectDependencies( session, request );
DependencyNode root = result.getRoot();
DependencyNode a1 = path( root, 0, 0 );
assertEquals( "a", a1.getArtifact().getArtifactId() );
assertEquals( "1", a1.getArtifact().getVersion() );
for ( DependencyNode child : a1.getChildren() )
{
assertFalse( "1".equals( child.getArtifact().getVersion() ) );
}
assertEquals( 1, result.getCycles().size() );
DependencyCycle cycle = result.getCycles().get( 0 );
assertEquals( Arrays.asList(), cycle.getPrecedingDependencies() );
assertEquals( Arrays.asList( root.getDependency(), path( root, 0 ).getDependency(), a1.getDependency() ),
cycle.getCyclicDependencies() );
}
@Test
public void testCyclicProjects_ConsiderLabelOfRootlessGraph()
throws Exception
{
Dependency dep = newDep( "gid:aid:ver", "compile" );
CollectRequest request =
new CollectRequest().addDependency( dep ).addRepository( repository ).setRootArtifact( dep.getArtifact() );
CollectResult result = collector.collectDependencies( session, request );
DependencyNode root = result.getRoot();
DependencyNode a1 = root.getChildren().get( 0 );
assertEquals( "aid", a1.getArtifact().getArtifactId() );
assertEquals( "ver", a1.getArtifact().getVersion() );
DependencyNode a2 = a1.getChildren().get( 0 );
assertEquals( "aid2", a2.getArtifact().getArtifactId() );
assertEquals( "ver", a2.getArtifact().getVersion() );
assertEquals( 1, result.getCycles().size() );
DependencyCycle cycle = result.getCycles().get( 0 );
assertEquals( Arrays.asList(), cycle.getPrecedingDependencies() );
assertEquals( Arrays.asList( new Dependency( dep.getArtifact(), null ), a1.getDependency() ),
cycle.getCyclicDependencies() );
}
@Test
public void testPartialResultOnError()
throws IOException
{
DependencyNode root = parser.parseResource( "expectedPartialSubtreeOnError.txt" );
Dependency dependency = root.getDependency();
CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );
CollectResult result;
try
{
result = collector.collectDependencies( session, request );
fail( "expected exception " );
}
catch ( DependencyCollectionException e )
{
result = e.getResult();
assertSame( request, result.getRequest() );
assertNotNull( result.getExceptions() );
assertEquals( 1, result.getExceptions().size() );
assertTrue( result.getExceptions().get( 0 ) instanceof ArtifactDescriptorException );
assertEqualSubtree( root, result.getRoot() );
}
}
@Test
public void testCollectMultipleDependencies()
throws DependencyCollectionException
{
Dependency root1 = newDep( "gid:aid:ext:ver", "compile" );
Dependency root2 = newDep( "gid:aid2:ext:ver", "compile" );
List<Dependency> dependencies = Arrays.asList( root1, root2 );
CollectRequest request = new CollectRequest( dependencies, null, Arrays.asList( repository ) );
CollectResult result = collector.collectDependencies( session, request );
assertEquals( 0, result.getExceptions().size() );
assertEquals( 2, result.getRoot().getChildren().size() );
assertEquals( root1, dep( result.getRoot(), 0 ) );
assertEquals( 1, path( result.getRoot(), 0 ).getChildren().size() );
assertEquals( root2, dep( result.getRoot(), 0, 0 ) );
assertEquals( 0, path( result.getRoot(), 1 ).getChildren().size() );
assertEquals( root2, dep( result.getRoot(), 1 ) );
}
@Test
public void testArtifactDescriptorResolutionNotRestrictedToRepoHostingSelectedVersion()
throws Exception
{
RemoteRepository repo2 = new RemoteRepository.Builder( "test", "default", "file:///" ).build();
final List<RemoteRepository> repos = new ArrayList<>();
collector.setArtifactDescriptorReader( new ArtifactDescriptorReader()
{
public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession session,
ArtifactDescriptorRequest request )
{
repos.addAll( request.getRepositories() );
return new ArtifactDescriptorResult( request );
}
} );
List<Dependency> dependencies = Arrays.asList( newDep( "verrange:parent:jar:1[1,)", "compile" ) );
CollectRequest request = new CollectRequest( dependencies, null, Arrays.asList( repository, repo2 ) );
CollectResult result = collector.collectDependencies( session, request );
assertEquals( 0, result.getExceptions().size() );
assertEquals( 2, repos.size() );
assertEquals( "id", repos.get( 0 ).getId() );
assertEquals( "test", repos.get( 1 ).getId() );
}
@Test
public void testManagedVersionScope()
throws DependencyCollectionException
{
Dependency dependency = newDep( "managed:aid:ext:ver" );
CollectRequest request = new CollectRequest( dependency, Arrays.asList( repository ) );
session.setDependencyManager( new ClassicDependencyManager() );
CollectResult result = collector.collectDependencies( session, request );
assertEquals( 0, result.getExceptions().size() );
DependencyNode root = result.getRoot();
assertEquals( dependency, dep( root ) );
assertEquals( dependency.getArtifact(), dep( root ).getArtifact() );
assertEquals( 1, root.getChildren().size() );
Dependency expect = newDep( "gid:aid:ext:ver", "compile" );
assertEquals( expect, dep( root, 0 ) );
assertEquals( 1, path( root, 0 ).getChildren().size() );
expect = newDep( "gid:aid2:ext:managedVersion", "managedScope" );
assertEquals( expect, dep( root, 0, 0 ) );
}
@Test
public void testDependencyManagement()
throws IOException, DependencyCollectionException
{
collector.setArtifactDescriptorReader( newReader( "managed/" ) );
DependencyNode root = parser.parseResource( "expectedSubtreeComparisonResult.txt" );
TestDependencyManager depMgmt = new TestDependencyManager();
depMgmt.add( dep( root, 0 ), "managed", null, null );
depMgmt.add( dep( root, 0, 1 ), "managed", "managed", null );
depMgmt.add( dep( root, 1 ), null, null, "managed" );
session.setDependencyManager( depMgmt );
// collect result will differ from expectedSubtreeComparisonResult.txt
// set localPath -> no dependency traversal
CollectRequest request = new CollectRequest( dep( root ), Arrays.asList( repository ) );
CollectResult result = collector.collectDependencies( session, request );
DependencyNode node = result.getRoot();
assertEquals( "managed", dep( node, 0, 1 ).getArtifact().getVersion() );
assertEquals( "managed", dep( node, 0, 1 ).getScope() );
assertEquals( "managed", dep( node, 1 ).getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) );
assertEquals( "managed", dep( node, 0, 0 ).getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) );
}
@Test
public void testDependencyManagement_VerboseMode()
throws Exception
{
String depId = "gid:aid2:ext";
TestDependencyManager depMgmt = new TestDependencyManager();
depMgmt.version( depId, "managedVersion" );
depMgmt.scope( depId, "managedScope" );
depMgmt.optional( depId, Boolean.TRUE );
depMgmt.path( depId, "managedPath" );
depMgmt.exclusions( depId, new Exclusion( "gid", "aid", "*", "*" ) );
session.setDependencyManager( depMgmt );
session.setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, Boolean.TRUE );
CollectRequest request = new CollectRequest().setRoot( newDep( "gid:aid:ver" ) );
CollectResult result = collector.collectDependencies( session, request );
DependencyNode node = result.getRoot().getChildren().get( 0 );
assertEquals( DependencyNode.MANAGED_VERSION | DependencyNode.MANAGED_SCOPE | DependencyNode.MANAGED_OPTIONAL
| DependencyNode.MANAGED_PROPERTIES | DependencyNode.MANAGED_EXCLUSIONS, node.getManagedBits() );
assertEquals( "ver", DependencyManagerUtils.getPremanagedVersion( node ) );
assertEquals( "compile", DependencyManagerUtils.getPremanagedScope( node ) );
assertEquals( Boolean.FALSE, DependencyManagerUtils.getPremanagedOptional( node ) );
}
@Test
public void testDependencyManagement_TransitiveDependencyManager()
throws DependencyCollectionException, IOException
{
collector.setArtifactDescriptorReader( newReader( "managed/" ) );
parser = new DependencyGraphParser( "artifact-descriptions/managed/" );
session.setDependencyManager( new TransitiveDependencyManager() );
final Dependency root = newDep( "gid:root:ext:ver", "compile" );
CollectRequest request = new CollectRequest( root, Collections.singletonList( repository ) );
request.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) );
CollectResult result = collector.collectDependencies( session, request );
final DependencyNode expectedTree = parser.parseResource( "management-tree.txt" );
assertEqualSubtree( expectedTree, result.getRoot() );
// Same test for root artifact (POM) request.
final CollectRequest rootArtifactRequest = new CollectRequest();
rootArtifactRequest.setRepositories( Collections.singletonList( repository ) );
rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) );
rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) );
rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) );
rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:must-retain-core-management" ) );
rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) );
session.setDependencyManager( new TransitiveDependencyManager() );
result = collector.collectDependencies( session, rootArtifactRequest );
assertEqualSubtree( expectedTree, toDependencyResult( result.getRoot(), "compile", null ) );
}
@Test
public void testDependencyManagement_DefaultDependencyManager()
throws DependencyCollectionException, IOException
{
collector.setArtifactDescriptorReader( newReader( "managed/" ) );
parser = new DependencyGraphParser( "artifact-descriptions/managed/" );
session.setDependencyManager( new DefaultDependencyManager() );
final Dependency root = newDep( "gid:root:ext:ver", "compile" );
CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) );
request.addManagedDependency( newDep( "gid:root:ext:must-not-manage-root" ) );
request.addManagedDependency( newDep( "gid:direct:ext:managed-by-dominant-request" ) );
CollectResult result = collector.collectDependencies( session, request );
final DependencyNode expectedTree = parser.parseResource( "default-management-tree.txt" );
assertEqualSubtree( expectedTree, result.getRoot() );
// Same test for root artifact (POM) request.
final CollectRequest rootArtifactRequest = new CollectRequest();
rootArtifactRequest.setRepositories( Arrays.asList( repository ) );
rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) );
rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) );
rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-not-manage-root" ) );
rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:managed-by-dominant-request" ) );
rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) );
session.setDependencyManager( new DefaultDependencyManager() );
result = collector.collectDependencies( session, rootArtifactRequest );
assertEqualSubtree( expectedTree, toDependencyResult( result.getRoot(), "compile", null ) );
}
private DependencyNode toDependencyResult( final DependencyNode root, final String rootScope,
final Boolean optional )
{
// Make the root artifact resultion result a dependency resolution result for the subtree check.
assertNull( "Expected root artifact resolution result.", root.getDependency() );
final DefaultDependencyNode defaultNode =
new DefaultDependencyNode( new Dependency( root.getArtifact(), rootScope ) );
defaultNode.setChildren( root.getChildren() );
if ( optional != null )
{
defaultNode.setOptional( optional );
}
return defaultNode;
}
@Test
public void testVersionFilter()
throws Exception
{
session.setVersionFilter( new HighestVersionFilter() );
CollectRequest request = new CollectRequest().setRoot( newDep( "gid:aid:1" ) );
CollectResult result = collector.collectDependencies( session, request );
assertEquals( 1, result.getRoot().getChildren().size() );
}
/**
* Tests that scope based dependency selection happens before dependency management.
*/
@Test
public void testSelectionBeforeManagement()
throws 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( 1, childLevel1.getChildren().size() );
}
static class TestDependencyManager
implements DependencyManager
{
private Map<String, String> versions = new HashMap<>();
private Map<String, String> scopes = new HashMap<>();
private Map<String, Boolean> optionals = new HashMap<>();
private Map<String, String> paths = new HashMap<>();
private Map<String, Collection<Exclusion>> exclusions = new HashMap<>();
public void add( Dependency d, String version, String scope, String localPath )
{
String id = toKey( d );
version( id, version );
scope( id, scope );
path( id, localPath );
}
public void version( String id, String version )
{
versions.put( id, version );
}
public void scope( String id, String scope )
{
scopes.put( id, scope );
}
public void optional( String id, Boolean optional )
{
optionals.put( id, optional );
}
public void path( String id, String path )
{
paths.put( id, path );
}
public void exclusions( String id, Exclusion... exclusions )
{
this.exclusions.put( id, exclusions != null ? Arrays.asList( exclusions ) : null );
}
public DependencyManagement manageDependency( Dependency d )
{
String id = toKey( d );
DependencyManagement mgmt = new DependencyManagement();
mgmt.setVersion( versions.get( id ) );
mgmt.setScope( scopes.get( id ) );
mgmt.setOptional( optionals.get( id ) );
String path = paths.get( id );
if ( path != null )
{
mgmt.setProperties( Collections.singletonMap( ArtifactProperties.LOCAL_PATH, path ) );
}
mgmt.setExclusions( exclusions.get( id ) );
return mgmt;
}
private String toKey( Dependency dependency )
{
return ArtifactIdUtils.toVersionlessId( dependency.getArtifact() );
}
public DependencyManager deriveChildManager( DependencyCollectionContext context )
{
return this;
}
}
}