You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2016/09/03 20:23:36 UTC
[13/51] [partial] maven-aether git commit: [MNG-6007] rename Aether
to Maven Artifact Resolver
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
deleted file mode 100644
index 6ccc508..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
+++ /dev/null
@@ -1,1327 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.collection.DependencyGraphTransformationContext;
-import org.eclipse.aether.collection.DependencyGraphTransformer;
-import org.eclipse.aether.graph.DefaultDependencyNode;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.ConfigUtils;
-
-/**
- * A dependency graph transformer that resolves version and scope conflicts among dependencies. For a given set of
- * conflicting nodes, one node will be chosen as the winner and the other nodes are removed from the dependency graph.
- * The exact rules by which a winning node and its effective scope are determined are controlled by user-supplied
- * implementations of {@link VersionSelector}, {@link ScopeSelector}, {@link OptionalitySelector} and
- * {@link ScopeDeriver}.
- * <p>
- * By default, this graph transformer will turn the dependency graph into a tree without duplicate artifacts. Using the
- * configuration property {@link #CONFIG_PROP_VERBOSE}, a verbose mode can be enabled where the graph is still turned
- * into a tree but all nodes participating in a conflict are retained. The nodes that were rejected during conflict
- * resolution have no children and link back to the winner node via the {@link #NODE_DATA_WINNER} key in their custom
- * data. Additionally, the keys {@link #NODE_DATA_ORIGINAL_SCOPE} and {@link #NODE_DATA_ORIGINAL_OPTIONALITY} are used
- * to store the original scope and optionality of each node. Obviously, the resulting dependency tree is not suitable
- * for artifact resolution unless a filter is employed to exclude the duplicate dependencies.
- * <p>
- * This transformer will query the keys {@link TransformationContextKeys#CONFLICT_IDS},
- * {@link TransformationContextKeys#SORTED_CONFLICT_IDS}, {@link TransformationContextKeys#CYCLIC_CONFLICT_IDS} for
- * existing information about conflict ids. In absence of this information, it will automatically invoke the
- * {@link ConflictIdSorter} to calculate it.
- */
-public final class ConflictResolver
- implements DependencyGraphTransformer
-{
-
- /**
- * The key in the repository session's {@link RepositorySystemSession#getConfigProperties() configuration
- * properties} used to store a {@link Boolean} flag controlling the transformer's verbose mode.
- */
- public static final String CONFIG_PROP_VERBOSE = "aether.conflictResolver.verbose";
-
- /**
- * The key in the dependency node's {@link DependencyNode#getData() custom data} under which a reference to the
- * {@link DependencyNode} which has won the conflict is stored.
- */
- public static final String NODE_DATA_WINNER = "conflict.winner";
-
- /**
- * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the scope of the
- * dependency before scope derivation and conflict resolution is stored.
- */
- public static final String NODE_DATA_ORIGINAL_SCOPE = "conflict.originalScope";
-
- /**
- * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the optional flag of
- * the dependency before derivation and conflict resolution is stored.
- */
- public static final String NODE_DATA_ORIGINAL_OPTIONALITY = "conflict.originalOptionality";
-
- private final VersionSelector versionSelector;
-
- private final ScopeSelector scopeSelector;
-
- private final ScopeDeriver scopeDeriver;
-
- private final OptionalitySelector optionalitySelector;
-
- /**
- * Creates a new conflict resolver instance with the specified hooks.
- *
- * @param versionSelector The version selector to use, must not be {@code null}.
- * @param scopeSelector The scope selector to use, must not be {@code null}.
- * @param optionalitySelector The optionality selector ot use, must not be {@code null}.
- * @param scopeDeriver The scope deriver to use, must not be {@code null}.
- */
- public ConflictResolver( VersionSelector versionSelector, ScopeSelector scopeSelector,
- OptionalitySelector optionalitySelector, ScopeDeriver scopeDeriver )
- {
- if ( versionSelector == null )
- {
- throw new IllegalArgumentException( "version selector not specified" );
- }
- this.versionSelector = versionSelector;
- if ( scopeSelector == null )
- {
- throw new IllegalArgumentException( "scope selector not specified" );
- }
- this.scopeSelector = scopeSelector;
- if ( scopeDeriver == null )
- {
- throw new IllegalArgumentException( "scope deriver not specified" );
- }
- this.scopeDeriver = scopeDeriver;
- if ( optionalitySelector == null )
- {
- throw new IllegalArgumentException( "optionality selector not specified" );
- }
- this.optionalitySelector = optionalitySelector;
- }
-
- public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- List<?> sortedConflictIds = (List<?>) context.get( TransformationContextKeys.SORTED_CONFLICT_IDS );
- if ( sortedConflictIds == null )
- {
- ConflictIdSorter sorter = new ConflictIdSorter();
- sorter.transformGraph( node, context );
-
- sortedConflictIds = (List<?>) context.get( TransformationContextKeys.SORTED_CONFLICT_IDS );
- }
-
- @SuppressWarnings( "unchecked" )
- Map<String, Object> stats = (Map<String, Object>) context.get( TransformationContextKeys.STATS );
- long time1 = System.nanoTime();
-
- @SuppressWarnings( "unchecked" )
- Collection<Collection<?>> conflictIdCycles =
- (Collection<Collection<?>>) context.get( TransformationContextKeys.CYCLIC_CONFLICT_IDS );
- if ( conflictIdCycles == null )
- {
- throw new RepositoryException( "conflict id cycles have not been identified" );
- }
-
- Map<?, ?> conflictIds = (Map<?, ?>) context.get( TransformationContextKeys.CONFLICT_IDS );
- if ( conflictIds == null )
- {
- throw new RepositoryException( "conflict groups have not been identified" );
- }
-
- Map<Object, Collection<Object>> cyclicPredecessors = new HashMap<Object, Collection<Object>>();
- for ( Collection<?> cycle : conflictIdCycles )
- {
- for ( Object conflictId : cycle )
- {
- Collection<Object> predecessors = cyclicPredecessors.get( conflictId );
- if ( predecessors == null )
- {
- predecessors = new HashSet<Object>();
- cyclicPredecessors.put( conflictId, predecessors );
- }
- predecessors.addAll( cycle );
- }
- }
-
- State state = new State( node, conflictIds, sortedConflictIds.size(), context );
- for ( Iterator<?> it = sortedConflictIds.iterator(); it.hasNext(); )
- {
- Object conflictId = it.next();
-
- // reset data structures for next graph walk
- state.prepare( conflictId, cyclicPredecessors.get( conflictId ) );
-
- // find nodes with the current conflict id and while walking the graph (more deeply), nuke leftover losers
- gatherConflictItems( node, state );
-
- // now that we know the min depth of the parents, update depth of conflict items
- state.finish();
-
- // earlier runs might have nuked all parents of the current conflict id, so it might not exist anymore
- if ( !state.items.isEmpty() )
- {
- ConflictContext ctx = state.conflictCtx;
- state.versionSelector.selectVersion( ctx );
- if ( ctx.winner == null )
- {
- throw new RepositoryException( "conflict resolver did not select winner among " + state.items );
- }
- DependencyNode winner = ctx.winner.node;
-
- state.scopeSelector.selectScope( ctx );
- if ( state.verbose )
- {
- winner.setData( NODE_DATA_ORIGINAL_SCOPE, winner.getDependency().getScope() );
- }
- winner.setScope( ctx.scope );
-
- state.optionalitySelector.selectOptionality( ctx );
- if ( state.verbose )
- {
- winner.setData( NODE_DATA_ORIGINAL_OPTIONALITY, winner.getDependency().isOptional() );
- }
- winner.setOptional( ctx.optional );
-
- removeLosers( state );
- }
-
- // record the winner so we can detect leftover losers during future graph walks
- state.winner();
-
- // in case of cycles, trigger final graph walk to ensure all leftover losers are gone
- if ( !it.hasNext() && !conflictIdCycles.isEmpty() && state.conflictCtx.winner != null )
- {
- DependencyNode winner = state.conflictCtx.winner.node;
- state.prepare( state, null );
- gatherConflictItems( winner, state );
- }
- }
-
- if ( stats != null )
- {
- long time2 = System.nanoTime();
- stats.put( "ConflictResolver.totalTime", time2 - time1 );
- stats.put( "ConflictResolver.conflictItemCount", state.totalConflictItems );
- }
-
- return node;
- }
-
- private boolean gatherConflictItems( DependencyNode node, State state )
- throws RepositoryException
- {
- Object conflictId = state.conflictIds.get( node );
- if ( state.currentId.equals( conflictId ) )
- {
- // found it, add conflict item (if not already done earlier by another path)
- state.add( node );
- // we don't recurse here so we might miss losers beneath us, those will be nuked during future walks below
- }
- else if ( state.loser( node, conflictId ) )
- {
- // found a leftover loser (likely in a cycle) of an already processed conflict id, tell caller to nuke it
- return false;
- }
- else if ( state.push( node, conflictId ) )
- {
- // found potential parent, no cycle and not visisted before with the same derived scope, so recurse
- for ( Iterator<DependencyNode> it = node.getChildren().iterator(); it.hasNext(); )
- {
- DependencyNode child = it.next();
- if ( !gatherConflictItems( child, state ) )
- {
- it.remove();
- }
- }
- state.pop();
- }
- return true;
- }
-
- private void removeLosers( State state )
- {
- ConflictItem winner = state.conflictCtx.winner;
- List<DependencyNode> previousParent = null;
- ListIterator<DependencyNode> childIt = null;
- boolean conflictVisualized = false;
- for ( ConflictItem item : state.items )
- {
- if ( item == winner )
- {
- continue;
- }
- if ( item.parent != previousParent )
- {
- childIt = item.parent.listIterator();
- previousParent = item.parent;
- conflictVisualized = false;
- }
- while ( childIt.hasNext() )
- {
- DependencyNode child = childIt.next();
- if ( child == item.node )
- {
- if ( state.verbose && !conflictVisualized && item.parent != winner.parent )
- {
- conflictVisualized = true;
- DependencyNode loser = new DefaultDependencyNode( child );
- loser.setData( NODE_DATA_WINNER, winner.node );
- loser.setData( NODE_DATA_ORIGINAL_SCOPE, loser.getDependency().getScope() );
- loser.setData( NODE_DATA_ORIGINAL_OPTIONALITY, loser.getDependency().isOptional() );
- loser.setScope( item.getScopes().iterator().next() );
- loser.setChildren( Collections.<DependencyNode>emptyList() );
- childIt.set( loser );
- }
- else
- {
- childIt.remove();
- }
- break;
- }
- }
- }
- // there might still be losers beneath the winner (e.g. in case of cycles)
- // those will be nuked during future graph walks when we include the winner in the recursion
- }
-
- static final class NodeInfo
- {
-
- /**
- * The smallest depth at which the node was seen, used for "the" depth of its conflict items.
- */
- int minDepth;
-
- /**
- * The set of derived scopes the node was visited with, used to check whether an already seen node needs to be
- * revisited again in context of another scope. To conserve memory, we start with {@code String} and update to
- * {@code Set<String>} if needed.
- */
- Object derivedScopes;
-
- /**
- * The set of derived optionalities the node was visited with, used to check whether an already seen node needs
- * to be revisited again in context of another optionality. To conserve memory, encoded as bit field (bit 0 ->
- * optional=false, bit 1 -> optional=true).
- */
- int derivedOptionalities;
-
- /**
- * The conflict items which are immediate children of the node, used to easily update those conflict items after
- * a new parent scope/optionality was encountered.
- */
- List<ConflictItem> children;
-
- static final int CHANGE_SCOPE = 0x01;
-
- static final int CHANGE_OPTIONAL = 0x02;
-
- private static final int OPT_FALSE = 0x01;
-
- private static final int OPT_TRUE = 0x02;
-
- NodeInfo( int depth, String derivedScope, boolean optional )
- {
- minDepth = depth;
- derivedScopes = derivedScope;
- derivedOptionalities = optional ? OPT_TRUE : OPT_FALSE;
- }
-
- @SuppressWarnings( "unchecked" )
- int update( int depth, String derivedScope, boolean optional )
- {
- if ( depth < minDepth )
- {
- minDepth = depth;
- }
- int changes;
- if ( derivedScopes.equals( derivedScope ) )
- {
- changes = 0;
- }
- else if ( derivedScopes instanceof Collection )
- {
- changes = ( (Collection<String>) derivedScopes ).add( derivedScope ) ? CHANGE_SCOPE : 0;
- }
- else
- {
- Collection<String> scopes = new HashSet<String>();
- scopes.add( (String) derivedScopes );
- scopes.add( derivedScope );
- derivedScopes = scopes;
- changes = CHANGE_SCOPE;
- }
- int bit = optional ? OPT_TRUE : OPT_FALSE;
- if ( ( derivedOptionalities & bit ) == 0 )
- {
- derivedOptionalities |= bit;
- changes |= CHANGE_OPTIONAL;
- }
- return changes;
- }
-
- void add( ConflictItem item )
- {
- if ( children == null )
- {
- children = new ArrayList<ConflictItem>( 1 );
- }
- children.add( item );
- }
-
- }
-
- final class State
- {
-
- /**
- * The conflict id currently processed.
- */
- Object currentId;
-
- /**
- * Stats counter.
- */
- int totalConflictItems;
-
- /**
- * Flag whether we should keep losers in the graph to enable visualization/troubleshooting of conflicts.
- */
- final boolean verbose;
-
- /**
- * A mapping from conflict id to winner node, helps to recognize nodes that have their effective
- * scope&optionality set or are leftovers from previous removals.
- */
- final Map<Object, DependencyNode> resolvedIds;
-
- /**
- * The set of conflict ids which could apply to ancestors of nodes with the current conflict id, used to avoid
- * recursion early on. This is basically a superset of the key set of resolvedIds, the additional ids account
- * for cyclic dependencies.
- */
- final Collection<Object> potentialAncestorIds;
-
- /**
- * The output from the conflict marker
- */
- final Map<?, ?> conflictIds;
-
- /**
- * The conflict items we have gathered so far for the current conflict id.
- */
- final List<ConflictItem> items;
-
- /**
- * The (conceptual) mapping from nodes to extra infos, technically keyed by the node's child list which better
- * captures the identity of a node since we're basically concerned with effects towards children.
- */
- final Map<List<DependencyNode>, NodeInfo> infos;
-
- /**
- * The set of nodes on the DFS stack to detect cycles, technically keyed by the node's child list to match the
- * dirty graph structure produced by the dependency collector for cycles.
- */
- final Map<List<DependencyNode>, Object> stack;
-
- /**
- * The stack of parent nodes.
- */
- final List<DependencyNode> parentNodes;
-
- /**
- * The stack of derived scopes for parent nodes.
- */
- final List<String> parentScopes;
-
- /**
- * The stack of derived optional flags for parent nodes.
- */
- final List<Boolean> parentOptionals;
-
- /**
- * The stack of node infos for parent nodes, may contain {@code null} which is used to disable creating new
- * conflict items when visiting their parent again (conflict items are meant to be unique by parent-node combo).
- */
- final List<NodeInfo> parentInfos;
-
- /**
- * The conflict context passed to the version/scope/optionality selectors, updated as we move along rather than
- * recreated to avoid tmp objects.
- */
- final ConflictContext conflictCtx;
-
- /**
- * The scope context passed to the scope deriver, updated as we move along rather than recreated to avoid tmp
- * objects.
- */
- final ScopeContext scopeCtx;
-
- /**
- * The effective version selector, i.e. after initialization.
- */
- final VersionSelector versionSelector;
-
- /**
- * The effective scope selector, i.e. after initialization.
- */
- final ScopeSelector scopeSelector;
-
- /**
- * The effective scope deriver, i.e. after initialization.
- */
- final ScopeDeriver scopeDeriver;
-
- /**
- * The effective optionality selector, i.e. after initialization.
- */
- final OptionalitySelector optionalitySelector;
-
- State( DependencyNode root, Map<?, ?> conflictIds, int conflictIdCount,
- DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- this.conflictIds = conflictIds;
- verbose = ConfigUtils.getBoolean( context.getSession(), false, CONFIG_PROP_VERBOSE );
- potentialAncestorIds = new HashSet<Object>( conflictIdCount * 2 );
- resolvedIds = new HashMap<Object, DependencyNode>( conflictIdCount * 2 );
- items = new ArrayList<ConflictItem>( 256 );
- infos = new IdentityHashMap<List<DependencyNode>, NodeInfo>( 64 );
- stack = new IdentityHashMap<List<DependencyNode>, Object>( 64 );
- parentNodes = new ArrayList<DependencyNode>( 64 );
- parentScopes = new ArrayList<String>( 64 );
- parentOptionals = new ArrayList<Boolean>( 64 );
- parentInfos = new ArrayList<NodeInfo>( 64 );
- conflictCtx = new ConflictContext( root, conflictIds, items );
- scopeCtx = new ScopeContext( null, null );
- versionSelector = ConflictResolver.this.versionSelector.getInstance( root, context );
- scopeSelector = ConflictResolver.this.scopeSelector.getInstance( root, context );
- scopeDeriver = ConflictResolver.this.scopeDeriver.getInstance( root, context );
- optionalitySelector = ConflictResolver.this.optionalitySelector.getInstance( root, context );
- }
-
- void prepare( Object conflictId, Collection<Object> cyclicPredecessors )
- {
- currentId = conflictCtx.conflictId = conflictId;
- conflictCtx.winner = null;
- conflictCtx.scope = null;
- conflictCtx.optional = null;
- items.clear();
- infos.clear();
- if ( cyclicPredecessors != null )
- {
- potentialAncestorIds.addAll( cyclicPredecessors );
- }
- }
-
- void finish()
- {
- List<DependencyNode> previousParent = null;
- int previousDepth = 0;
- totalConflictItems += items.size();
- for ( int i = items.size() - 1; i >= 0; i-- )
- {
- ConflictItem item = items.get( i );
- if ( item.parent == previousParent )
- {
- item.depth = previousDepth;
- }
- else if ( item.parent != null )
- {
- previousParent = item.parent;
- NodeInfo info = infos.get( previousParent );
- previousDepth = info.minDepth + 1;
- item.depth = previousDepth;
- }
- }
- potentialAncestorIds.add( currentId );
- }
-
- void winner()
- {
- resolvedIds.put( currentId, ( conflictCtx.winner != null ) ? conflictCtx.winner.node : null );
- }
-
- boolean loser( DependencyNode node, Object conflictId )
- {
- DependencyNode winner = resolvedIds.get( conflictId );
- return winner != null && winner != node;
- }
-
- boolean push( DependencyNode node, Object conflictId )
- throws RepositoryException
- {
- if ( conflictId == null )
- {
- if ( node.getDependency() != null )
- {
- if ( node.getData().get( NODE_DATA_WINNER ) != null )
- {
- return false;
- }
- throw new RepositoryException( "missing conflict id for node " + node );
- }
- }
- else if ( !potentialAncestorIds.contains( conflictId ) )
- {
- return false;
- }
-
- List<DependencyNode> graphNode = node.getChildren();
- if ( stack.put( graphNode, Boolean.TRUE ) != null )
- {
- return false;
- }
-
- int depth = depth();
- String scope = deriveScope( node, conflictId );
- boolean optional = deriveOptional( node, conflictId );
- NodeInfo info = infos.get( graphNode );
- if ( info == null )
- {
- info = new NodeInfo( depth, scope, optional );
- infos.put( graphNode, info );
- parentInfos.add( info );
- parentNodes.add( node );
- parentScopes.add( scope );
- parentOptionals.add( optional );
- }
- else
- {
- int changes = info.update( depth, scope, optional );
- if ( changes == 0 )
- {
- stack.remove( graphNode );
- return false;
- }
- parentInfos.add( null ); // disable creating new conflict items, we update the existing ones below
- parentNodes.add( node );
- parentScopes.add( scope );
- parentOptionals.add( optional );
- if ( info.children != null )
- {
- if ( ( changes & NodeInfo.CHANGE_SCOPE ) != 0 )
- {
- for ( int i = info.children.size() - 1; i >= 0; i-- )
- {
- ConflictItem item = info.children.get( i );
- String childScope = deriveScope( item.node, null );
- item.addScope( childScope );
- }
- }
- if ( ( changes & NodeInfo.CHANGE_OPTIONAL ) != 0 )
- {
- for ( int i = info.children.size() - 1; i >= 0; i-- )
- {
- ConflictItem item = info.children.get( i );
- boolean childOptional = deriveOptional( item.node, null );
- item.addOptional( childOptional );
- }
- }
- }
- }
-
- return true;
- }
-
- void pop()
- {
- int last = parentInfos.size() - 1;
- parentInfos.remove( last );
- parentScopes.remove( last );
- parentOptionals.remove( last );
- DependencyNode node = parentNodes.remove( last );
- stack.remove( node.getChildren() );
- }
-
- void add( DependencyNode node )
- throws RepositoryException
- {
- DependencyNode parent = parent();
- if ( parent == null )
- {
- ConflictItem item = newConflictItem( parent, node );
- items.add( item );
- }
- else
- {
- NodeInfo info = parentInfos.get( parentInfos.size() - 1 );
- if ( info != null )
- {
- ConflictItem item = newConflictItem( parent, node );
- info.add( item );
- items.add( item );
- }
- }
- }
-
- private ConflictItem newConflictItem( DependencyNode parent, DependencyNode node )
- throws RepositoryException
- {
- return new ConflictItem( parent, node, deriveScope( node, null ), deriveOptional( node, null ) );
- }
-
- private int depth()
- {
- return parentNodes.size();
- }
-
- private DependencyNode parent()
- {
- int size = parentNodes.size();
- return ( size <= 0 ) ? null : parentNodes.get( size - 1 );
- }
-
- private String deriveScope( DependencyNode node, Object conflictId )
- throws RepositoryException
- {
- if ( ( node.getManagedBits() & DependencyNode.MANAGED_SCOPE ) != 0
- || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
- {
- return scope( node.getDependency() );
- }
-
- int depth = parentNodes.size();
- scopes( depth, node.getDependency() );
- if ( depth > 0 )
- {
- scopeDeriver.deriveScope( scopeCtx );
- }
- return scopeCtx.derivedScope;
- }
-
- private void scopes( int parent, Dependency child )
- {
- scopeCtx.parentScope = ( parent > 0 ) ? parentScopes.get( parent - 1 ) : null;
- scopeCtx.derivedScope = scopeCtx.childScope = scope( child );
- }
-
- private String scope( Dependency dependency )
- {
- return ( dependency != null ) ? dependency.getScope() : null;
- }
-
- private boolean deriveOptional( DependencyNode node, Object conflictId )
- {
- Dependency dep = node.getDependency();
- boolean optional = ( dep != null ) ? dep.isOptional() : false;
- if ( optional || ( node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL ) != 0
- || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
- {
- return optional;
- }
- int depth = parentNodes.size();
- return ( depth > 0 ) ? parentOptionals.get( depth - 1 ) : false;
- }
-
- }
-
- /**
- * A context used to hold information that is relevant for deriving the scope of a child dependency.
- *
- * @see ScopeDeriver
- * @noinstantiate This class is not intended to be instantiated by clients in production code, the constructor may
- * change without notice and only exists to enable unit testing.
- */
- public static final class ScopeContext
- {
-
- String parentScope;
-
- String childScope;
-
- String derivedScope;
-
- /**
- * Creates a new scope context with the specified properties.
- *
- * @param parentScope The scope of the parent dependency, may be {@code null}.
- * @param childScope The scope of the child dependency, may be {@code null}.
- * @noreference This class is not intended to be instantiated by clients in production code, the constructor may
- * change without notice and only exists to enable unit testing.
- */
- public ScopeContext( String parentScope, String childScope )
- {
- this.parentScope = ( parentScope != null ) ? parentScope : "";
- derivedScope = this.childScope = ( childScope != null ) ? childScope : "";
- }
-
- /**
- * Gets the scope of the parent dependency. This is usually the scope that was derived by earlier invocations of
- * the scope deriver.
- *
- * @return The scope of the parent dependency, never {@code null}.
- */
- public String getParentScope()
- {
- return parentScope;
- }
-
- /**
- * Gets the original scope of the child dependency. This is the scope that was declared in the artifact
- * descriptor of the parent dependency.
- *
- * @return The original scope of the child dependency, never {@code null}.
- */
- public String getChildScope()
- {
- return childScope;
- }
-
- /**
- * Gets the derived scope of the child dependency. This is initially equal to {@link #getChildScope()} until the
- * scope deriver makes changes.
- *
- * @return The derived scope of the child dependency, never {@code null}.
- */
- public String getDerivedScope()
- {
- return derivedScope;
- }
-
- /**
- * Sets the derived scope of the child dependency.
- *
- * @param derivedScope The derived scope of the dependency, may be {@code null}.
- */
- public void setDerivedScope( String derivedScope )
- {
- this.derivedScope = ( derivedScope != null ) ? derivedScope : "";
- }
-
- }
-
- /**
- * A conflicting dependency.
- *
- * @noinstantiate This class is not intended to be instantiated by clients in production code, the constructor may
- * change without notice and only exists to enable unit testing.
- */
- public static final class ConflictItem
- {
-
- // nodes can share child lists, we care about the unique owner of a child node which is the child list
- final List<DependencyNode> parent;
-
- // only for debugging/toString() to help identify the parent node(s)
- final Artifact artifact;
-
- final DependencyNode node;
-
- int depth;
-
- // we start with String and update to Set<String> if needed
- Object scopes;
-
- // bit field of OPTIONAL_FALSE and OPTIONAL_TRUE
- int optionalities;
-
- /**
- * Bit flag indicating whether one or more paths consider the dependency non-optional.
- */
- public static final int OPTIONAL_FALSE = 0x01;
-
- /**
- * Bit flag indicating whether one or more paths consider the dependency optional.
- */
- public static final int OPTIONAL_TRUE = 0x02;
-
- ConflictItem( DependencyNode parent, DependencyNode node, String scope, boolean optional )
- {
- if ( parent != null )
- {
- this.parent = parent.getChildren();
- this.artifact = parent.getArtifact();
- }
- else
- {
- this.parent = null;
- this.artifact = null;
- }
- this.node = node;
- this.scopes = scope;
- this.optionalities = optional ? OPTIONAL_TRUE : OPTIONAL_FALSE;
- }
-
- /**
- * Creates a new conflict item with the specified properties.
- *
- * @param parent The parent node of the conflicting dependency, may be {@code null}.
- * @param node The conflicting dependency, must not be {@code null}.
- * @param depth The zero-based depth of the conflicting dependency.
- * @param optionalities The optionalities the dependency was encountered with, encoded as a bit field consisting
- * of {@link ConflictResolver.ConflictItem#OPTIONAL_TRUE} and
- * {@link ConflictResolver.ConflictItem#OPTIONAL_FALSE}.
- * @param scopes The derived scopes of the conflicting dependency, must not be {@code null}.
- * @noreference This class is not intended to be instantiated by clients in production code, the constructor may
- * change without notice and only exists to enable unit testing.
- */
- public ConflictItem( DependencyNode parent, DependencyNode node, int depth, int optionalities, String... scopes )
- {
- this.parent = ( parent != null ) ? parent.getChildren() : null;
- this.artifact = ( parent != null ) ? parent.getArtifact() : null;
- this.node = node;
- this.depth = depth;
- this.optionalities = optionalities;
- this.scopes = Arrays.asList( scopes );
- }
-
- /**
- * Determines whether the specified conflict item is a sibling of this item.
- *
- * @param item The other conflict item, must not be {@code null}.
- * @return {@code true} if the given item has the same parent as this item, {@code false} otherwise.
- */
- public boolean isSibling( ConflictItem item )
- {
- return parent == item.parent;
- }
-
- /**
- * Gets the dependency node involved in the conflict.
- *
- * @return The involved dependency node, never {@code null}.
- */
- public DependencyNode getNode()
- {
- return node;
- }
-
- /**
- * Gets the dependency involved in the conflict, short for {@code getNode.getDependency()}.
- *
- * @return The involved dependency, never {@code null}.
- */
- public Dependency getDependency()
- {
- return node.getDependency();
- }
-
- /**
- * Gets the zero-based depth at which the conflicting node occurs in the graph. As such, the depth denotes the
- * number of parent nodes. If actually multiple paths lead to the node, the return value denotes the smallest
- * possible depth.
- *
- * @return The zero-based depth of the node in the graph.
- */
- public int getDepth()
- {
- return depth;
- }
-
- /**
- * Gets the derived scopes of the dependency. In general, the same dependency node could be reached via
- * different paths and each path might result in a different derived scope.
- *
- * @see ScopeDeriver
- * @return The (read-only) set of derived scopes of the dependency, never {@code null}.
- */
- @SuppressWarnings( "unchecked" )
- public Collection<String> getScopes()
- {
- if ( scopes instanceof String )
- {
- return Collections.singleton( (String) scopes );
- }
- return (Collection<String>) scopes;
- }
-
- @SuppressWarnings( "unchecked" )
- void addScope( String scope )
- {
- if ( scopes instanceof Collection )
- {
- ( (Collection<String>) scopes ).add( scope );
- }
- else if ( !scopes.equals( scope ) )
- {
- Collection<Object> set = new HashSet<Object>();
- set.add( scopes );
- set.add( scope );
- scopes = set;
- }
- }
-
- /**
- * Gets the derived optionalities of the dependency. In general, the same dependency node could be reached via
- * different paths and each path might result in a different derived optionality.
- *
- * @return A bit field consisting of {@link ConflictResolver.ConflictItem#OPTIONAL_FALSE} and/or
- * {@link ConflictResolver.ConflictItem#OPTIONAL_TRUE} indicating the derived optionalities the
- * dependency was encountered with.
- */
- public int getOptionalities()
- {
- return optionalities;
- }
-
- void addOptional( boolean optional )
- {
- optionalities |= optional ? OPTIONAL_TRUE : OPTIONAL_FALSE;
- }
-
- @Override
- public String toString()
- {
- return node + " @ " + depth + " < " + artifact;
- }
-
- }
-
- /**
- * A context used to hold information that is relevant for resolving version and scope conflicts.
- *
- * @see VersionSelector
- * @see ScopeSelector
- * @noinstantiate This class is not intended to be instantiated by clients in production code, the constructor may
- * change without notice and only exists to enable unit testing.
- */
- public static final class ConflictContext
- {
-
- final DependencyNode root;
-
- final Map<?, ?> conflictIds;
-
- final Collection<ConflictItem> items;
-
- Object conflictId;
-
- ConflictItem winner;
-
- String scope;
-
- Boolean optional;
-
- ConflictContext( DependencyNode root, Map<?, ?> conflictIds, Collection<ConflictItem> items )
- {
- this.root = root;
- this.conflictIds = conflictIds;
- this.items = Collections.unmodifiableCollection( items );
- }
-
- /**
- * Creates a new conflict context.
- *
- * @param root The root node of the dependency graph, must not be {@code null}.
- * @param conflictId The conflict id for the set of conflicting dependencies in this context, must not be
- * {@code null}.
- * @param conflictIds The mapping from dependency node to conflict id, must not be {@code null}.
- * @param items The conflict items in this context, must not be {@code null}.
- * @noreference This class is not intended to be instantiated by clients in production code, the constructor may
- * change without notice and only exists to enable unit testing.
- */
- public ConflictContext( DependencyNode root, Object conflictId, Map<DependencyNode, Object> conflictIds,
- Collection<ConflictItem> items )
- {
- this( root, conflictIds, items );
- this.conflictId = conflictId;
- }
-
- /**
- * Gets the root node of the dependency graph being transformed.
- *
- * @return The root node of the dependeny graph, never {@code null}.
- */
- public DependencyNode getRoot()
- {
- return root;
- }
-
- /**
- * Determines whether the specified dependency node belongs to this conflict context.
- *
- * @param node The dependency node to check, must not be {@code null}.
- * @return {@code true} if the given node belongs to this conflict context, {@code false} otherwise.
- */
- public boolean isIncluded( DependencyNode node )
- {
- return conflictId.equals( conflictIds.get( node ) );
- }
-
- /**
- * Gets the collection of conflict items in this context.
- *
- * @return The (read-only) collection of conflict items in this context, never {@code null}.
- */
- public Collection<ConflictItem> getItems()
- {
- return items;
- }
-
- /**
- * Gets the conflict item which has been selected as the winner among the conflicting dependencies.
- *
- * @return The winning conflict item or {@code null} if not set yet.
- */
- public ConflictItem getWinner()
- {
- return winner;
- }
-
- /**
- * Sets the conflict item which has been selected as the winner among the conflicting dependencies.
- *
- * @param winner The winning conflict item, may be {@code null}.
- */
- public void setWinner( ConflictItem winner )
- {
- this.winner = winner;
- }
-
- /**
- * Gets the effective scope of the winning dependency.
- *
- * @return The effective scope of the winning dependency or {@code null} if none.
- */
- public String getScope()
- {
- return scope;
- }
-
- /**
- * Sets the effective scope of the winning dependency.
- *
- * @param scope The effective scope, may be {@code null}.
- */
- public void setScope( String scope )
- {
- this.scope = scope;
- }
-
- /**
- * Gets the effective optional flag of the winning dependency.
- *
- * @return The effective optional flag or {@code null} if none.
- */
- public Boolean getOptional()
- {
- return optional;
- }
-
- /**
- * Sets the effective optional flag of the winning dependency.
- *
- * @param optional The effective optional flag, may be {@code null}.
- */
- public void setOptional( Boolean optional )
- {
- this.optional = optional;
- }
-
- @Override
- public String toString()
- {
- return winner + " @ " + scope + " < " + items;
- }
-
- }
-
- /**
- * An extension point of {@link ConflictResolver} that determines the winner among conflicting dependencies. The
- * winning node (and its children) will be retained in the dependency graph, the other nodes will get removed. The
- * version selector does not need to deal with potential scope conflicts, these will be addressed afterwards by the
- * {@link ScopeSelector}.
- * <p>
- * <strong>Note:</strong> Implementations must be stateless.
- */
- public abstract static class VersionSelector
- {
-
- /**
- * Retrieves the version selector for use during the specified graph transformation. The conflict resolver calls
- * this method once per
- * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
- * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
- * implementations must be stateless, a new instance needs to be returned to hold such auxiliary data. The
- * default implementation simply returns the current instance which is appropriate for implementations which do
- * not require auxiliary data.
- *
- * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
- * @param context The graph transformation context, must not be {@code null}.
- * @return The scope deriver to use for the given graph transformation, never {@code null}.
- * @throws RepositoryException If the instance could not be retrieved.
- */
- public VersionSelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- return this;
- }
-
- /**
- * Determines the winning node among conflicting dependencies. Implementations will usually iterate
- * {@link ConflictContext#getItems()}, inspect {@link ConflictItem#getNode()} and eventually call
- * {@link ConflictContext#setWinner(ConflictResolver.ConflictItem)} to deliver the winner. Failure to select a
- * winner will automatically fail the entire conflict resolution.
- *
- * @param context The conflict context, must not be {@code null}.
- * @throws RepositoryException If the version selection failed.
- */
- public abstract void selectVersion( ConflictContext context )
- throws RepositoryException;
-
- }
-
- /**
- * An extension point of {@link ConflictResolver} that determines the effective scope of a dependency from a
- * potentially conflicting set of {@link ScopeDeriver derived scopes}. The scope selector gets invoked after the
- * {@link VersionSelector} has picked the winning node.
- * <p>
- * <strong>Note:</strong> Implementations must be stateless.
- */
- public abstract static class ScopeSelector
- {
-
- /**
- * Retrieves the scope selector for use during the specified graph transformation. The conflict resolver calls
- * this method once per
- * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
- * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
- * implementations must be stateless, a new instance needs to be returned to hold such auxiliary data. The
- * default implementation simply returns the current instance which is appropriate for implementations which do
- * not require auxiliary data.
- *
- * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
- * @param context The graph transformation context, must not be {@code null}.
- * @return The scope selector to use for the given graph transformation, never {@code null}.
- * @throws RepositoryException If the instance could not be retrieved.
- */
- public ScopeSelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- return this;
- }
-
- /**
- * Determines the effective scope of the dependency given by {@link ConflictContext#getWinner()}.
- * Implementations will usually iterate {@link ConflictContext#getItems()}, inspect
- * {@link ConflictItem#getScopes()} and eventually call {@link ConflictContext#setScope(String)} to deliver the
- * effective scope.
- *
- * @param context The conflict context, must not be {@code null}.
- * @throws RepositoryException If the scope selection failed.
- */
- public abstract void selectScope( ConflictContext context )
- throws RepositoryException;
-
- }
-
- /**
- * An extension point of {@link ConflictResolver} that determines the scope of a dependency in relation to the scope
- * of its parent.
- * <p>
- * <strong>Note:</strong> Implementations must be stateless.
- */
- public abstract static class ScopeDeriver
- {
-
- /**
- * Retrieves the scope deriver for use during the specified graph transformation. The conflict resolver calls
- * this method once per
- * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
- * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
- * implementations must be stateless, a new instance needs to be returned to hold such auxiliary data. The
- * default implementation simply returns the current instance which is appropriate for implementations which do
- * not require auxiliary data.
- *
- * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
- * @param context The graph transformation context, must not be {@code null}.
- * @return The scope deriver to use for the given graph transformation, never {@code null}.
- * @throws RepositoryException If the instance could not be retrieved.
- */
- public ScopeDeriver getInstance( DependencyNode root, DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- return this;
- }
-
- /**
- * Determines the scope of a dependency in relation to the scope of its parent. Implementors need to call
- * {@link ScopeContext#setDerivedScope(String)} to deliver the result of their calculation. If said method is
- * not invoked, the conflict resolver will assume the scope of the child dependency remains unchanged.
- *
- * @param context The scope context, must not be {@code null}.
- * @throws RepositoryException If the scope deriviation failed.
- */
- public abstract void deriveScope( ScopeContext context )
- throws RepositoryException;
-
- }
-
- /**
- * An extension point of {@link ConflictResolver} that determines the effective optional flag of a dependency from a
- * potentially conflicting set of derived optionalities. The optionality selector gets invoked after the
- * {@link VersionSelector} has picked the winning node.
- * <p>
- * <strong>Note:</strong> Implementations must be stateless.
- */
- public abstract static class OptionalitySelector
- {
-
- /**
- * Retrieves the optionality selector for use during the specified graph transformation. The conflict resolver
- * calls this method once per
- * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
- * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
- * implementations must be stateless, a new instance needs to be returned to hold such auxiliary data. The
- * default implementation simply returns the current instance which is appropriate for implementations which do
- * not require auxiliary data.
- *
- * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
- * @param context The graph transformation context, must not be {@code null}.
- * @return The optionality selector to use for the given graph transformation, never {@code null}.
- * @throws RepositoryException If the instance could not be retrieved.
- */
- public OptionalitySelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- return this;
- }
-
- /**
- * Determines the effective optional flag of the dependency given by {@link ConflictContext#getWinner()}.
- * Implementations will usually iterate {@link ConflictContext#getItems()}, inspect
- * {@link ConflictItem#getOptionalities()} and eventually call {@link ConflictContext#setOptional(Boolean)} to
- * deliver the effective optional flag.
- *
- * @param context The conflict context, must not be {@code null}.
- * @throws RepositoryException If the optionality selection failed.
- */
- public abstract void selectOptionality( ConflictContext context )
- throws RepositoryException;
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java
deleted file mode 100644
index d96e04e..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.RepositoryException;
-import org.eclipse.aether.collection.DependencyGraphTransformationContext;
-import org.eclipse.aether.collection.DependencyGraphTransformer;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.artifact.JavaScopes;
-
-/**
- * A dependency graph transformer that refines the request context for nodes that belong to the "project" context by
- * appending the classpath type to which the node belongs. For instance, a compile-time project dependency will be
- * assigned the request context "project/compile".
- *
- * @see DependencyNode#getRequestContext()
- */
-public final class JavaDependencyContextRefiner
- implements DependencyGraphTransformer
-{
-
- public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- String ctx = node.getRequestContext();
-
- if ( "project".equals( ctx ) )
- {
- String scope = getClasspathScope( node );
- if ( scope != null )
- {
- ctx += '/' + scope;
- node.setRequestContext( ctx );
- }
- }
-
- for ( DependencyNode child : node.getChildren() )
- {
- transformGraph( child, context );
- }
-
- return node;
- }
-
- private String getClasspathScope( DependencyNode node )
- {
- Dependency dependency = node.getDependency();
- if ( dependency == null )
- {
- return null;
- }
-
- String scope = dependency.getScope();
-
- if ( JavaScopes.COMPILE.equals( scope ) || JavaScopes.SYSTEM.equals( scope )
- || JavaScopes.PROVIDED.equals( scope ) )
- {
- return JavaScopes.COMPILE;
- }
- else if ( JavaScopes.RUNTIME.equals( scope ) )
- {
- return JavaScopes.RUNTIME;
- }
- else if ( JavaScopes.TEST.equals( scope ) )
- {
- return JavaScopes.TEST;
- }
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/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
deleted file mode 100644
index 441b6df..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
+++ /dev/null
@@ -1,389 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.collection.DependencyGraphTransformationContext;
-import org.eclipse.aether.collection.DependencyGraphTransformer;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.artifact.JavaScopes;
-
-/**
- * A {@code DependencyGraphTransformer} applying the Maven dependency mediation mechanism.
- *
- * @author Christian Schulte
- * @since 1.2
- * @see <a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">Introduction to the Dependency Mechanism</a>
- */
-public final class JavaDependencyMediator
- implements DependencyGraphTransformer
-{
-
- private static final Map<String, Integer> APPLICATION_SCOPE_PRIORITIES = new HashMap<String, Integer>( 5 );
-
- private static final Map<String, Integer> TEST_SCOPE_PRIORITIES = new HashMap<String, Integer>( 5 );
-
- static
- {
- APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.TEST, 0 );
- APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.RUNTIME, 1 );
- APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.PROVIDED, 2 );
- APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.COMPILE, 3 );
- APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.SYSTEM, 4 );
-
- TEST_SCOPE_PRIORITIES.put( JavaScopes.RUNTIME, 0 );
- TEST_SCOPE_PRIORITIES.put( JavaScopes.PROVIDED, 1 );
- TEST_SCOPE_PRIORITIES.put( JavaScopes.COMPILE, 2 );
- TEST_SCOPE_PRIORITIES.put( JavaScopes.TEST, 3 );
- TEST_SCOPE_PRIORITIES.put( JavaScopes.SYSTEM, 4 );
- }
-
- /**
- * Application scope nodes are prioritized over non application scope nodes.
- */
- public static final int APPLICATION_SCOPE_PRIORITIZATION = 1 << 1;
-
- /**
- * Test scope nodes are prioritized over non test scope nodes.
- */
- public static final int TEST_SCOPE_PRIORITIZATION = 1 << 2;
-
- /**
- * Nearest wins only strategy. No scopes are prioritized.
- */
- public static final int NO_PRIORITIZATION = 1 << 3;
-
- /**
- * The prioritization to apply.
- */
- private final int prioritization;
-
- /**
- * Creates a new {@code DependencyGraphTransformer}.
- *
- * @param prioritization The prioritization to apply.
- *
- * @see #APPLICATION_SCOPE_PRIORITIZATION
- * @see #TEST_SCOPE_PRIORITIZATION
- * @see #NO_PRIORITIZATION
- */
- public JavaDependencyMediator( final int prioritization )
- {
- super();
- this.prioritization = prioritization;
- }
-
- @Override
- public DependencyNode transformGraph( final DependencyNode node,
- final DependencyGraphTransformationContext context )
- throws RepositoryException
- {
- DependencyNode result = node;
- result = this.removeNonTransitiveNodes( result );
- result = this.updateTransitiveScopes( result );
-
- for ( ;; )
- {
- if ( this.removeDuplicateNodes( result, result, new HashMap<ConflictMarker.Key, DependencyNode>( 8192 ),
- new HashMap<DependencyNode, DependencyNode>( 8192 ) ) )
- {
- break;
- }
- }
-
- return result;
- }
-
- private DependencyNode removeNonTransitiveNodes( 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 Iterator<DependencyNode> it = parent.getChildren().iterator(); it.hasNext(); )
- {
- final DependencyNode child = it.next();
-
- 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
- && child.getDependency().getScope().length() >= 0
- ? child.getDependency().getScope()
- : JavaScopes.COMPILE;
-
- if ( ( child.getManagedBits() & DependencyNode.MANAGED_SCOPE ) == 0 )
- {
- // Non-managed child scopes are updated according to the table in the "Dependency Scope" section
- // of the "Introduction to the Dependency Mechanism" document.
-
- if ( JavaScopes.PROVIDED.equals( parentScope ) )
- {
- // Compile and runtime become provided.
- if ( JavaScopes.COMPILE.equals( childScope )
- || JavaScopes.RUNTIME.equals( childScope ) )
- {
- childScope = JavaScopes.PROVIDED;
- child.setScope( childScope );
- }
- }
- else if ( JavaScopes.RUNTIME.equals( parentScope ) )
- {
- // Compile becomes runtime.
- if ( JavaScopes.COMPILE.equals( childScope ) )
- {
- childScope = JavaScopes.RUNTIME;
- child.setScope( childScope );
- }
- }
- else if ( JavaScopes.TEST.equals( parentScope ) )
- {
- // Compile and runtime become test.
- if ( JavaScopes.COMPILE.equals( childScope )
- || JavaScopes.RUNTIME.equals( childScope ) )
- {
- childScope = JavaScopes.TEST;
- child.setScope( childScope );
- }
- }
- }
- }
-
- this.updateTransitiveScopes( child );
- }
-
- return parent;
- }
-
- private boolean removeDuplicateNodes( final DependencyNode rootNode,
- final DependencyNode candidateNode,
- final Map<ConflictMarker.Key, DependencyNode> winnerNodes,
- final Map<DependencyNode, DependencyNode> looserNodes )
- {
- boolean restart = false;
-
- recurse:
- {
- if ( candidateNode.getDependency() != null )
- {
- final ConflictMarker.Key candidateKey = new ConflictMarker.Key( candidateNode.getArtifact() );
- final DependencyNode winnerNode = winnerNodes.get( candidateKey );
-
- if ( winnerNode == null )
- {
- // Conflict not yet seen. Candidate is selected.
- winnerNodes.put( candidateKey, candidateNode );
- }
- else if ( this.isPreferredNode( winnerNode, candidateNode ) )
- {
- // Conflict already seen. Candidate is preferred.
- winnerNodes.put( candidateKey, candidateNode );
- looserNodes.put( candidateNode, winnerNode );
-
- if ( winnerNode.getParent() != null )
- {
- winnerNode.getParent().getChildren().remove( winnerNode );
- }
- else
- {
- rootNode.getChildren().remove( winnerNode );
- }
-
- final DependencyNode winningChild = getWinningChild( winnerNode, winnerNodes.values() );
-
- if ( winningChild != null )
- {
- // The node eliminated by the current candidate node contains a child node which has been
- // selected the winner in a previous iteration. As that winner is eliminated in this iteration,
- // the former looser needs to be re-added and the whole transformation re-started (undo and
- // restart). No need to maintain the maps here because they are thrown away when restarting.
- // Doing it for completeness, however.
- final DependencyNode looserNode = looserNodes.remove( winningChild ); // Can be get().
-
- if ( looserNode != null )
- {
- if ( looserNode.getParent() != null )
- {
- if ( !looserNode.getParent().getChildren().contains( looserNode ) )
- {
- looserNode.getParent().getChildren().add( looserNode );
- }
- }
- else if ( !rootNode.getChildren().contains( looserNode ) )
- {
- rootNode.getChildren().add( looserNode );
- }
-
- // Not needed, but...
- final DependencyNode winner =
- winnerNodes.remove( new ConflictMarker.Key( looserNode.getArtifact() ) );
-
- if ( winner != null )
- {
- looserNodes.remove( winner );
- }
- }
-
- restart = true;
- break recurse;
- }
- }
- else
- {
- // Conflict already seen. Candidate is not preferred.
- looserNodes.put( winnerNode, candidateNode );
- if ( candidateNode.getParent() != null )
- {
- candidateNode.getParent().getChildren().remove( candidateNode );
- }
- else
- {
- rootNode.getChildren().remove( candidateNode );
- }
- // No need to inspect children.
- break recurse;
- }
- }
-
- for ( final DependencyNode child : new ArrayList<DependencyNode>( candidateNode.getChildren() ) )
- {
- if ( !this.removeDuplicateNodes( rootNode, child, winnerNodes, looserNodes ) )
- {
- restart = true;
- break recurse;
- }
- }
- }
-
- return !restart;
- }
-
- private boolean isPreferredNode( final DependencyNode existing, final DependencyNode candidate )
- {
- boolean preferred = false;
- Integer p1 = null;
- Integer p2 = null;
- boolean prioritize = true;
-
- if ( this.prioritization == APPLICATION_SCOPE_PRIORITIZATION )
- {
- p1 = APPLICATION_SCOPE_PRIORITIES.get( existing.getDependency().getScope() );
- p2 = APPLICATION_SCOPE_PRIORITIES.get( candidate.getDependency().getScope() );
- }
- else if ( this.prioritization == TEST_SCOPE_PRIORITIZATION )
- {
- p1 = TEST_SCOPE_PRIORITIES.get( existing.getDependency().getScope() );
- p2 = TEST_SCOPE_PRIORITIES.get( candidate.getDependency().getScope() );
- }
- else if ( this.prioritization == NO_PRIORITIZATION )
- {
- prioritize = false;
- }
- else
- {
- throw new AssertionError( this.prioritization );
- }
-
- 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 = !prioritize || equalPriority || candidateScopePrioritized;
- }
- else if ( candidate.getDepth() == existing.getDepth() )
- {
- preferred = prioritize && !equalPriority && candidateScopePrioritized;
- }
-
- return preferred;
- }
-
- private static DependencyNode getWinningChild( final DependencyNode node,
- final Collection<DependencyNode> winnerNodes )
- {
- DependencyNode winningChild = winnerNodes.contains( node )
- ? node
- : null;
-
- if ( winningChild == null )
- {
- for ( final DependencyNode child : node.getChildren() )
- {
- winningChild = getWinningChild( child, winnerNodes );
-
- if ( winningChild != null )
- {
- break;
- }
- }
- }
-
- return winningChild;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java
deleted file mode 100644
index 4c5fd3e..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.RepositoryException;
-import org.eclipse.aether.util.artifact.JavaScopes;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeContext;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeDeriver;
-
-/**
- * A scope deriver for use with {@link ConflictResolver} that supports the scopes from {@link JavaScopes}.
- */
-public final class JavaScopeDeriver
- extends ScopeDeriver
-{
-
- /**
- * Creates a new instance of this scope deriver.
- */
- public JavaScopeDeriver()
- {
- }
-
- @Override
- public void deriveScope( ScopeContext context )
- throws RepositoryException
- {
- context.setDerivedScope( getDerivedScope( context.getParentScope(), context.getChildScope() ) );
- }
-
- private String getDerivedScope( String parentScope, String childScope )
- {
- String derivedScope;
-
- if ( JavaScopes.SYSTEM.equals( childScope ) || JavaScopes.TEST.equals( childScope ) )
- {
- derivedScope = childScope;
- }
- else if ( parentScope == null || parentScope.length() <= 0 || JavaScopes.COMPILE.equals( parentScope ) )
- {
- derivedScope = childScope;
- }
- else if ( JavaScopes.TEST.equals( parentScope ) || JavaScopes.RUNTIME.equals( parentScope ) )
- {
- derivedScope = parentScope;
- }
- else if ( JavaScopes.SYSTEM.equals( parentScope ) || JavaScopes.PROVIDED.equals( parentScope ) )
- {
- derivedScope = JavaScopes.PROVIDED;
- }
- else
- {
- derivedScope = JavaScopes.RUNTIME;
- }
-
- return derivedScope;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java
deleted file mode 100644
index 93edf05..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.HashSet;
-import java.util.Set;
-
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.util.artifact.JavaScopes;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictContext;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictItem;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeSelector;
-
-/**
- * A scope selector for use with {@link ConflictResolver} that supports the scopes from {@link JavaScopes}. In general,
- * this selector picks the widest scope present among conflicting dependencies where e.g. "compile" is wider than
- * "runtime" which is wider than "test". If however a direct dependency is involved, its scope is selected.
- */
-public final class JavaScopeSelector
- extends ScopeSelector
-{
-
- /**
- * Creates a new instance of this scope selector.
- */
- public JavaScopeSelector()
- {
- }
-
- @Override
- public void selectScope( ConflictContext context )
- throws RepositoryException
- {
- String scope = context.getWinner().getDependency().getScope();
- if ( !JavaScopes.SYSTEM.equals( scope ) )
- {
- scope = chooseEffectiveScope( context.getItems() );
- }
- context.setScope( scope );
- }
-
- private String chooseEffectiveScope( Collection<ConflictItem> items )
- {
- Set<String> scopes = new HashSet<String>();
- for ( ConflictItem item : items )
- {
- if ( item.getDepth() <= 1 )
- {
- return item.getDependency().getScope();
- }
- scopes.addAll( item.getScopes() );
- }
- return chooseEffectiveScope( scopes );
- }
-
- private String chooseEffectiveScope( Set<String> scopes )
- {
- if ( scopes.size() > 1 )
- {
- scopes.remove( JavaScopes.SYSTEM );
- }
-
- String effectiveScope = "";
-
- if ( scopes.size() == 1 )
- {
- effectiveScope = scopes.iterator().next();
- }
- else if ( scopes.contains( JavaScopes.COMPILE ) )
- {
- effectiveScope = JavaScopes.COMPILE;
- }
- else if ( scopes.contains( JavaScopes.RUNTIME ) )
- {
- effectiveScope = JavaScopes.RUNTIME;
- }
- else if ( scopes.contains( JavaScopes.PROVIDED ) )
- {
- effectiveScope = JavaScopes.PROVIDED;
- }
- else if ( scopes.contains( JavaScopes.TEST ) )
- {
- effectiveScope = JavaScopes.TEST;
- }
-
- return effectiveScope;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java
deleted file mode 100644
index c1ffa85..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.HashSet;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.collection.UnsolvableVersionConflictException;
-import org.eclipse.aether.graph.DependencyFilter;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictContext;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictItem;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.VersionSelector;
-import org.eclipse.aether.util.graph.visitor.PathRecordingDependencyVisitor;
-import org.eclipse.aether.version.Version;
-import org.eclipse.aether.version.VersionConstraint;
-
-/**
- * A version selector for use with {@link ConflictResolver} that resolves version conflicts using a nearest-wins
- * strategy. If there is no single node that satisfies all encountered version ranges, the selector will fail.
- */
-public final class NearestVersionSelector
- extends VersionSelector
-{
-
- /**
- * Creates a new instance of this version selector.
- */
- public NearestVersionSelector()
- {
- }
-
- @Override
- public void selectVersion( ConflictContext context )
- throws RepositoryException
- {
- ConflictGroup group = new ConflictGroup();
- for ( ConflictItem item : context.getItems() )
- {
- DependencyNode node = item.getNode();
- VersionConstraint constraint = node.getVersionConstraint();
-
- boolean backtrack = false;
- boolean hardConstraint = constraint.getRange() != null;
-
- if ( hardConstraint )
- {
- if ( group.constraints.add( constraint ) )
- {
- if ( group.winner != null && !constraint.containsVersion( group.winner.getNode().getVersion() ) )
- {
- backtrack = true;
- }
- }
- }
-
- if ( isAcceptable( group, node.getVersion() ) )
- {
- group.candidates.add( item );
-
- if ( backtrack )
- {
- backtrack( group, context );
- }
- else if ( group.winner == null || isNearer( item, group.winner ) )
- {
- group.winner = item;
- }
- }
- else if ( backtrack )
- {
- backtrack( group, context );
- }
- }
- context.setWinner( group.winner );
- }
-
- private void backtrack( ConflictGroup group, ConflictContext context )
- throws UnsolvableVersionConflictException
- {
- group.winner = null;
-
- for ( Iterator<ConflictItem> it = group.candidates.iterator(); it.hasNext(); )
- {
- ConflictItem candidate = it.next();
-
- if ( !isAcceptable( group, candidate.getNode().getVersion() ) )
- {
- it.remove();
- }
- else if ( group.winner == null || isNearer( candidate, group.winner ) )
- {
- group.winner = candidate;
- }
- }
-
- if ( group.winner == null )
- {
- throw newFailure( context );
- }
- }
-
- private boolean isAcceptable( ConflictGroup group, Version version )
- {
- for ( VersionConstraint constraint : group.constraints )
- {
- if ( !constraint.containsVersion( version ) )
- {
- return false;
- }
- }
- return true;
- }
-
- private boolean isNearer( ConflictItem item1, ConflictItem item2 )
- {
- if ( item1.isSibling( item2 ) )
- {
- return item1.getNode().getVersion().compareTo( item2.getNode().getVersion() ) > 0;
- }
- else
- {
- return item1.getDepth() < item2.getDepth();
- }
- }
-
- private UnsolvableVersionConflictException newFailure( final ConflictContext context )
- {
- DependencyFilter filter = new DependencyFilter()
- {
- public boolean accept( DependencyNode node, List<DependencyNode> parents )
- {
- return context.isIncluded( node );
- }
- };
- PathRecordingDependencyVisitor visitor = new PathRecordingDependencyVisitor( filter );
- context.getRoot().accept( visitor );
- return new UnsolvableVersionConflictException( visitor.getPaths() );
- }
-
- static final class ConflictGroup
- {
-
- final Collection<VersionConstraint> constraints;
-
- final Collection<ConflictItem> candidates;
-
- ConflictItem winner;
-
- public ConflictGroup()
- {
- constraints = new HashSet<VersionConstraint>();
- candidates = new ArrayList<ConflictItem>( 64 );
- }
-
- @Override
- public String toString()
- {
- return String.valueOf( winner );
- }
-
- }
-
-}