You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sc...@apache.org on 2016/07/02 16:09:53 UTC
[2/2] maven-aether git commit: Feature: Updated class
'JavaDependencyMediator' to become a very simple but complete replacement for
the 'ConflictResolver'. In addition to the nearest node wins strategy,
this implementation supports scop
Feature: Updated class 'JavaDependencyMediator' to become a very simple but
complete replacement for the 'ConflictResolver'. In addition to the
nearest node wins strategy, this implementation supports scope
priorities. Currently the priorities are hard-coded to (from highest
to lowest): system, compile, runtime, test, provided. This may be
changed in the future to allow for different priorities based on the
target classpath to transform the graph to. So that when transforming
to a test classpath the test scope gets higher priority than the
compile scope. See MNG-5988.
Project: http://git-wip-us.apache.org/repos/asf/maven-aether/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-aether/commit/5b69d98e
Tree: http://git-wip-us.apache.org/repos/asf/maven-aether/tree/5b69d98e
Diff: http://git-wip-us.apache.org/repos/asf/maven-aether/diff/5b69d98e
Branch: refs/heads/master
Commit: 5b69d98e7bce7e49e1af031db59990f22d91526b
Parents: 0a82c39
Author: Christian Schulte <sc...@apache.org>
Authored: Sat Jul 2 17:14:33 2016 +0200
Committer: Christian Schulte <sc...@apache.org>
Committed: Sat Jul 2 17:23:50 2016 +0200
----------------------------------------------------------------------
.../transformer/JavaDependencyMediator.java | 132 +++++++++++++++++--
1 file changed, 118 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/5b69d98e/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
index ae385e6..626fc5d 100644
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
+++ b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
@@ -19,7 +19,10 @@ package org.eclipse.aether.util.graph.transformer;
* under the License.
*/
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import org.eclipse.aether.RepositoryException;
import org.eclipse.aether.collection.DependencyGraphTransformationContext;
@@ -43,10 +46,14 @@ public final class JavaDependencyMediator
final DependencyGraphTransformationContext context )
throws RepositoryException
{
- return this.recurse( node );
+ DependencyNode result = node;
+ result = this.removeNonTransitiveNodes( result );
+ result = this.updateTransitiveScopes( result );
+ result = this.removeDuplicateNodes( result, new HashMap<ConflictMarker.Key, DependencyNode>( 1024 ) );
+ return result;
}
- private DependencyNode recurse( final DependencyNode parent )
+ private DependencyNode removeNonTransitiveNodes( final DependencyNode parent )
{
final String parentScope = parent.getDependency() != null
? parent.getDependency().getScope() != null
@@ -58,8 +65,45 @@ public final class JavaDependencyMediator
for ( final Iterator<DependencyNode> it = parent.getChildren().iterator(); it.hasNext(); )
{
final DependencyNode child = it.next();
- boolean removed = false;
+ recurse:
+ {
+ if ( parentScope != null )
+ {
+ String childScope = child.getDependency().getScope() != null
+ && child.getDependency().getScope().length() >= 0
+ ? child.getDependency().getScope()
+ : JavaScopes.COMPILE;
+
+ // Provided and test scopes are non-transitive.
+ // Optional dependencies are non-transitive.
+ if ( JavaScopes.PROVIDED.equals( childScope )
+ || JavaScopes.TEST.equals( childScope )
+ || child.getDependency().isOptional() )
+ {
+ it.remove();
+ break recurse;
+ }
+ }
+
+ this.removeNonTransitiveNodes( child );
+ }
+ }
+
+ return parent;
+ }
+
+ private DependencyNode updateTransitiveScopes( final DependencyNode parent )
+ {
+ final String parentScope = parent.getDependency() != null
+ ? parent.getDependency().getScope() != null
+ && parent.getDependency().getScope().length() >= 0
+ ? parent.getDependency().getScope()
+ : JavaScopes.COMPILE
+ : null;
+
+ for ( final DependencyNode child : parent.getChildren() )
+ {
if ( parentScope != null )
{
String childScope = child.getDependency().getScope() != null
@@ -79,7 +123,7 @@ public final class JavaDependencyMediator
|| JavaScopes.RUNTIME.equals( childScope ) )
{
childScope = JavaScopes.PROVIDED;
- child.getDependency().setScope( childScope );
+ child.setScope( childScope );
}
}
else if ( JavaScopes.RUNTIME.equals( parentScope ) )
@@ -88,7 +132,7 @@ public final class JavaDependencyMediator
if ( JavaScopes.COMPILE.equals( childScope ) )
{
childScope = JavaScopes.RUNTIME;
- child.getDependency().setScope( childScope );
+ child.setScope( childScope );
}
}
else if ( JavaScopes.TEST.equals( parentScope ) )
@@ -98,27 +142,87 @@ public final class JavaDependencyMediator
|| JavaScopes.RUNTIME.equals( childScope ) )
{
childScope = JavaScopes.TEST;
- child.getDependency().setScope( childScope );
+ child.setScope( childScope );
}
}
}
+ }
+
+ this.updateTransitiveScopes( child );
+ }
- // Provided and test scopes are non-transitive.
- if ( JavaScopes.PROVIDED.equals( childScope )
- || JavaScopes.TEST.equals( childScope ) )
+ return parent;
+ }
+
+ private DependencyNode removeDuplicateNodes( final DependencyNode candidate,
+ final Map<ConflictMarker.Key, DependencyNode> nodes )
+ {
+ recurse:
+ {
+ if ( candidate.getDependency() != null )
+ {
+ final ConflictMarker.Key candidateKey = new ConflictMarker.Key( candidate.getArtifact() );
+ final DependencyNode existing = nodes.get( candidateKey );
+
+ if ( existing == null )
{
- it.remove();
- removed = true;
+ // Candidate is selected.
+ nodes.put( candidateKey, candidate );
+ }
+ else if ( this.isPreferredNode( existing, candidate ) )
+ {
+ // Candidate is selected.
+ nodes.put( candidateKey, candidate );
+ existing.getParent().getChildren().remove( existing );
+ }
+ else
+ {
+ // Candidate is not selected.
+ candidate.getParent().getChildren().remove( candidate );
+ // No need to inspect children.
+ break recurse;
}
}
- if ( !removed )
+ for ( final DependencyNode child : new ArrayList<DependencyNode>( candidate.getChildren() ) )
{
- this.recurse( child );
+ this.removeDuplicateNodes( child, nodes );
}
}
- return parent;
+ return candidate;
+ }
+
+ private boolean isPreferredNode( final DependencyNode existing, final DependencyNode candidate )
+ {
+ boolean preferred = false;
+ final Integer p1 = SCOPE_PRIORITIES.get( existing.getDependency().getScope() );
+ final Integer p2 = SCOPE_PRIORITIES.get( candidate.getDependency().getScope() );
+ final boolean candidateScopePrioritized = p1 != null && p2 != null ? p2 > p1 : false;
+ final boolean equalPriority = existing.getDependency().getScope().
+ equals( candidate.getDependency().getScope() );
+
+ if ( candidate.getDepth() < existing.getDepth() )
+ {
+ preferred = equalPriority || candidateScopePrioritized;
+ }
+ else if ( candidate.getDepth() == existing.getDepth() )
+ {
+ preferred = !equalPriority && candidateScopePrioritized;
+ }
+
+ return preferred;
+ }
+
+ private static final Map<String, Integer> SCOPE_PRIORITIES = new HashMap<String, Integer>();
+
+ static
+ {
+ SCOPE_PRIORITIES.put( JavaScopes.PROVIDED, 0 );
+ SCOPE_PRIORITIES.put( JavaScopes.TEST, 0 );
+ SCOPE_PRIORITIES.put( JavaScopes.RUNTIME, 1 );
+ SCOPE_PRIORITIES.put( JavaScopes.COMPILE, 2 );
+ SCOPE_PRIORITIES.put( JavaScopes.SYSTEM, 3 );
}
}