[MNG-612] Merged MNG-612 maven-artifact branch from 2.0.x:

https://svn.apache.org/repos/asf/maven/components/branches/MNG-612/maven-artifact/


git-svn-id: https://svn.apache.org/repos/asf/maven/artifact/branches/MNG-612@572705 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java b/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java
index ddcb601..964b97c 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java
@@ -37,11 +37,28 @@
  */
 public interface ArtifactCollector
 {
+    /**
+     * The plexus role for this component.
+     * 
+     * @since 3.0
+     */
+    String ROLE = ArtifactCollector.class.getName();
+
+    // TODO: deprecate since conflict resolvers should always be specified
     ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, ArtifactRepository localRepository,
                                       List remoteRepositories, ArtifactMetadataSource source, ArtifactFilter filter,
                                       List listeners );
 
+    // TODO: deprecate since conflict resolvers should always be specified
     ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, Map managedVersions,
                                       ArtifactRepository localRepository, List remoteRepositories,
                                       ArtifactMetadataSource source, ArtifactFilter filter, List listeners );
+
+    /**
+     * @since 3.0
+     */
+    ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, Map managedVersions,
+                                      ArtifactRepository localRepository, List remoteRepositories,
+                                      ArtifactMetadataSource source, ArtifactFilter filter, List listeners,
+                                      List conflictResolvers ) throws ArtifactResolutionException;
 }
diff --git a/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolutionRequest.java b/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolutionRequest.java
index ab839b8..e6d1f5f 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolutionRequest.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolutionRequest.java
@@ -39,6 +39,8 @@
     private ArtifactMetadataSource metadataSource;
 
     private Map managedVersionMap;
+    
+    private List conflictResolvers;
 
     public Artifact getArtifact()
     {
@@ -195,6 +197,18 @@
 
         return this;
     }
+    
+    public List getConflictResolvers()
+    {
+        return conflictResolvers;
+    }
+    
+    public ArtifactResolutionRequest setConflictResolvers( List conflictResolvers )
+    {
+        this.conflictResolvers = conflictResolvers;
+        
+        return this;
+    }
 
     public String toString()
     {
diff --git a/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolver.java b/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolver.java
index f426f0d..b855e70 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolver.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/ArtifactResolver.java
@@ -96,6 +96,15 @@
                                                   List listeners )
         throws ArtifactResolutionException, ArtifactNotFoundException;
 
+    /**
+     * @since 3.0
+     */
+    ArtifactResolutionResult resolveTransitively( Set artifacts, Artifact originatingArtifact, Map managedVersions,
+                                                  ArtifactRepository localRepository, List remoteRepositories,
+                                                  ArtifactMetadataSource source, ArtifactFilter filter, List listeners,
+                                                  List conflictResolvers )
+        throws ArtifactResolutionException, ArtifactNotFoundException;
+    
     void resolveAlways( Artifact artifact,
                         List remoteRepositories,
                         ArtifactRepository localRepository )
diff --git a/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java b/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java
index 8e0267d..04909d6 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java
@@ -24,6 +24,7 @@
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 import org.apache.maven.artifact.metadata.ResolutionGroup;
 import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.conflict.ConflictResolver;
 import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.versioning.ArtifactVersion;
@@ -52,6 +53,11 @@
 public class DefaultArtifactCollector
     implements ArtifactCollector
 {
+    /**
+     * The conflict resolver to use when none is specified.
+     */
+    private ConflictResolver defaultConflictResolver;
+         
     public ArtifactResolutionResult collect( Set artifacts,
                                              Artifact originatingArtifact,
                                              ArtifactRepository localRepository,
@@ -73,8 +79,24 @@
                                              ArtifactFilter filter,
                                              List listeners )
     {
+        return collect( artifacts, originatingArtifact, managedVersions, localRepository, remoteRepositories, source,
+                        filter, listeners, null );
+    }
+
+    public ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, Map managedVersions,
+                                             ArtifactRepository localRepository, List remoteRepositories,
+                                             ArtifactMetadataSource source, ArtifactFilter filter, List listeners,
+                                             List conflictResolvers )
+    {
         ArtifactResolutionResult result = new ArtifactResolutionResult();
 
+        if ( conflictResolvers == null )
+        {
+            // TODO: warn that we're using the default conflict resolver
+
+            conflictResolvers = Collections.singletonList( defaultConflictResolver );
+        }
+                                           
         Map resolvedArtifacts = new LinkedHashMap();
 
         ResolutionNode root = new ResolutionNode( originatingArtifact, remoteRepositories );
@@ -99,7 +121,7 @@
         ManagedVersionMap versionMap = getManagedVersionsMap( originatingArtifact, managedVersions );
 
         recurse( result, root, resolvedArtifacts, versionMap, localRepository, remoteRepositories, source, filter,
-            listeners );
+            listeners, conflictResolvers );
 
         Set set = new LinkedHashSet();
 
@@ -186,7 +208,8 @@
                           List remoteRepositories,
                           ArtifactMetadataSource source,
                           ArtifactFilter filter,
-                          List listeners )
+                          List listeners,
+                          List conflictResolvers )
     //throws ArtifactResolutionException
     {
         fireEvent( ResolutionListener.TEST_ARTIFACT, listeners, node );
@@ -250,7 +273,31 @@
                         }
 
                         // Conflict Resolution
-                        // TODO: use as conflict resolver(s), chain
+                        ResolutionNode resolved = null;
+                        for ( Iterator j = conflictResolvers.iterator(); resolved == null && j.hasNext(); )
+                        {
+                            ConflictResolver conflictResolver = (ConflictResolver) j.next();
+
+                            resolved = conflictResolver.resolveConflict( previous, node );
+                        }
+
+                        if ( resolved == null )
+                        {
+                            // TODO: add better exception that can detail the two conflicting artifacts
+                            result.addVersionRangeViolation( new ArtifactResolutionException(
+                                "Cannot resolve artifact version conflict between "
+                                + previous.getArtifact().getVersion() + " and "
+                                + node.getArtifact().getVersion(), previous.getArtifact() ) );
+                        }
+
+                        if ( resolved != previous && resolved != node )
+                        {
+                            // TODO: add better exception
+                            result.addVersionRangeViolation( new ArtifactResolutionException(
+                                "Conflict resolver returned unknown resolution node: ",
+                                resolved.getArtifact() ) );
+                        }
+                         
 
                         // TODO: should this be part of mediation?
                         // previous one is more dominant
@@ -258,7 +305,7 @@
 
                         ResolutionNode farthest;
 
-                        if ( previous.getDepth() <= node.getDepth() )
+                        if ( resolved == previous )
                         {
                             nearest = previous;
 
@@ -429,7 +476,7 @@
                         }
 
                         recurse( result, child, resolvedArtifacts, managedVersions, localRepository, remoteRepositories, source,
-                            filter, listeners );
+                            filter, listeners, conflictResolvers );
                     }
                 }
                 catch ( OverConstrainedVersionException e )
diff --git a/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java b/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
index 20284ec..d10799f 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
@@ -337,15 +337,6 @@
                                                          ArtifactFilter filter )
         throws ArtifactResolutionException, ArtifactNotFoundException
     {
-        // TODO: this is simplistic
-        List listeners = new ArrayList();
-        if ( getLogger().isDebugEnabled() )
-        {
-            listeners.add( new DebugResolutionListener( getLogger() ) );
-        }
-
-        listeners.add( new WarningResolutionListener( getLogger() ) );
-
         return resolveTransitively(
             artifacts,
             originatingArtifact,
@@ -354,8 +345,7 @@
             remoteRepositories,
             source,
             filter,
-            listeners );
-
+            null );
     }
 
     public ArtifactResolutionResult resolveTransitively( Set artifacts,
@@ -404,6 +394,33 @@
                                                          List listeners )
         throws ArtifactResolutionException, ArtifactNotFoundException
     {
+        return resolveTransitively( artifacts, originatingArtifact, managedVersions, localRepository,
+                                    remoteRepositories, source, filter, listeners, null );
+    }
+    
+    public ArtifactResolutionResult resolveTransitively( Set artifacts,
+                                                         Artifact originatingArtifact,
+                                                         Map managedVersions,
+                                                         ArtifactRepository localRepository,
+                                                         List remoteRepositories,
+                                                         ArtifactMetadataSource source,
+                                                         ArtifactFilter filter,
+                                                         List listeners,
+                                                         List conflictResolvers )
+        throws ArtifactResolutionException, ArtifactNotFoundException
+    {
+        if ( listeners == null )
+        {
+            // TODO: this is simplistic
+            listeners = new ArrayList();
+            if ( getLogger().isDebugEnabled() )
+            {
+                listeners.add( new DebugResolutionListener( getLogger() ) );
+            }
+
+            listeners.add( new WarningResolutionListener( getLogger() ) );
+        }
+
         ArtifactResolutionResult result;
 
         result = artifactCollector.collect(
@@ -414,7 +431,8 @@
             remoteRepositories,
             source,
             filter,
-            listeners );
+            listeners,
+            conflictResolvers );
 
         // We have collected all the problems so let's mimic the way the old code worked and just blow up right here.
         // That's right lets just let it rip right here and send a big incomprehensible blob of text at unsuspecting
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolver.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolver.java
index 18a0029..283695b 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolver.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolver.java
@@ -19,11 +19,29 @@
  * under the License.
  */
 
+import org.apache.maven.artifact.resolver.ResolutionNode;
+
 /**
+ * Determines which version of an artifact to use when there are conflicting declarations.
+ * 
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
  * @version $Id$
  */
 public interface ConflictResolver
 {
     static String ROLE = ConflictResolver.class.getName();
+
+    /**
+     * Determines which of the specified versions of an artifact to use when there are conflicting declarations.
+     * 
+     * @param node1
+     *            the first artifact declaration
+     * @param node2
+     *            the second artifact declaration
+     * @return the artifact declaration to use: <code>node1</code>; <code>node2</code>; or <code>null</code>if
+     *         this conflict cannot be resolved
+     * @since 3.0
+     */
+    ResolutionNode resolveConflict( ResolutionNode node1, ResolutionNode node2 );
 }
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolverFactory.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolverFactory.java
new file mode 100644
index 0000000..ebafa67
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolverFactory.java
@@ -0,0 +1,51 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.
+ */
+
+/**
+ * A factory that produces conflict resolvers of various types.
+ * 
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @since 3.0
+ * @see ConflictResolver
+ */
+public interface ConflictResolverFactory
+{
+    // constants --------------------------------------------------------------
+    
+    /**
+     * The plexus role for this component.
+     */
+    String ROLE = ConflictResolverFactory.class.getName();
+    
+    // methods ----------------------------------------------------------------
+    
+    /**
+     * Gets a conflict resolver of the specified type.
+     * 
+     * @param type
+     *            the type of conflict resolver to obtain
+     * @return the conflict resolver
+     * @throws ConflictResolverNotFoundException
+     *             if the specified type was not found
+     */
+    ConflictResolver getConflictResolver( String type ) throws ConflictResolverNotFoundException;
+}
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolverNotFoundException.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolverNotFoundException.java
new file mode 100644
index 0000000..d44d058
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/ConflictResolverNotFoundException.java
@@ -0,0 +1,50 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.
+ */
+
+/**
+ * Indicates that a specified conflict resolver implementation could not be found.
+ * 
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @since 3.0
+ */
+public class ConflictResolverNotFoundException extends Exception
+{
+    // constants --------------------------------------------------------------
+
+    /**
+     * The serial version ID.
+     */
+    private static final long serialVersionUID = 3372412184339653914L;
+
+    // constructors -----------------------------------------------------------
+
+    /**
+     * Creates a new <code>ConflictResolverNotFoundException</code> with the specified message.
+     * 
+     * @param message
+     *            the message
+     */
+    public ConflictResolverNotFoundException( String message )
+    {
+        super( message );
+    }
+}
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolver.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolver.java
index 0f3fb93..692b182 100644
--- a/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolver.java
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolver.java
@@ -20,10 +20,14 @@
  */
 
 /**
+ * The default conflict resolver that delegates to the nearest strategy.
+ * 
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
  * @version $Id$
+ * @see NearestConflictResolver
+ * @deprecated As of 3.0, use a specific implementation instead, e.g. {@link NearestConflictResolver}
  */
 public class DefaultConflictResolver
-    implements ConflictResolver
+    extends NearestConflictResolver
 {
 }
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolverFactory.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolverFactory.java
new file mode 100644
index 0000000..12d5225
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/DefaultConflictResolverFactory.java
@@ -0,0 +1,71 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+
+/**
+ * A conflict resolver factory that obtains instances from a plexus container.
+ * 
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @since 3.0
+ */
+public class DefaultConflictResolverFactory implements ConflictResolverFactory, Contextualizable
+{
+    // fields -----------------------------------------------------------------
+
+    /**
+     * The plexus container used to obtain instances from.
+     */
+    private PlexusContainer container;
+    
+    // ConflictResolverFactory methods ----------------------------------------
+    
+    /*
+     * @see org.apache.maven.artifact.resolver.conflict.ConflictResolverFactory#getConflictResolver(java.lang.String)
+     */
+    public ConflictResolver getConflictResolver( String type ) throws ConflictResolverNotFoundException
+    {
+        try
+        {
+            return (ConflictResolver) container.lookup( ConflictResolver.ROLE, type );
+        }
+        catch ( ComponentLookupException exception )
+        {
+            throw new ConflictResolverNotFoundException( "Cannot find conflict resolver of type: " + type );
+        }
+    }
+
+    // Contextualizable methods -----------------------------------------------
+
+    /*
+     * @see org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable#contextualize(org.codehaus.plexus.context.Context)
+     */
+    public void contextualize( Context context ) throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+    }
+}
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/FarthestConflictResolver.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/FarthestConflictResolver.java
new file mode 100644
index 0000000..bf3221a
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/FarthestConflictResolver.java
@@ -0,0 +1,45 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.apache.maven.artifact.resolver.ResolutionNode;
+
+/**
+ * Resolves conflicting artifacts by always selecting the <em>farthest</em> declaration. Farthest is defined as the
+ * declaration that has the most transitive steps away from the project being built.
+ * 
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @since 3.0
+ */
+public class FarthestConflictResolver
+    implements ConflictResolver
+{
+    // ConflictResolver methods -----------------------------------------------
+    
+    /*
+     * @see org.apache.maven.artifact.resolver.conflict.ConflictResolver#resolveConflict(org.apache.maven.artifact.resolver.ResolutionNode,
+     *      org.apache.maven.artifact.resolver.ResolutionNode)
+     */
+    public ResolutionNode resolveConflict( ResolutionNode node1, ResolutionNode node2 )
+    {
+        return node1.getDepth() >= node2.getDepth() ? node1 : node2;
+    }
+}
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/NearestConflictResolver.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/NearestConflictResolver.java
new file mode 100644
index 0000000..a67c701
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/NearestConflictResolver.java
@@ -0,0 +1,46 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.apache.maven.artifact.resolver.ResolutionNode;
+
+/**
+ * Resolves conflicting artifacts by always selecting the <em>nearest</em> declaration. Nearest is defined as the
+ * declaration that has the least transitive steps away from the project being built.
+ * 
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @since 3.0
+ */
+public class NearestConflictResolver
+    implements ConflictResolver
+{
+    // ConflictResolver methods -----------------------------------------------
+    
+    /*
+     * @see org.apache.maven.artifact.resolver.conflict.ConflictResolver#resolveConflict(org.apache.maven.artifact.resolver.ResolutionNode,
+     *      org.apache.maven.artifact.resolver.ResolutionNode)
+     */
+    public ResolutionNode resolveConflict( ResolutionNode node1, ResolutionNode node2 )
+    {
+        return node1.getDepth() <= node2.getDepth() ? node1 : node2;
+    }
+}
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/NewestConflictResolver.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/NewestConflictResolver.java
new file mode 100644
index 0000000..2a1d759
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/NewestConflictResolver.java
@@ -0,0 +1,60 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.apache.maven.artifact.resolver.ResolutionNode;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
+
+/**
+ * Resolves conflicting artifacts by always selecting the <em>newest</em> declaration. Newest is defined as the
+ * declaration whose version is greater according to <code>ArtifactVersion.compareTo</code>.
+ * 
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @see ArtifactVersion#compareTo(Object)
+ * @since 3.0
+ */
+public class NewestConflictResolver
+    implements ConflictResolver
+{
+    // ConflictResolver methods -----------------------------------------------
+    
+    /*
+     * @see org.apache.maven.artifact.resolver.conflict.ConflictResolver#resolveConflict(org.apache.maven.artifact.resolver.ResolutionNode,
+     *      org.apache.maven.artifact.resolver.ResolutionNode)
+     */
+    public ResolutionNode resolveConflict( ResolutionNode node1, ResolutionNode node2 )
+    {
+        try
+        {
+            ArtifactVersion version1 = node1.getArtifact().getSelectedVersion();
+            ArtifactVersion version2 = node2.getArtifact().getSelectedVersion();
+            
+            return version1.compareTo( version2 ) > 0 ? node1 : node2;
+        }
+        catch (OverConstrainedVersionException exception)
+        {
+            // TODO: log message or throw exception?
+            
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/artifact/resolver/conflict/OldestConflictResolver.java b/src/main/java/org/apache/maven/artifact/resolver/conflict/OldestConflictResolver.java
new file mode 100644
index 0000000..ebfa923
--- /dev/null
+++ b/src/main/java/org/apache/maven/artifact/resolver/conflict/OldestConflictResolver.java
@@ -0,0 +1,60 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.apache.maven.artifact.resolver.ResolutionNode;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
+
+/**
+ * Resolves conflicting artifacts by always selecting the <em>oldest</em> declaration. Oldest is defined as the
+ * declaration whose version is less according to <code>ArtifactVersion.compareTo</code>.
+ * 
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @see ArtifactVersion#compareTo(Object)
+ * @since 3.0
+ */
+public class OldestConflictResolver
+    implements ConflictResolver
+{
+    // ConflictResolver methods -----------------------------------------------
+    
+    /*
+     * @see org.apache.maven.artifact.resolver.conflict.ConflictResolver#resolveConflict(org.apache.maven.artifact.resolver.ResolutionNode,
+     *      org.apache.maven.artifact.resolver.ResolutionNode)
+     */
+    public ResolutionNode resolveConflict( ResolutionNode node1, ResolutionNode node2 )
+    {
+        try
+        {
+            ArtifactVersion version1 = node1.getArtifact().getSelectedVersion();
+            ArtifactVersion version2 = node2.getArtifact().getSelectedVersion();
+            
+            return version1.compareTo( version2 ) <= 0 ? node1 : node2;
+        }
+        catch (OverConstrainedVersionException exception)
+        {
+            // TODO: log message or throw exception?
+            
+            return null;
+        }
+    }
+}
diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml
index 58f6528..edb785b 100644
--- a/src/main/resources/META-INF/plexus/components.xml
+++ b/src/main/resources/META-INF/plexus/components.xml
@@ -216,8 +216,43 @@
     <component>
       <role>org.apache.maven.artifact.resolver.ArtifactCollector</role>
       <implementation>org.apache.maven.artifact.resolver.DefaultArtifactCollector</implementation>
+      <requirements>
+        <requirement>
+          <role>org.apache.maven.artifact.resolver.conflict.ConflictResolver</role>
+        </requirement>
+      </requirements>
     </component>
     
+    <component>
+      <role>org.apache.maven.artifact.resolver.conflict.ConflictResolver</role>
+      <role-hint>default</role-hint>
+      <implementation>org.apache.maven.artifact.resolver.conflict.NearestConflictResolver</implementation>
+    </component>
+
+    <component>
+      <role>org.apache.maven.artifact.resolver.conflict.ConflictResolver</role>
+      <role-hint>nearest</role-hint>
+      <implementation>org.apache.maven.artifact.resolver.conflict.NearestConflictResolver</implementation>
+    </component>
+
+    <component>
+      <role>org.apache.maven.artifact.resolver.conflict.ConflictResolver</role>
+      <role-hint>farthest</role-hint>
+      <implementation>org.apache.maven.artifact.resolver.conflict.FarthestConflictResolver</implementation>
+    </component>
+
+    <component>
+      <role>org.apache.maven.artifact.resolver.conflict.ConflictResolver</role>
+      <role-hint>newest</role-hint>
+      <implementation>org.apache.maven.artifact.resolver.conflict.NewestConflictResolver</implementation>
+    </component>
+
+    <component>
+      <role>org.apache.maven.artifact.resolver.conflict.ConflictResolver</role>
+      <role-hint>oldest</role-hint>
+      <implementation>org.apache.maven.artifact.resolver.conflict.OldestConflictResolver</implementation>
+    </component>
+
     <!-- From maven-artifact-manager -->
     
     <!--
@@ -389,5 +424,15 @@
       <implementation>org.apache.maven.artifact.repository.DefaultArtifactRepositoryFactory</implementation>
     </component>    
     
+    <!--
+     |
+     | ConflictResolverFactory
+     |
+     -->
+    <component>
+      <role>org.apache.maven.artifact.resolver.conflict.ConflictResolverFactory</role>
+      <implementation>org.apache.maven.artifact.resolver.conflict.DefaultConflictResolverFactory</implementation>
+    </component>
+     
   </components>
 </component-set>
diff --git a/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java b/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java
index 21148c8..72a3603 100644
--- a/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java
+++ b/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java
@@ -71,7 +71,7 @@
 
         this.source = new Source();
         this.artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
-        this.artifactCollector = new DefaultArtifactCollector();
+        this.artifactCollector = (ArtifactCollector) lookup( ArtifactCollector.ROLE );
 
         this.projectArtifact = createArtifactSpec( "project", "1.0", null );
     }
diff --git a/src/test/java/org/apache/maven/artifact/resolver/conflict/AbstractConflictResolverTest.java b/src/test/java/org/apache/maven/artifact/resolver/conflict/AbstractConflictResolverTest.java
new file mode 100644
index 0000000..f286d57
--- /dev/null
+++ b/src/test/java/org/apache/maven/artifact/resolver/conflict/AbstractConflictResolverTest.java
@@ -0,0 +1,143 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * 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.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.resolver.ResolutionNode;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.codehaus.plexus.PlexusTestCase;
+
+/**
+ * Provides a basis for testing conflict resolvers.
+ *
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ */
+public abstract class AbstractConflictResolverTest
+    extends PlexusTestCase
+{
+    // constants --------------------------------------------------------------
+    
+    private static final String GROUP_ID = "test";
+    
+    // fields -----------------------------------------------------------------
+    
+    protected Artifact a1;
+
+    protected Artifact a2;
+
+    protected Artifact b1;
+
+    private final String roleHint;
+    
+    private ArtifactFactory artifactFactory;
+
+    private ConflictResolver conflictResolver;
+    
+    // constructors -----------------------------------------------------------
+    
+    public AbstractConflictResolverTest( String roleHint )
+        throws Exception
+    {
+        this.roleHint = roleHint;
+    }
+    
+    // TestCase methods -------------------------------------------------------
+    
+    /*
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
+        conflictResolver = (ConflictResolver) lookup( ConflictResolver.ROLE, roleHint );
+        
+        a1 = createArtifact( "a", "1.0" );
+        a2 = createArtifact( "a", "2.0" );
+        b1 = createArtifact( "b", "1.0" );
+    }
+    
+    /*
+     * @see org.codehaus.plexus.PlexusTestCase#tearDown()
+     */
+    protected void tearDown() throws Exception
+    {
+        a1 = null;
+        a2 = null;
+        b1 = null;
+        
+        artifactFactory = null;
+        conflictResolver = null;
+        
+        super.tearDown();
+    }
+    
+    // protected methods ------------------------------------------------------
+    
+    protected ConflictResolver getConflictResolver()
+    {
+        return conflictResolver;
+    }
+    
+    protected void assertResolveConflict( ResolutionNode expectedNode, ResolutionNode actualNode1, ResolutionNode actualNode2 )
+    {
+        ResolutionNode resolvedNode = getConflictResolver().resolveConflict( actualNode1, actualNode2 );
+        
+        assertNotNull( "Expected resolvable", resolvedNode );
+        assertEquals( "Resolution node", expectedNode, resolvedNode );
+    }
+
+    protected void assertUnresolvableConflict( ResolutionNode actualNode1, ResolutionNode actualNode2 )
+    {
+        ResolutionNode resolvedNode = getConflictResolver().resolveConflict( actualNode1, actualNode2 );
+        
+        assertNull( "Expected unresolvable", resolvedNode );
+    }
+
+    protected Artifact createArtifact( String id, String version ) throws InvalidVersionSpecificationException
+    {
+        return createArtifact( id, version, Artifact.SCOPE_COMPILE );
+    }
+
+    protected Artifact createArtifact( String id, String version, boolean optional )
+        throws InvalidVersionSpecificationException
+    {
+        return createArtifact( id, version, Artifact.SCOPE_COMPILE, null, optional );
+    }
+
+    protected Artifact createArtifact( String id, String version, String scope )
+        throws InvalidVersionSpecificationException
+    {
+        return createArtifact( id, version, scope, null, false );
+    }
+
+    protected Artifact createArtifact( String id, String version, String scope, String inheritedScope, boolean optional )
+        throws InvalidVersionSpecificationException
+    {
+        VersionRange versionRange = VersionRange.createFromVersionSpec( version );
+        
+        return artifactFactory.createDependencyArtifact( GROUP_ID, id, versionRange, "jar", null, scope,
+                                                         inheritedScope, optional );
+    }
+}
diff --git a/src/test/java/org/apache/maven/artifact/resolver/conflict/FarthestConflictResolverTest.java b/src/test/java/org/apache/maven/artifact/resolver/conflict/FarthestConflictResolverTest.java
new file mode 100644
index 0000000..7d37bdd
--- /dev/null
+++ b/src/test/java/org/apache/maven/artifact/resolver/conflict/FarthestConflictResolverTest.java
@@ -0,0 +1,107 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+
+import org.apache.maven.artifact.resolver.ResolutionNode;
+
+/**
+ * Tests <code>FarthestConflictResolver</code>.
+ *
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @see FarthestConflictResolver
+ */
+public class FarthestConflictResolverTest
+    extends AbstractConflictResolverTest
+{
+    // constructors -----------------------------------------------------------
+    
+    public FarthestConflictResolverTest()
+        throws Exception
+    {
+        super("farthest");
+    }
+    
+    // tests ------------------------------------------------------------------
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * b:1.0 -> a:2.0
+     * </pre>
+     */
+    public void testDepth()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        
+        assertResolveConflict( a2n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * b:1.0 -> a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testDepthReversed()
+    {
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a2n, a2n, a1n );
+    }
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * a:2.0
+     * </pre>
+     */
+    public void testEqual()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a1n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testEqualReversed()
+    {
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a2n, a2n, a1n );
+    }
+}
diff --git a/src/test/java/org/apache/maven/artifact/resolver/conflict/NearestConflictResolverTest.java b/src/test/java/org/apache/maven/artifact/resolver/conflict/NearestConflictResolverTest.java
new file mode 100644
index 0000000..09b439b
--- /dev/null
+++ b/src/test/java/org/apache/maven/artifact/resolver/conflict/NearestConflictResolverTest.java
@@ -0,0 +1,107 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+
+import org.apache.maven.artifact.resolver.ResolutionNode;
+
+/**
+ * Tests <code>NearestConflictResolver</code>.
+ *
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @see NearestConflictResolver
+ */
+public class NearestConflictResolverTest
+    extends AbstractConflictResolverTest
+{
+    // constructors -----------------------------------------------------------
+    
+    public NearestConflictResolverTest()
+        throws Exception
+    {
+        super("nearest");
+    }
+    
+    // tests ------------------------------------------------------------------
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * b:1.0 -> a:2.0
+     * </pre>
+     */
+    public void testDepth()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        
+        assertResolveConflict( a1n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * b:1.0 -> a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testDepthReversed()
+    {
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a1n, a2n, a1n );
+    }
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * a:2.0
+     * </pre>
+     */
+    public void testEqual()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a1n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testEqualReversed()
+    {
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a2n, a2n, a1n );
+    }
+}
diff --git a/src/test/java/org/apache/maven/artifact/resolver/conflict/NewestConflictResolverTest.java b/src/test/java/org/apache/maven/artifact/resolver/conflict/NewestConflictResolverTest.java
new file mode 100644
index 0000000..90083ab
--- /dev/null
+++ b/src/test/java/org/apache/maven/artifact/resolver/conflict/NewestConflictResolverTest.java
@@ -0,0 +1,107 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+
+import org.apache.maven.artifact.resolver.ResolutionNode;
+
+/**
+ * Tests <code>NewestConflictResolver</code>.
+ *
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @see NewestConflictResolver
+ */
+public class NewestConflictResolverTest
+    extends AbstractConflictResolverTest
+{
+    // constructors -----------------------------------------------------------
+    
+    public NewestConflictResolverTest()
+        throws Exception
+    {
+        super("newest");
+    }
+    
+    // tests ------------------------------------------------------------------
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * b:1.0 -> a:2.0
+     * </pre>
+     */
+    public void testDepth()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        
+        assertResolveConflict( a2n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * b:1.0 -> a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testDepthReversed()
+    {
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a2n, a2n, a1n );
+    }
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * a:2.0
+     * </pre>
+     */
+    public void testEqual()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a2n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:2.0</code> wins in the scenario:
+     * <pre>
+     * a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testEqualReversed()
+    {
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a2n, a2n, a1n );
+    }
+}
diff --git a/src/test/java/org/apache/maven/artifact/resolver/conflict/OldestConflictResolverTest.java b/src/test/java/org/apache/maven/artifact/resolver/conflict/OldestConflictResolverTest.java
new file mode 100644
index 0000000..a5023c6
--- /dev/null
+++ b/src/test/java/org/apache/maven/artifact/resolver/conflict/OldestConflictResolverTest.java
@@ -0,0 +1,107 @@
+package org.apache.maven.artifact.resolver.conflict;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+
+import org.apache.maven.artifact.resolver.ResolutionNode;
+
+/**
+ * Tests <code>OldestConflictResolver</code>.
+ *
+ * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
+ * @version $Id$
+ * @see OldestConflictResolver
+ */
+public class OldestConflictResolverTest
+    extends AbstractConflictResolverTest
+{
+    // constructors -----------------------------------------------------------
+    
+    public OldestConflictResolverTest()
+        throws Exception
+    {
+        super("oldest");
+    }
+    
+    // tests ------------------------------------------------------------------
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * b:1.0 -> a:2.0
+     * </pre>
+     */
+    public void testDepth()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        
+        assertResolveConflict( a1n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * b:1.0 -> a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testDepthReversed()
+    {
+        ResolutionNode b1n = new ResolutionNode( b1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST, b1n );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a1n, a2n, a1n );
+    }
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * a:1.0
+     * a:2.0
+     * </pre>
+     */
+    public void testEqual()
+    {
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a1n, a1n, a2n );
+    }
+
+    /**
+     * Tests that <code>a:1.0</code> wins in the scenario:
+     * <pre>
+     * a:2.0
+     * a:1.0
+     * </pre>
+     */
+    public void testEqualReversed()
+    {
+        ResolutionNode a2n = new ResolutionNode( a2, Collections.EMPTY_LIST );
+        ResolutionNode a1n = new ResolutionNode( a1, Collections.EMPTY_LIST );
+        
+        assertResolveConflict( a1n, a2n, a1n );
+    }
+}