From 9c060b192a0bfda57e3e8fb2220b6f7930e60397 Mon Sep 17 00:00:00 2001
From: Brett Leslie Porter <brett@apache.org>
Date: Fri, 9 Sep 2005 06:49:59 +0000
Subject: [PATCH] PR: MNG-613 Completion of the version selection from a range.

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@279720 13f79535-47bb-0310-9956-ffa450edef68
---
 .../artifact/ant/AntResolutionListener.java   |  10 +-
 .../resources/META-INF/plexus/components.xml  |   3 +
 .../resolver/DebugResolutionListener.java     |   6 +
 .../resolver/DefaultArtifactResolver.java     |   2 +-
 .../resolver/WarningResolutionListener.java   |   4 +
 .../resolver/ArtifactResolverTest.java        |  16 ++-
 .../org/apache/maven/artifact/Artifact.java   |   4 +
 .../maven/artifact/DefaultArtifact.java       |  32 ++++-
 .../metadata/ArtifactMetadataSource.java      |   3 +
 .../artifact/resolver/ArtifactCollector.java  |   6 +-
 .../resolver/DefaultArtifactCollector.java    |  58 ++++++--
 .../artifact/resolver/ResolutionListener.java |   4 +
 .../artifact/versioning/VersionRange.java     |  70 +++++++++-
 .../DefaultArtifactCollectorTest.java         |  16 ++-
 maven-core-it/it0034/expected-results.txt     |   1 +
 maven-core-it/it0034/pom.xml                  |   4 +-
 maven-core-it/it0034/prebuild-hook.txt        |   1 +
 maven-project/pom.xml                         |   6 +
 .../artifact/ActiveProjectArtifact.java       |  10 ++
 .../project/artifact/MavenMetadataSource.java | 126 +++++++++++++++++-
 .../resources/META-INF/plexus/components.xml  |   3 +
 .../maven/project/TestArtifactResolver.java   |  10 +-
 22 files changed, 353 insertions(+), 42 deletions(-)

diff --git a/maven-artifact-ant/src/main/java/org/apache/maven/artifact/ant/AntResolutionListener.java b/maven-artifact-ant/src/main/java/org/apache/maven/artifact/ant/AntResolutionListener.java
index 679fdcc94c..40eca46836 100644
--- a/maven-artifact-ant/src/main/java/org/apache/maven/artifact/ant/AntResolutionListener.java
+++ b/maven-artifact-ant/src/main/java/org/apache/maven/artifact/ant/AntResolutionListener.java
@@ -69,12 +69,18 @@ public class AntResolutionListener
 
     public void updateScope( Artifact artifact, String scope )
     {
-        project.log( indent + artifact.getId() + " (settings scope to: " + scope + ")" );
+        project.log( indent + artifact.getId() + " (setting scope to: " + scope + ")" );
     }
 
     public void updateScopeCurrentPom( Artifact artifact, String scope )
     {
-    	updateScope( artifact, scope );
+        updateScope( artifact, scope );
+    }
+
+    public void selectVersionFromRange( Artifact artifact )
+    {
+        project.log( indent + artifact.getId() + " (setting version to: " + artifact.getVersion() + " from range: " +
+            artifact.getVersionRange() + ")" );
     }
 
     public void manageArtifact( Artifact artifact, Artifact replacement )
diff --git a/maven-artifact-ant/src/main/resources/META-INF/plexus/components.xml b/maven-artifact-ant/src/main/resources/META-INF/plexus/components.xml
index 956c425faa..e7e3aad5b8 100644
--- a/maven-artifact-ant/src/main/resources/META-INF/plexus/components.xml
+++ b/maven-artifact-ant/src/main/resources/META-INF/plexus/components.xml
@@ -441,6 +441,9 @@
         <requirement>
           <role>org.apache.maven.artifact.factory.ArtifactFactory</role>
         </requirement>
+        <requirement>
+          <role>org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager</role>
+        </requirement>
       </requirements>
     </component>
 
diff --git a/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DebugResolutionListener.java b/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DebugResolutionListener.java
index 0fcf7592a7..ad87a59e64 100644
--- a/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DebugResolutionListener.java
+++ b/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DebugResolutionListener.java
@@ -76,6 +76,12 @@ public class DebugResolutionListener
         logger.debug( indent + artifact.getId() + " (setting scope to: " + scope + ")" );
     }
 
+    public void selectVersionFromRange( Artifact artifact )
+    {
+        logger.debug( indent + artifact.getId() + " (setting version to: " + artifact.getVersion() + " from range: " +
+            artifact.getVersionRange() + ")" );
+    }
+
     public void manageArtifact( Artifact artifact, Artifact replacement )
     {
         String msg = indent + artifact.getId();
diff --git a/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java b/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
index 9b21695e8a..315c86846a 100644
--- a/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
+++ b/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
@@ -198,7 +198,7 @@ public class DefaultArtifactResolver
         ArtifactResolutionResult artifactResolutionResult;
         artifactResolutionResult = artifactCollector.collect( artifacts, originatingArtifact, managedVersions,
                                                               localRepository, remoteRepositories, source, filter,
-                                                              artifactFactory, listeners );
+                                                              listeners );
 
         for ( Iterator i = artifactResolutionResult.getArtifactResolutionNodes().iterator(); i.hasNext(); )
         {
diff --git a/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/WarningResolutionListener.java b/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/WarningResolutionListener.java
index e58d0d2028..f587eb9684 100644
--- a/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/WarningResolutionListener.java
+++ b/maven-artifact-manager/src/main/java/org/apache/maven/artifact/resolver/WarningResolutionListener.java
@@ -84,4 +84,8 @@ public class WarningResolutionListener
     public void manageArtifact( Artifact artifact, Artifact replacement )
     {
     }
+
+    public void selectVersionFromRange( Artifact artifact )
+    {
+    }
 }
diff --git a/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java b/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java
index 2343351533..6e980bd5b3 100644
--- a/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java
+++ b/maven-artifact-manager/src/test/java/org/apache/maven/artifact/resolver/ArtifactResolverTest.java
@@ -104,7 +104,7 @@ public class ArtifactResolverTest
             {
                 Set dependencies = new HashSet();
 
-                if ( artifact.getArtifactId().equals( "g" ) )
+                if ( "g".equals( artifact.getArtifactId() ) )
                 {
                     try
                     {
@@ -118,6 +118,12 @@ public class ArtifactResolverTest
 
                 return new ResolutionGroup( artifact, dependencies, remoteRepositories );
             }
+
+            public List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
+                                                   List remoteRepositories )
+            {
+                throw new UnsupportedOperationException( "Cannot get available versions in this test case" );
+            }
         };
 
         ArtifactResolutionResult result = artifactResolver.resolveTransitively( Collections.singleton( g ),
@@ -152,7 +158,7 @@ public class ArtifactResolverTest
             {
                 Set dependencies = new HashSet();
 
-                if ( artifact.getArtifactId().equals( "i" ) )
+                if ( "i".equals( artifact.getArtifactId() ) )
                 {
                     try
                     {
@@ -166,6 +172,12 @@ public class ArtifactResolverTest
 
                 return new ResolutionGroup( artifact, dependencies, remoteRepositories );
             }
+
+            public List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
+                                                   List remoteRepositories )
+            {
+                throw new UnsupportedOperationException( "Cannot get available versions in this test case" );
+            }
         };
 
         ArtifactResolutionResult result = artifactResolver.resolveTransitively( Collections.singleton( i ),
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/Artifact.java b/maven-artifact/src/main/java/org/apache/maven/artifact/Artifact.java
index 7bbb03d128..32e0ad180f 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/Artifact.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/Artifact.java
@@ -145,4 +145,8 @@ public interface Artifact
     boolean isRelease();
 
     void setRelease( boolean release );
+
+    List getAvailableVersions();
+
+    void setAvailableVersions( List versions );
 }
\ No newline at end of file
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java b/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java
index 795271415e..115a2d3410 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java
@@ -76,6 +76,8 @@ public class DefaultArtifact
 
     private boolean release = false;
 
+    private List availableVersions;
+
     public DefaultArtifact( String groupId, String artifactId, VersionRange versionRange, String scope, String type,
                             String classifier, ArtifactHandler artifactHandler )
     {
@@ -229,7 +231,8 @@ public class DefaultArtifact
 
     public String toString()
     {
-        return getId();
+        return getDependencyConflictId() + ( hasClassifier() ? ":" + getClassifier() : "" ) + ":" +
+            ( version != null || baseVersion != null ? getBaseVersion() : versionRange.toString() );
     }
 
     public int hashCode()
@@ -431,15 +434,22 @@ public class DefaultArtifact
 
     public boolean isSnapshot()
     {
-        Matcher m = VERSION_FILE_PATTERN.matcher( getBaseVersion() );
-        if ( m.matches() )
+        if ( version != null || baseVersion != null )
         {
-            setBaseVersion( m.group( 1 ) + "-" + SNAPSHOT_VERSION );
-            return true;
+            Matcher m = VERSION_FILE_PATTERN.matcher( getBaseVersion() );
+            if ( m.matches() )
+            {
+                setBaseVersion( m.group( 1 ) + "-" + SNAPSHOT_VERSION );
+                return true;
+            }
+            else
+            {
+                return getBaseVersion().endsWith( SNAPSHOT_VERSION ) || getBaseVersion().equals( LATEST_VERSION );
+            }
         }
         else
         {
-            return getBaseVersion().endsWith( SNAPSHOT_VERSION ) || getBaseVersion().equals( LATEST_VERSION );
+            return false;
         }
     }
 
@@ -473,4 +483,14 @@ public class DefaultArtifact
     {
         return release;
     }
+
+    public List getAvailableVersions()
+    {
+        return availableVersions;
+    }
+
+    public void setAvailableVersions( List availableVersions )
+    {
+        this.availableVersions = availableVersions;
+    }
 }
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/metadata/ArtifactMetadataSource.java b/maven-artifact/src/main/java/org/apache/maven/artifact/metadata/ArtifactMetadataSource.java
index de37124fa3..44aef5d916 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/metadata/ArtifactMetadataSource.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/metadata/ArtifactMetadataSource.java
@@ -31,4 +31,7 @@ public interface ArtifactMetadataSource
 
     ResolutionGroup retrieve( Artifact artifact, ArtifactRepository localRepository, List remoteRepositories )
         throws ArtifactMetadataRetrievalException;
+
+    List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository, List remoteRepositories )
+        throws ArtifactMetadataRetrievalException;
 }
\ No newline at end of file
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java b/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java
index f7c0866e8f..035b5b4791 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ArtifactCollector.java
@@ -17,7 +17,6 @@ package org.apache.maven.artifact.resolver;
 */
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
@@ -37,12 +36,11 @@ public interface ArtifactCollector
 {
     ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, ArtifactRepository localRepository,
                                       List remoteRepositories, ArtifactMetadataSource source, ArtifactFilter filter,
-                                      ArtifactFactory artifactFactory, List listeners )
+                                      List listeners )
         throws ArtifactResolutionException;
 
     ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, Map managedVersions,
                                       ArtifactRepository localRepository, List remoteRepositories,
-                                      ArtifactMetadataSource source, ArtifactFilter filter,
-                                      ArtifactFactory artifactFactory, List listeners )
+                                      ArtifactMetadataSource source, ArtifactFilter filter, List listeners )
         throws ArtifactResolutionException;
 }
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java b/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java
index 13d092eb0a..142caaaa31 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactCollector.java
@@ -17,12 +17,12 @@ package org.apache.maven.artifact.resolver;
  */
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 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.filter.ArtifactFilter;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
 import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
 import org.apache.maven.artifact.versioning.VersionRange;
 
@@ -45,18 +45,16 @@ public class DefaultArtifactCollector
 {
     public ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact,
                                              ArtifactRepository localRepository, List remoteRepositories,
-                                             ArtifactMetadataSource source, ArtifactFilter filter,
-                                             ArtifactFactory artifactFactory, List listeners )
+                                             ArtifactMetadataSource source, ArtifactFilter filter, List listeners )
         throws ArtifactResolutionException
     {
         return collect( artifacts, originatingArtifact, Collections.EMPTY_MAP, localRepository, remoteRepositories,
-                        source, filter, artifactFactory, listeners );
+                        source, filter, listeners );
     }
 
     public ArtifactResolutionResult collect( Set artifacts, Artifact originatingArtifact, Map managedVersions,
                                              ArtifactRepository localRepository, List remoteRepositories,
-                                             ArtifactMetadataSource source, ArtifactFilter filter,
-                                             ArtifactFactory artifactFactory, List listeners )
+                                             ArtifactMetadataSource source, ArtifactFilter filter, List listeners )
         throws ArtifactResolutionException
     {
         Map resolvedArtifacts = new HashMap();
@@ -68,7 +66,7 @@ public class DefaultArtifactCollector
             root.addDependencies( artifacts, remoteRepositories, filter );
 
             recurse( root, resolvedArtifacts, managedVersions, localRepository, remoteRepositories, source, filter,
-                     artifactFactory, listeners );
+                     listeners );
 
             Set set = new HashSet();
 
@@ -97,7 +95,7 @@ public class DefaultArtifactCollector
 
     private void recurse( ResolutionNode node, Map resolvedArtifacts, Map managedVersions,
                           ArtifactRepository localRepository, List remoteRepositories, ArtifactMetadataSource source,
-                          ArtifactFilter filter, ArtifactFactory artifactFactory, List listeners )
+                          ArtifactFilter filter, List listeners )
         throws CyclicDependencyException, TransitiveArtifactResolutionException, OverConstrainedVersionException
     {
         fireEvent( ResolutionListener.TEST_ARTIFACT, listeners, node );
@@ -179,8 +177,43 @@ public class DefaultArtifactCollector
                     {
                         // set the recommended version
                         VersionRange versionRange = artifact.getVersionRange();
-                        String version = versionRange.getSelectedVersion().toString();
-                        artifact.selectVersion( version );
+
+                        // TODO: maybe its better to just pass the range through to retrieval and use a transformation?
+                        ArtifactVersion version;
+                        if ( !versionRange.isSelectedVersionKnown() )
+                        {
+                            List versions = artifact.getAvailableVersions();
+                            if ( versions == null )
+                            {
+                                versions = source.retrieveAvailableVersions( artifact, localRepository,
+                                                                             remoteRepositories );
+                                artifact.setAvailableVersions( versions );
+                            }
+
+                            version = versionRange.matchVersion( versions );
+
+                            if ( version == null )
+                            {
+                                if ( versions.isEmpty() )
+                                {
+                                    throw new OverConstrainedVersionException(
+                                        "No versions are present in the repository for the artifact with a range " +
+                                            versionRange );
+                                }
+                                else
+                                {
+                                    throw new OverConstrainedVersionException(
+                                        "Couldn't find a version in " + versions + " to match range " + versionRange );
+                                }
+                            }
+                        }
+                        else
+                        {
+                            version = versionRange.getSelectedVersion();
+                        }
+
+                        artifact.selectVersion( version.toString() );
+                        fireEvent( ResolutionListener.SELECT_VERSION_FROM_RANGE, listeners, child );
                     }
 
                     ResolutionGroup rGroup = source.retrieve( artifact, localRepository, remoteRepositories );
@@ -202,7 +235,7 @@ public class DefaultArtifactCollector
                 }
 
                 recurse( child, resolvedArtifacts, managedVersions, localRepository, remoteRepositories, source, filter,
-                         artifactFactory, listeners );
+                         listeners );
             }
         }
 
@@ -289,6 +322,9 @@ public class DefaultArtifactCollector
                 case ResolutionListener.MANAGE_ARTIFACT:
                     listener.manageArtifact( node.getArtifact(), replacement );
                     break;
+                case ResolutionListener.SELECT_VERSION_FROM_RANGE:
+                    listener.selectVersionFromRange( node.getArtifact() );
+                    break;
                 default:
                     throw new IllegalStateException( "Unknown event: " + event );
             }
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ResolutionListener.java b/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ResolutionListener.java
index f85002d8c8..b4e0294b71 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ResolutionListener.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/resolver/ResolutionListener.java
@@ -46,6 +46,8 @@ public interface ResolutionListener
 
     int UPDATE_SCOPE_CURRENT_POM = 9;
 
+    int SELECT_VERSION_FROM_RANGE = 10;
+
     void testArtifact( Artifact node );
 
     void startProcessChildren( Artifact artifact );
@@ -63,4 +65,6 @@ public interface ResolutionListener
     void omitForCycle( Artifact artifact );
 
     void updateScopeCurrentPom( Artifact artifact, String scope );
+
+    void selectVersionFromRange( Artifact artifact );
 }
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java b/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java
index 945f988cb0..9b2351c590 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java
@@ -407,9 +407,7 @@ public class VersionRange
             else
             {
                 Restriction restriction = (Restriction) restrictions.get( restrictions.size() - 1 );
-                // TODO: how can we find the latest release before something to facilitate ) at the end?
-                // Also, how can we find the latest release when there no RELEASE metadata? We need to be maintaining
-                // a version list in the repository
+
                 version = restriction.getUpperBound();
                 if ( version == null )
                 {
@@ -420,6 +418,38 @@ public class VersionRange
         return version;
     }
 
+    public boolean isSelectedVersionKnown()
+        throws OverConstrainedVersionException
+    {
+        boolean value;
+        if ( recommendedVersion != null )
+        {
+            value = true;
+        }
+        else
+        {
+            if ( restrictions.size() == 0 )
+            {
+                throw new OverConstrainedVersionException( "The artifact has no valid ranges" );
+            }
+            else
+            {
+                Restriction restriction = (Restriction) restrictions.get( restrictions.size() - 1 );
+
+                if ( restriction.getUpperBound() == null )
+                {
+                    // RELEASE version, considered known
+                    value = true;
+                }
+                else
+                {
+                    value = restriction.isUpperBoundInclusive();
+                }
+            }
+        }
+        return value;
+    }
+
     public String toString()
     {
         if ( recommendedVersion != null )
@@ -453,4 +483,38 @@ public class VersionRange
             return buf.toString();
         }
     }
+
+    public ArtifactVersion matchVersion( List versions )
+    {
+        // TODO: could be more efficient by sorting the list and then moving along the restrictions in order?
+
+        ArtifactVersion matched = null;
+        for ( Iterator i = versions.iterator(); i.hasNext(); )
+        {
+            ArtifactVersion version = (ArtifactVersion) i.next();
+            if ( containsVersion( version ) )
+            {
+                // valid - check if it is greater than the currently matched version
+                if ( matched == null || version.compareTo( matched ) > 0 )
+                {
+                    matched = version;
+                }
+            }
+        }
+        return matched;
+    }
+
+    private boolean containsVersion( ArtifactVersion version )
+    {
+        boolean matched = false;
+        for ( Iterator i = restrictions.iterator(); i.hasNext() && !matched; )
+        {
+            Restriction restriction = (Restriction) i.next();
+            if ( restriction.containsVersion( version ) )
+            {
+                matched = true;
+            }
+        }
+        return matched;
+    }
 }
diff --git a/maven-artifact/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java b/maven-artifact/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java
index 422a104105..dc6b8f4032 100644
--- a/maven-artifact/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java
+++ b/maven-artifact/src/test/java/org/apache/maven/artifact/resolver/DefaultArtifactCollectorTest.java
@@ -336,21 +336,21 @@ public class DefaultArtifactCollectorTest
         throws ArtifactResolutionException
     {
         return artifactCollector.collect( artifacts, projectArtifact.artifact, null, null, source, null,
-                                          artifactFactory, Collections.EMPTY_LIST );
+                                          Collections.EMPTY_LIST );
     }
 
     private ArtifactResolutionResult collect( ArtifactSpec a )
         throws ArtifactResolutionException
     {
         return artifactCollector.collect( Collections.singleton( a.artifact ), projectArtifact.artifact, null, null,
-                                          source, null, artifactFactory, Collections.EMPTY_LIST );
+                                          source, null, Collections.EMPTY_LIST );
     }
 
     private ArtifactResolutionResult collect( ArtifactSpec a, ArtifactFilter filter )
         throws ArtifactResolutionException
     {
         return artifactCollector.collect( Collections.singleton( a.artifact ), projectArtifact.artifact, null, null,
-                                          source, filter, artifactFactory, Collections.EMPTY_LIST );
+                                          source, filter, Collections.EMPTY_LIST );
     }
 
     private ArtifactResolutionResult collect( ArtifactSpec a, Artifact managedVersion )
@@ -358,8 +358,7 @@ public class DefaultArtifactCollectorTest
     {
         Map managedVersions = Collections.singletonMap( managedVersion.getDependencyConflictId(), managedVersion );
         return artifactCollector.collect( Collections.singleton( a.artifact ), projectArtifact.artifact,
-                                          managedVersions, null, null, source, null, artifactFactory,
-                                          Collections.EMPTY_LIST );
+                                          managedVersions, null, null, source, null, Collections.EMPTY_LIST );
     }
 
     private ArtifactSpec createArtifact( String id, String version )
@@ -461,5 +460,12 @@ public class DefaultArtifactCollectorTest
 
             return projectArtifacts;
         }
+
+        public List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
+                                               List remoteRepositories )
+            throws ArtifactMetadataRetrievalException
+        {
+            throw new UnsupportedOperationException( "Cannot get available versions in this test case" );
+        }
     }
 }
diff --git a/maven-core-it/it0034/expected-results.txt b/maven-core-it/it0034/expected-results.txt
index 64f948ec6c..d2fed33a5a 100644
--- a/maven-core-it/it0034/expected-results.txt
+++ b/maven-core-it/it0034/expected-results.txt
@@ -1 +1,2 @@
+${artifact:junit:junit:3.7:jar}
 ${artifact:org.apache.maven:maven-core-it-support:1.1:jar}
diff --git a/maven-core-it/it0034/pom.xml b/maven-core-it/it0034/pom.xml
index 755a9f0997..a1223ea94f 100644
--- a/maven-core-it/it0034/pom.xml
+++ b/maven-core-it/it0034/pom.xml
@@ -7,8 +7,8 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <type>jar</type>
+      <!-- Select 3.7 -->
+      <version>(,3.8)</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/maven-core-it/it0034/prebuild-hook.txt b/maven-core-it/it0034/prebuild-hook.txt
index 58e13fba23..245966da96 100644
--- a/maven-core-it/it0034/prebuild-hook.txt
+++ b/maven-core-it/it0034/prebuild-hook.txt
@@ -1 +1,2 @@
 rm ${artifact:org.apache.maven:maven-core-it-support:1.1:jar}
+rm ${artifact:junit:junit:3.7:jar}
diff --git a/maven-project/pom.xml b/maven-project/pom.xml
index 4601fc40f5..d748943a30 100755
--- a/maven-project/pom.xml
+++ b/maven-project/pom.xml
@@ -18,6 +18,12 @@
       <artifactId>maven-model</artifactId>
       <version>2.0-beta-1-SNAPSHOT</version>
     </dependency>
+    <!-- TODO: temporary - refactor code to avoid this. It is for metadata retrieval in MavenMetadataSource -->
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+      <version>2.0-beta-1-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-profile</artifactId>
diff --git a/maven-project/src/main/java/org/apache/maven/project/artifact/ActiveProjectArtifact.java b/maven-project/src/main/java/org/apache/maven/project/artifact/ActiveProjectArtifact.java
index fe77a66ca5..0d41e28a8d 100644
--- a/maven-project/src/main/java/org/apache/maven/project/artifact/ActiveProjectArtifact.java
+++ b/maven-project/src/main/java/org/apache/maven/project/artifact/ActiveProjectArtifact.java
@@ -260,4 +260,14 @@ public class ActiveProjectArtifact
     {
         artifact.setResolved( release );
     }
+
+    public List getAvailableVersions()
+    {
+        return artifact.getAvailableVersions();
+    }
+
+    public void setAvailableVersions( List versions )
+    {
+        artifact.setAvailableVersions( versions );
+    }
 }
diff --git a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
index 9977ead375..cf51960af9 100644
--- a/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
+++ b/maven-project/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
@@ -18,13 +18,20 @@ package org.apache.maven.project.artifact;
 
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.metadata.ArtifactMetadata;
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 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.repository.metadata.ArtifactRepositoryMetadata;
+import org.apache.maven.artifact.repository.metadata.Metadata;
+import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
+import org.apache.maven.artifact.repository.metadata.Versioning;
+import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
 import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.model.Dependency;
@@ -36,9 +43,15 @@ import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectBuilder;
 import org.apache.maven.project.ProjectBuildingException;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.util.IOUtil;
 import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -48,20 +61,22 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @author <a href="mailto:brett@apache.org">Brett Porter</a>
  * @version $Id$
  */
 public class MavenMetadataSource
     extends AbstractLogEnabled
     implements ArtifactMetadataSource
 {
-
     public static final String ROLE_HINT = "maven";
 
     private MavenProjectBuilder mavenProjectBuilder;
 
     private ArtifactFactory artifactFactory;
 
+    private RepositoryMetadataManager repositoryMetadataManager;
+
     /**
      * Retrieve the metadata for the project from the repository.
      * Uses the ProjectBuilder, to enable post-processing and inheritance calculation before retrieving the
@@ -88,8 +103,8 @@ public class MavenMetadataSource
             {
                 try
                 {
-                    project = mavenProjectBuilder
-                        .buildFromRepository( pomArtifact, remoteRepositories, localRepository );
+                    project = mavenProjectBuilder.buildFromRepository( pomArtifact, remoteRepositories,
+                                                                       localRepository );
                 }
                 catch ( InvalidModelException e )
                 {
@@ -256,4 +271,107 @@ public class MavenMetadataSource
 
         return projectArtifacts;
     }
+
+    public List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
+                                           List remoteRepositories )
+        throws ArtifactMetadataRetrievalException
+    {
+        ArtifactMetadata metadata = new ArtifactRepositoryMetadata( artifact );
+        repositoryMetadataManager.resolve( metadata, remoteRepositories, localRepository );
+
+        // TODO: this has been ripped from AbstractVersionTransformation - stop duplication
+        Versioning versioning = null;
+        for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); )
+        {
+            ArtifactRepository repository = (ArtifactRepository) i.next();
+
+            versioning = loadVersioningInformation( metadata, repository, localRepository, artifact );
+            if ( versioning != null )
+            {
+                artifact.setRepository( repository );
+                // TODO: merge instead (see above)
+                break;
+            }
+        }
+        Versioning v = loadVersioningInformation( metadata, localRepository, localRepository, artifact );
+        if ( v != null )
+        {
+            versioning = v;
+            // TODO: figure out way to avoid duplicated message
+            if ( getLogger().isDebugEnabled() /*&& !alreadyResolved*/ )
+            {
+                // Locally installed file is newer, don't use the resolved version
+                getLogger().debug( artifact.getArtifactId() + ": using locally installed snapshot" );
+            }
+        }
+
+        List versions;
+        if ( versioning != null )
+        {
+            versions = new ArrayList( versioning.getVersions().size() );
+            for ( Iterator i = versioning.getVersions().iterator(); i.hasNext(); )
+            {
+                String version = (String) i.next();
+                versions.add( new DefaultArtifactVersion( version ) );
+            }
+        }
+        else
+        {
+            versions = Collections.EMPTY_LIST;
+        }
+
+        return versions;
+    }
+
+    private Versioning loadVersioningInformation( ArtifactMetadata repoMetadata, ArtifactRepository remoteRepository,
+                                                    ArtifactRepository localRepository, Artifact artifact )
+        throws ArtifactMetadataRetrievalException
+    {
+        File metadataFile = new File( localRepository.getBasedir(),
+                                      localRepository.pathOfLocalRepositoryMetadata( repoMetadata, remoteRepository ) );
+
+        Versioning versioning = null;
+        if ( metadataFile.exists() )
+        {
+            Metadata metadata = readMetadata( metadataFile );
+            versioning = metadata.getVersioning();
+        }
+        return versioning;
+    }
+
+    /**
+     * @todo share with DefaultPluginMappingManager.
+     */
+    private static Metadata readMetadata( File mappingFile )
+        throws ArtifactMetadataRetrievalException
+    {
+        Metadata result;
+
+        Reader fileReader = null;
+        try
+        {
+            fileReader = new FileReader( mappingFile );
+
+            MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
+
+            result = mappingReader.read( fileReader );
+        }
+        catch ( FileNotFoundException e )
+        {
+            throw new ArtifactMetadataRetrievalException( "Cannot read version information from: " + mappingFile, e );
+        }
+        catch ( IOException e )
+        {
+            throw new ArtifactMetadataRetrievalException( "Cannot read version information from: " + mappingFile, e );
+        }
+        catch ( XmlPullParserException e )
+        {
+            throw new ArtifactMetadataRetrievalException( "Cannot parse version information from: " + mappingFile, e );
+        }
+        finally
+        {
+            IOUtil.close( fileReader );
+        }
+        return result;
+    }
 }
diff --git a/maven-project/src/main/resources/META-INF/plexus/components.xml b/maven-project/src/main/resources/META-INF/plexus/components.xml
index eb6c2eeaee..6fd727eb1f 100644
--- a/maven-project/src/main/resources/META-INF/plexus/components.xml
+++ b/maven-project/src/main/resources/META-INF/plexus/components.xml
@@ -175,6 +175,9 @@
         <requirement>
           <role>org.apache.maven.artifact.factory.ArtifactFactory</role>
         </requirement>
+        <requirement>
+          <role>org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager</role>
+        </requirement>
       </requirements>
     </component>
   </components>
diff --git a/maven-project/src/test/java/org/apache/maven/project/TestArtifactResolver.java b/maven-project/src/test/java/org/apache/maven/project/TestArtifactResolver.java
index d3b4f4f0a8..c0f3bb22e0 100644
--- a/maven-project/src/test/java/org/apache/maven/project/TestArtifactResolver.java
+++ b/maven-project/src/test/java/org/apache/maven/project/TestArtifactResolver.java
@@ -136,6 +136,12 @@ public class TestArtifactResolver
             return new ResolutionGroup( artifact, artifacts, artifactRepositories );
         }
 
+        public List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
+                                               List remoteRepositories )
+        {
+            throw new UnsupportedOperationException( "Cannot get available versions in this test case" );
+        }
+
         protected Set createArtifacts( List dependencies, String inheritedScope )
             throws InvalidVersionSpecificationException
         {
@@ -146,11 +152,11 @@ public class TestArtifactResolver
                 Dependency d = (Dependency) i.next();
 
                 String scope = d.getScope();
-                
+
                 if ( StringUtils.isEmpty( scope ) )
                 {
                     scope = Artifact.SCOPE_COMPILE;
-                    
+
                     d.setScope( scope );
                 }