[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 );
+ }
+}