You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2024/05/02 15:10:43 UTC

(maven) branch master updated: Fix consumer pom builder (#1491)

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new 64e9447926 Fix consumer pom builder (#1491)
64e9447926 is described below

commit 64e944792613e241b3faddcb4c793e147f6faa5e
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu May 2 17:10:38 2024 +0200

    Fix consumer pom builder (#1491)
---
 .../main/java/org/apache/maven/api/Session.java    |   4 +
 .../apache/maven/api/services/LookupException.java |   5 +
 .../maven/api/services/ModelBuilderRequest.java    |  42 +++-
 .../org/apache/maven/api/services}/ModelCache.java |   4 +-
 ...upException.java => ModelRepositoryHolder.java} |  31 +--
 .../apache/maven/api/services/ModelResolver.java   | 104 +++-----
 .../org/apache/maven/api/services/PathSource.java  |   5 +
 .../maven/api/services/RepositoryFactory.java      |   9 +
 maven-api-impl/pom.xml                             |   5 +
 .../internal/impl/DefaultArtifactResolver.java     |   2 +-
 .../maven/internal/impl/DefaultBuilderProblem.java |   2 +-
 .../internal/impl/DefaultRepositoryFactory.java    |  30 +++
 .../internal/impl/model/DefaultModelBuilder.java   | 125 ++++++----
 .../resolver/DefaultArtifactDescriptorReader.java  |  19 +-
 .../internal/impl/resolver/DefaultModelCache.java  |  28 ++-
 .../resolver/DefaultModelRepositoryHolder.java     | 112 +++++++++
 .../impl/resolver/DefaultModelResolver.java        | 212 ++---------------
 .../impl/resolver/DefaultModelResolverTest.java    | 207 ++++++++++++++++
 .../impl/standalone/RepositorySystemSupplier.java  |   3 +-
 .../impl/standalone/TestApiStandalone.java         |   8 +-
 .../remote-repo/org/apache/apache/1/apache-1.pom   |  82 +++++++
 .../org/apache/apache/maven-metadata.xml           |  13 +
 .../org/apache/maven/its/a/0.1/a-0.1.jar           | Bin 0 -> 1898 bytes
 .../org/apache/maven/its/a/0.1/a-0.1.pom           |  41 ++++
 .../org/apache/maven/its/a/maven-metadata.xml      |  12 +
 .../org/apache/maven/its/b/0.1/b-0.1.jar           | Bin 0 -> 1936 bytes
 .../org/apache/maven/its/b/0.1/b-0.1.pom           |  49 ++++
 .../org/apache/maven/its/b/maven-metadata.xml      |  12 +
 .../org/apache/maven/its/bom/0.1/bom-0.1.pom       |  21 ++
 .../org/apache/maven/its/bom/maven-metadata.xml    |  11 +
 .../org/apache/maven/its/parent/0.1/parent-0.1.pom |  22 ++
 .../org/apache/maven/its/parent/maven-metadata.xml |  11 +
 .../maven-it-plugin/0.1/maven-it-plugin-0.1.jar    | Bin 0 -> 13520 bytes
 .../maven-it-plugin/0.1/maven-it-plugin-0.1.pom    |  70 ++++++
 .../maven/its/plugins/maven-it-plugin/0.1/pom.xml  |  70 ++++++
 .../its/plugins/maven-it-plugin/maven-metadata.xml |  14 ++
 .../apache/maven/its/plugins/maven-metadata.xml    |  10 +
 .../maven-plugin-api/2.0/maven-plugin-api-2.0.jar  | Bin 0 -> 10133 bytes
 .../maven-plugin-api/2.0/maven-plugin-api-2.0.pom  |  23 ++
 .../org/apache/maven/maven/2.0/maven-2.0.pom       | 264 +++++++++++++++++++++
 .../0.1/maven-clean-plugin-0.1.jar                 | Bin 0 -> 6767 bytes
 .../0.1/maven-clean-plugin-0.1.pom                 |  70 ++++++
 .../plugins/maven-clean-plugin/maven-metadata.xml  |  14 ++
 .../0.1/maven-compiler-plugin-0.1.jar              | Bin 0 -> 8085 bytes
 .../0.1/maven-compiler-plugin-0.1.pom              |  70 ++++++
 .../maven-compiler-plugin/maven-metadata.xml       |  14 ++
 .../0.1/maven-deploy-plugin-0.1.jar                | Bin 0 -> 6777 bytes
 .../0.1/maven-deploy-plugin-0.1.pom                |  70 ++++++
 .../plugins/maven-deploy-plugin/maven-metadata.xml |  14 ++
 .../0.1/maven-install-plugin-0.1.jar               | Bin 0 -> 6781 bytes
 .../0.1/maven-install-plugin-0.1.pom               |  70 ++++++
 .../maven-install-plugin/maven-metadata.xml        |  14 ++
 .../maven-jar-plugin/0.1/maven-jar-plugin-0.1.jar  | Bin 0 -> 6790 bytes
 .../maven-jar-plugin/0.1/maven-jar-plugin-0.1.pom  |  70 ++++++
 .../plugins/maven-jar-plugin/maven-metadata.xml    |  14 ++
 .../org/apache/maven/plugins/maven-metadata.xml    |  45 ++++
 .../0.1/maven-plugin-plugin-0.1.jar                | Bin 0 -> 8007 bytes
 .../0.1/maven-plugin-plugin-0.1.pom                |  70 ++++++
 .../plugins/maven-plugin-plugin/maven-metadata.xml |  14 ++
 .../0.1/maven-resources-plugin-0.1.jar             | Bin 0 -> 8034 bytes
 .../0.1/maven-resources-plugin-0.1.pom             |  70 ++++++
 .../maven-resources-plugin/maven-metadata.xml      |  14 ++
 .../0.1/maven-surefire-plugin-0.1.jar              | Bin 0 -> 6827 bytes
 .../0.1/maven-surefire-plugin-0.1.pom              |  70 ++++++
 .../maven-surefire-plugin/maven-metadata.xml       |  14 ++
 .../plexus/plexus-utils/1.1/plexus-utils-1.1.jar   | Bin 0 -> 168568 bytes
 .../plexus/plexus-utils/1.1/plexus-utils-1.1.pom   |  27 +++
 .../maven/AbstractCoreMavenComponentTestCase.java  |  14 +-
 .../test/java/org/apache/maven/SimpleLookup.java   |  68 ++++++
 .../apache/maven/project/TestModelResolver.java    |  31 +--
 .../repository/LegacyRepositorySystemTest.java     |  14 +-
 .../impl/DefaultConsumerPomBuilder.java            |  32 ++-
 .../maven/project/DefaultProjectBuilder.java       | 101 ++++----
 .../META-INF/maven/org.apache.maven.api.di.Inject  |  45 ++--
 .../java/org/apache/maven/MavenTestHelper.java     |  15 +-
 .../test/java/org/apache/maven/SimpleLookup.java   |  68 ++++++
 .../transformation/AbstractRepositoryTestCase.java |  15 +-
 .../impl/ConsumerPomBuilderTest.java               |  28 +++
 .../org/apache/maven/model/ModelBuilderTest.java   |  15 +-
 .../internal/BootstrapCoreExtensionManager.java    |   6 +-
 .../internal/MavenRepositorySystemSupplier.java    |   3 +-
 81 files changed, 2430 insertions(+), 451 deletions(-)

diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
index 8f817f4d0f..31aeb06b7b 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
@@ -37,6 +37,10 @@ import org.apache.maven.api.settings.Settings;
 /**
  * The session to install / deploy / resolve artifacts and dependencies.
  *
+ * TODO: move the remote repositories in the requests (plugins will need to access this list somehow)
+ * TODO: add request trace so that requests can be linked together and through the resolver
+ * TODO: add a Request interface holding session + parent request
+ *
  * @since 4.0.0
  */
 @Experimental
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
index b72d04b76e..ee67fa9bdc 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
@@ -27,6 +27,11 @@ import org.apache.maven.api.annotations.Experimental;
  */
 @Experimental
 public class LookupException extends MavenException {
+
+    public LookupException(String message) {
+        super(message);
+    }
+
     /**
      * @param message the message to give
      * @param e the {@link Exception}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java
index 23ce6de182..31e639867f 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java
@@ -37,7 +37,8 @@ import static org.apache.maven.api.services.BaseRequest.nonNull;
  * Request used to build a {@link org.apache.maven.api.Project} using
  * the {@link ProjectBuilder} service.
  *
- * TODO: add validationLevel, activeProfileIds, inactiveProfileIds, resolveDependencies
+ * TODO: replace ModelRepositoryHolder with just the enum for the strategy
+ * TODO: replace validation level with an enum (though, we usually need just a boolean)
  *
  * @since 4.0.0
  */
@@ -138,8 +139,15 @@ public interface ModelBuilderRequest {
     @Nonnull
     Map<String, String> getUserProperties();
 
+    @Nonnull
     ModelResolver getModelResolver();
 
+    @Nonnull
+    ModelRepositoryHolder getModelRepositoryHolder();
+
+    @Nullable
+    ModelCache getModelCache();
+
     @Nullable
     Object getListener();
 
@@ -197,6 +205,8 @@ public interface ModelBuilderRequest {
         Map<String, String> systemProperties;
         Map<String, String> userProperties;
         ModelResolver modelResolver;
+        ModelRepositoryHolder modelRepositoryHolder;
+        ModelCache modelCache;
         Object listener;
         ModelBuilderResult interimResult;
         ModelTransformerContextBuilder transformerContextBuilder;
@@ -217,6 +227,8 @@ public interface ModelBuilderRequest {
             this.systemProperties = request.getSystemProperties();
             this.userProperties = request.getUserProperties();
             this.modelResolver = request.getModelResolver();
+            this.modelRepositoryHolder = request.getModelRepositoryHolder();
+            this.modelCache = request.getModelCache();
             this.listener = request.getListener();
             this.interimResult = request.getInterimResult();
             this.transformerContextBuilder = request.getTransformerContextBuilder();
@@ -287,6 +299,16 @@ public interface ModelBuilderRequest {
             return this;
         }
 
+        public ModelBuilderRequestBuilder modelRepositoryHolder(ModelRepositoryHolder modelRepositoryHolder) {
+            this.modelRepositoryHolder = modelRepositoryHolder;
+            return this;
+        }
+
+        public ModelBuilderRequestBuilder modelCache(ModelCache modelCache) {
+            this.modelCache = modelCache;
+            return this;
+        }
+
         public ModelBuilderRequestBuilder listener(Object listener) {
             this.listener = listener;
             return this;
@@ -318,6 +340,8 @@ public interface ModelBuilderRequest {
                     systemProperties,
                     userProperties,
                     modelResolver,
+                    modelRepositoryHolder,
+                    modelCache,
                     listener,
                     interimResult,
                     transformerContextBuilder);
@@ -336,6 +360,8 @@ public interface ModelBuilderRequest {
             private final Map<String, String> systemProperties;
             private final Map<String, String> userProperties;
             private final ModelResolver modelResolver;
+            private final ModelRepositoryHolder modelRepositoryHolder;
+            private final ModelCache modelCache;
             private final Object listener;
             private final ModelBuilderResult interimResult;
             private final ModelTransformerContextBuilder transformerContextBuilder;
@@ -355,6 +381,8 @@ public interface ModelBuilderRequest {
                     Map<String, String> systemProperties,
                     Map<String, String> userProperties,
                     ModelResolver modelResolver,
+                    ModelRepositoryHolder modelRepositoryHolder,
+                    ModelCache modelCache,
                     Object listener,
                     ModelBuilderResult interimResult,
                     ModelTransformerContextBuilder transformerContextBuilder) {
@@ -372,6 +400,8 @@ public interface ModelBuilderRequest {
                         systemProperties != null ? Map.copyOf(systemProperties) : session.getSystemProperties();
                 this.userProperties = userProperties != null ? Map.copyOf(userProperties) : session.getUserProperties();
                 this.modelResolver = modelResolver;
+                this.modelRepositoryHolder = modelRepositoryHolder;
+                this.modelCache = modelCache;
                 this.listener = listener;
                 this.interimResult = interimResult;
                 this.transformerContextBuilder = transformerContextBuilder;
@@ -437,6 +467,16 @@ public interface ModelBuilderRequest {
                 return modelResolver;
             }
 
+            @Override
+            public ModelRepositoryHolder getModelRepositoryHolder() {
+                return modelRepositoryHolder;
+            }
+
+            @Override
+            public ModelCache getModelCache() {
+                return modelCache;
+            }
+
             public Object getListener() {
                 return listener;
             }
diff --git a/maven-api-impl/src/main/java/org/apache/maven/api/services/model/ModelCache.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelCache.java
similarity index 94%
rename from maven-api-impl/src/main/java/org/apache/maven/api/services/model/ModelCache.java
rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelCache.java
index 39b4179c09..b928c3c8e4 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/api/services/model/ModelCache.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelCache.java
@@ -16,12 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.api.services.model;
+package org.apache.maven.api.services;
 
 import java.util.function.Supplier;
 
-import org.apache.maven.api.services.Source;
-
 /**
  * Caches auxiliary data used during model building like already processed raw/effective models. The data in the cache
  * is meant for exclusive consumption by the model builder and is opaque to the cache implementation. The cache key is
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelRepositoryHolder.java
similarity index 62%
copy from api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
copy to api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelRepositoryHolder.java
index b72d04b76e..3be93256be 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelRepositoryHolder.java
@@ -18,27 +18,16 @@
  */
 package org.apache.maven.api.services;
 
-import org.apache.maven.api.annotations.Experimental;
+import java.util.List;
 
-/**
- * The Exception class throw by the {@link Lookup} service.
- *
- * @since 4.0.0
- */
-@Experimental
-public class LookupException extends MavenException {
-    /**
-     * @param message the message to give
-     * @param e the {@link Exception}
-     */
-    public LookupException(String message, Exception e) {
-        super(message, e);
-    }
+import org.apache.maven.api.RemoteRepository;
+import org.apache.maven.api.model.Repository;
+
+public interface ModelRepositoryHolder {
+
+    void merge(List<Repository> repos, boolean replace);
+
+    List<RemoteRepository> getRepositories();
 
-    /**
-     * @param e the {@link Exception}
-     */
-    public LookupException(Exception e) {
-        super(e);
-    }
+    ModelRepositoryHolder copy();
 }
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelResolver.java
index 72a114a80e..560cbd0186 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelResolver.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelResolver.java
@@ -19,107 +19,67 @@
 package org.apache.maven.api.services;
 
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
 
 import org.apache.maven.api.Service;
 import org.apache.maven.api.Session;
 import org.apache.maven.api.annotations.Nonnull;
 import org.apache.maven.api.model.Dependency;
 import org.apache.maven.api.model.Parent;
-import org.apache.maven.api.model.Repository;
 
 /**
- * Resolves a POM from its coordinates. During the build process, the
- * {@link org.apache.maven.api.services.ModelBuilder} will add any relevant repositories to the model resolver. In
- * other words, the model resolver is stateful and should not be reused across multiple model building requests.
- *
+ * Resolves a POM from its coordinates.
  */
 public interface ModelResolver extends Service {
 
-    /**
-     * Tries to resolve the POM for the specified coordinates.
-     *
-     * @param groupId The group identifier of the POM, must not be {@code null}.
-     * @param artifactId The artifact identifier of the POM, must not be {@code null}.
-     * @param version The version of the POM, must not be {@code null}.
-     * @return The source of the requested POM, never {@code null}.
-     * @throws ModelResolverException If the POM could not be resolved from any configured repository.
-     */
-    @Nonnull
-    ModelSource resolveModel(
-            @Nonnull Session session, @Nonnull String groupId, @Nonnull String artifactId, @Nonnull String version)
-            throws ModelResolverException;
-
     /**
      * Tries to resolve the POM for the specified parent coordinates possibly updating {@code parent}.
-     * <p>
-     * Unlike the {@link #resolveModel(Session, String, String, String)} method, this method
-     * supports version ranges and updates the given {@code parent} instance to match the returned {@code ModelSource}.
-     * If {@code parent} declares a version range, the version corresponding to the returned {@code ModelSource} will
-     * be set on the given {@code parent}.
-     * </p>
      *
+     * @param session The session to use to resolve the model, must not be {@code null}.
      * @param parent The parent coordinates to resolve, must not be {@code null}.
-     *
+     * @param modified a holder for the updated parent, must not be {@code null}.
      * @return The source of the requested POM, never {@code null}.
-     *
      * @throws ModelResolverException If the POM could not be resolved from any configured repository.
      */
     @Nonnull
-    ModelSource resolveModel(
+    default ModelSource resolveModel(
             @Nonnull Session session, @Nonnull Parent parent, @Nonnull AtomicReference<Parent> modified)
-            throws ModelResolverException;
+            throws ModelResolverException {
+        return resolveModel(
+                session,
+                parent.getGroupId(),
+                parent.getArtifactId(),
+                parent.getVersion(),
+                version -> modified.set(parent.withVersion(version)));
+    }
 
     /**
      * Tries to resolve the POM for the specified dependency coordinates possibly updating {@code dependency}.
-     * <p>
-     * Unlike the {@link #resolveModel(Session, String, String, String)} method, this method
-     * supports version ranges and updates the given {@code dependency} instance to match the returned
-     * {@code ModelSource}. If {@code dependency} declares a version range, the version corresponding to the returned
-     * {@code ModelSource} will be set on the given {@code dependency}.
-     * </p>
      *
+     * @param session The session to use to resolve the model, must not be {@code null}.
      * @param dependency The dependency coordinates to resolve, must not be {@code null}.
-     *
+     * @param modified a holder for the updated dependency, must not be {@code null}.
      * @return The source of the requested POM, never {@code null}.
-     *
      * @throws ModelResolverException If the POM could not be resolved from any configured repository.
-     *
-     * @see Dependency#clone()
      */
     @Nonnull
-    ModelSource resolveModel(
+    default ModelSource resolveModel(
             @Nonnull Session session, @Nonnull Dependency dependency, @Nonnull AtomicReference<Dependency> modified)
-            throws ModelResolverException;
+            throws ModelResolverException {
+        return resolveModel(
+                session,
+                dependency.getGroupId(),
+                dependency.getArtifactId(),
+                dependency.getVersion(),
+                version -> modified.set(dependency.withVersion(version)));
+    }
 
-    /**
-     * Adds a repository to use for subsequent resolution requests. The order in which repositories are added matters,
-     * repositories that were added first should also be searched first. When multiple repositories with the same
-     * identifier are added, only the first repository being added will be used.
-     *
-     * @param repository The repository to add to the internal search chain, must not be {@code null}.
-     * @throws ModelResolverException If the repository could not be added (e.g. due to invalid URL or layout).
-     */
-    void addRepository(@Nonnull Session session, Repository repository) throws ModelResolverException;
-
-    /**
-     * Adds a repository to use for subsequent resolution requests. The order in which repositories are added matters,
-     * repositories that were added first should also be searched first. When multiple repositories with the same
-     * identifier are added, then the value of the replace argument determines the behaviour.
-     *
-     * If replace is false then any existing repository with the same Id will remain in use. If replace
-     * is true the new repository replaces the original.
-     *
-     * @param repository The repository to add to the internal search chain, must not be {@code null}.
-     * @throws ModelResolverException If the repository could not be added (e.g. due to invalid URL or layout).
-     */
-    void addRepository(@Nonnull Session session, Repository repository, boolean replace) throws ModelResolverException;
-
-    /**
-     * Clones this resolver for usage in a forked resolution process. In general, implementors need not provide a deep
-     * clone. The only requirement is that invocations of {@link #addRepository(Session, Repository)} on the clone do not affect
-     * the state of the original resolver and vice versa.
-     *
-     * @return The cloned resolver, never {@code null}.
-     */
-    ModelResolver newCopy();
+    @Nonnull
+    ModelSource resolveModel(
+            @Nonnull Session session,
+            @Nonnull String groupId,
+            @Nonnull String artifactId,
+            @Nonnull String version,
+            @Nonnull Consumer<String> resolvedVersion)
+            throws ModelResolverException;
 }
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PathSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PathSource.java
index 9b3ce52220..4ceda1c8ae 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PathSource.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PathSource.java
@@ -79,4 +79,9 @@ class PathSource implements ModelSource {
     public int hashCode() {
         return Objects.hash(path);
     }
+
+    @Override
+    public String toString() {
+        return "PathSource[" + "location='" + location + '\'' + ", " + "path=" + path + ']';
+    }
 }
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java
index c04728f960..abd7ff9670 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java
@@ -19,10 +19,12 @@
 package org.apache.maven.api.services;
 
 import java.nio.file.Path;
+import java.util.List;
 
 import org.apache.maven.api.LocalRepository;
 import org.apache.maven.api.RemoteRepository;
 import org.apache.maven.api.Service;
+import org.apache.maven.api.Session;
 import org.apache.maven.api.annotations.Experimental;
 import org.apache.maven.api.annotations.Nonnull;
 import org.apache.maven.api.model.Repository;
@@ -43,4 +45,11 @@ public interface RepositoryFactory extends Service {
 
     @Nonnull
     RemoteRepository createRemote(@Nonnull Repository repository);
+
+    @Nonnull
+    List<RemoteRepository> aggregate(
+            @Nonnull Session session,
+            @Nonnull List<RemoteRepository> dominant,
+            @Nonnull List<RemoteRepository> recessive,
+            boolean processRecessive);
 }
diff --git a/maven-api-impl/pom.xml b/maven-api-impl/pom.xml
index 344bc9c6b4..9ff181d294 100644
--- a/maven-api-impl/pom.xml
+++ b/maven-api-impl/pom.xml
@@ -118,6 +118,11 @@ under the License.
       <artifactId>mockito-junit-jupiter</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-di</artifactId>
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java
index 72ae752e32..9fe55007b2 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java
@@ -76,7 +76,7 @@ public class DefaultArtifactResolver implements ArtifactResolver {
             }
             return () -> paths;
         } catch (ArtifactResolutionException e) {
-            throw new ArtifactResolverException("Unable to resolve artifact", e);
+            throw new ArtifactResolverException("Unable to resolve artifact: " + e.getMessage(), e);
         }
     }
 }
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultBuilderProblem.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultBuilderProblem.java
index 95ffe21cd1..b69a23110f 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultBuilderProblem.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultBuilderProblem.java
@@ -76,7 +76,7 @@ class DefaultBuilderProblem implements BuilderProblem {
     @Override
     public String getLocation() {
         StringBuilder buffer = new StringBuilder(256);
-        if (!getSource().isEmpty()) {
+        if (getSource() != null && !getSource().isEmpty()) {
             buffer.append(getSource());
         }
         if (getLineNumber() > 0) {
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java
index 2a85389e4e..9eff11343f 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java
@@ -19,19 +19,32 @@
 package org.apache.maven.internal.impl;
 
 import java.nio.file.Path;
+import java.util.List;
 
 import org.apache.maven.api.LocalRepository;
 import org.apache.maven.api.RemoteRepository;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Inject;
 import org.apache.maven.api.di.Named;
 import org.apache.maven.api.di.Singleton;
 import org.apache.maven.api.model.Repository;
 import org.apache.maven.api.services.RepositoryFactory;
+import org.eclipse.aether.impl.RemoteRepositoryManager;
 import org.eclipse.aether.repository.RepositoryPolicy;
 
+import static org.apache.maven.internal.impl.Utils.nonNull;
+
 @Named
 @Singleton
 public class DefaultRepositoryFactory implements RepositoryFactory {
 
+    final RemoteRepositoryManager remoteRepositoryManager;
+
+    @Inject
+    public DefaultRepositoryFactory(RemoteRepositoryManager remoteRepositoryManager) {
+        this.remoteRepositoryManager = remoteRepositoryManager;
+    }
+
     @Override
     public LocalRepository createLocal(Path path) {
         return new DefaultLocalRepository(new org.eclipse.aether.repository.LocalRepository(path.toFile()));
@@ -52,6 +65,23 @@ public class DefaultRepositoryFactory implements RepositoryFactory {
                 .build());
     }
 
+    @Override
+    public List<RemoteRepository> aggregate(
+            Session session,
+            List<RemoteRepository> dominant,
+            List<RemoteRepository> recessive,
+            boolean processRecessive) {
+        InternalSession internalSession = InternalSession.from(nonNull(session, "session"));
+        List<org.eclipse.aether.repository.RemoteRepository> repos = remoteRepositoryManager.aggregateRepositories(
+                internalSession.getSession(),
+                internalSession.toRepositories(nonNull(dominant, "dominant")),
+                internalSession.toRepositories(nonNull(recessive, "recessive")),
+                processRecessive);
+        return repos.stream()
+                .<RemoteRepository>map(DefaultRemoteRepository::new)
+                .toList();
+    }
+
     public static org.eclipse.aether.repository.RepositoryPolicy buildRepositoryPolicy(
             org.apache.maven.api.model.RepositoryPolicy policy) {
         boolean enabled = true;
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java
index 43bdd649ee..47ef58d451 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java
@@ -39,6 +39,7 @@ import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import org.apache.maven.api.Session;
 import org.apache.maven.api.VersionRange;
 import org.apache.maven.api.annotations.Nullable;
 import org.apache.maven.api.di.Inject;
@@ -64,6 +65,7 @@ import org.apache.maven.api.services.ModelBuilder;
 import org.apache.maven.api.services.ModelBuilderException;
 import org.apache.maven.api.services.ModelBuilderRequest;
 import org.apache.maven.api.services.ModelBuilderResult;
+import org.apache.maven.api.services.ModelCache;
 import org.apache.maven.api.services.ModelProblem;
 import org.apache.maven.api.services.ModelProblemCollector;
 import org.apache.maven.api.services.ModelResolver;
@@ -77,11 +79,10 @@ import org.apache.maven.api.services.Source;
 import org.apache.maven.api.services.SuperPomProvider;
 import org.apache.maven.api.services.VersionParserException;
 import org.apache.maven.api.services.model.*;
-import org.apache.maven.api.services.model.ModelCache;
 import org.apache.maven.api.services.xml.XmlReaderException;
 import org.apache.maven.api.services.xml.XmlReaderRequest;
-import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.internal.impl.resolver.DefaultModelCache;
+import org.apache.maven.internal.impl.resolver.DefaultModelRepositoryHolder;
 import org.apache.maven.internal.impl.resolver.DefaultModelResolver;
 import org.apache.maven.model.v4.MavenTransformer;
 import org.codehaus.plexus.interpolation.InterpolationException;
@@ -89,7 +90,8 @@ import org.codehaus.plexus.interpolation.Interpolator;
 import org.codehaus.plexus.interpolation.MapBasedValueSource;
 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
-import org.eclipse.aether.impl.RemoteRepositoryManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  */
@@ -101,6 +103,8 @@ public class DefaultModelBuilder implements ModelBuilder {
     private static final String FILE = "file";
     private static final String IMPORT = "import";
 
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
     private final ModelProcessor modelProcessor;
     private final ModelValidator modelValidator;
     private final ModelNormalizer modelNormalizer;
@@ -119,7 +123,6 @@ public class DefaultModelBuilder implements ModelBuilder {
     private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
     private final ModelTransformer transformer;
     private final ModelVersionParser versionParser;
-    private final RemoteRepositoryManager remoteRepositoryManager;
 
     @SuppressWarnings("checkstyle:ParameterNumber")
     @Inject
@@ -141,8 +144,7 @@ public class DefaultModelBuilder implements ModelBuilder {
             PluginConfigurationExpander pluginConfigurationExpander,
             ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator,
             ModelTransformer transformer,
-            ModelVersionParser versionParser,
-            RemoteRepositoryManager remoteRepositoryManager) {
+            ModelVersionParser versionParser) {
         this.modelProcessor = modelProcessor;
         this.modelValidator = modelValidator;
         this.modelNormalizer = modelNormalizer;
@@ -161,7 +163,6 @@ public class DefaultModelBuilder implements ModelBuilder {
         this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
         this.transformer = transformer;
         this.versionParser = versionParser;
-        this.remoteRepositoryManager = remoteRepositoryManager;
     }
 
     @Override
@@ -171,6 +172,7 @@ public class DefaultModelBuilder implements ModelBuilder {
 
     @Override
     public ModelBuilderResult build(ModelBuilderRequest request) throws ModelBuilderException {
+        request = fillRequestDefaults(request);
         if (request.getInterimResult() != null) {
             return build(request, request.getInterimResult(), new LinkedHashSet<>());
         } else {
@@ -178,6 +180,23 @@ public class DefaultModelBuilder implements ModelBuilder {
         }
     }
 
+    private static ModelBuilderRequest fillRequestDefaults(ModelBuilderRequest request) {
+        ModelBuilderRequest.ModelBuilderRequestBuilder builder = ModelBuilderRequest.builder(request);
+        if (request.getModelCache() == null) {
+            builder.modelCache(new DefaultModelCache());
+        }
+        if (request.getModelRepositoryHolder() == null) {
+            builder.modelRepositoryHolder(new DefaultModelRepositoryHolder(
+                    request.getSession(),
+                    DefaultModelRepositoryHolder.RepositoryMerging.POM_DOMINANT,
+                    request.getSession().getRemoteRepositories()));
+        }
+        if (request.getModelResolver() == null) {
+            builder.modelResolver(new DefaultModelResolver());
+        }
+        return builder.build();
+    }
+
     protected ModelBuilderResult build(ModelBuilderRequest request, Collection<String> importIds)
             throws ModelBuilderException {
         // phase 1
@@ -322,7 +341,19 @@ public class DefaultModelBuilder implements ModelBuilder {
             }
 
             // add repositories specified by the current model so that we can resolve the parent
-            configureResolver(getModelResolver(request), model, request, problems, false);
+            if (!model.getRepositories().isEmpty()) {
+                List<String> oldRepos = request.getModelRepositoryHolder().getRepositories().stream()
+                        .map(Object::toString)
+                        .toList();
+                request.getModelRepositoryHolder().merge(model.getRepositories(), false);
+                List<String> newRepos = request.getModelRepositoryHolder().getRepositories().stream()
+                        .map(Object::toString)
+                        .toList();
+                if (!Objects.equals(oldRepos, newRepos)) {
+                    logger.debug("Merging repositories from " + model.getId() + "\n"
+                            + newRepos.stream().map(s -> "    " + s).collect(Collectors.joining("\n")));
+                }
+            }
 
             // we pass a cloned model, so that resolving the parent version does not affect the returned model
             ModelData parentData = readParent(model, currentData.source(), request, problems);
@@ -376,7 +407,19 @@ public class DefaultModelBuilder implements ModelBuilder {
         result.setEffectiveModel(resultModel);
 
         // Now the fully interpolated model is available: reconfigure the resolver
-        configureResolver(getModelResolver(request), resultModel, request, problems, true);
+        if (!resultModel.getRepositories().isEmpty()) {
+            List<String> oldRepos = request.getModelRepositoryHolder().getRepositories().stream()
+                    .map(Object::toString)
+                    .toList();
+            request.getModelRepositoryHolder().merge(resultModel.getRepositories(), true);
+            List<String> newRepos = request.getModelRepositoryHolder().getRepositories().stream()
+                    .map(Object::toString)
+                    .toList();
+            if (!Objects.equals(oldRepos, newRepos)) {
+                logger.debug("Replacing repositories from " + resultModel.getId() + "\n"
+                        + newRepos.stream().map(s -> "    " + s).collect(Collectors.joining("\n")));
+            }
+        }
 
         return resultModel;
     }
@@ -472,7 +515,8 @@ public class DefaultModelBuilder implements ModelBuilder {
         return build(request, result, new LinkedHashSet<>());
     }
 
-    public Model buildRawModel(final ModelBuilderRequest request) throws ModelBuilderException {
+    public Model buildRawModel(ModelBuilderRequest request) throws ModelBuilderException {
+        request = fillRequestDefaults(request);
         DefaultModelProblemCollector problems = new DefaultModelProblemCollector(new DefaultModelBuilderResult());
         Model model = readRawModel(request, problems);
         if (hasModelErrors(problems)) {
@@ -484,15 +528,6 @@ public class DefaultModelBuilder implements ModelBuilder {
     private ModelBuilderResult build(
             ModelBuilderRequest request, final ModelBuilderResult phaseOneResult, Collection<String> importIds)
             throws ModelBuilderException {
-        if (request.getModelResolver() == null) {
-            ModelResolver resolver = new DefaultModelResolver(
-                    remoteRepositoryManager,
-                    InternalSession.from(request.getSession())
-                            .toRepositories(request.getSession().getRemoteRepositories()));
-            request =
-                    ModelBuilderRequest.builder(request).modelResolver(resolver).build();
-        }
-
         DefaultModelBuilderResult result = asDefaultModelBuilderResult(phaseOneResult);
 
         DefaultModelProblemCollector problems = new DefaultModelProblemCollector(result);
@@ -756,15 +791,6 @@ public class DefaultModelBuilder implements ModelBuilder {
         return context;
     }
 
-    private void configureResolver(
-            ModelResolver modelResolver,
-            Model model,
-            ModelBuilderRequest request,
-            DefaultModelProblemCollector problems,
-            boolean replaceRepositories) {
-        model.getRepositories().forEach(r -> modelResolver.addRepository(request.getSession(), r, replaceRepositories));
-    }
-
     private void checkPluginVersions(List<Model> lineage, ModelBuilderRequest request, ModelProblemCollector problems) {
         if (request.getValidationLevel() < ModelBuilderRequest.VALIDATION_LEVEL_MAVEN_2_0) {
             return;
@@ -875,7 +901,9 @@ public class DefaultModelBuilder implements ModelBuilder {
 
         Parent parent = childModel.getParent();
         if (parent != null) {
-            parentData = readParentLocally(childModel, childSource, request, problems);
+            if (request.isProjectBuild()) {
+                parentData = readParentLocally(childModel, childSource, request, problems);
+            }
             if (parentData == null) {
                 parentData = readParentExternally(childModel, request, problems);
             }
@@ -1043,7 +1071,9 @@ public class DefaultModelBuilder implements ModelBuilder {
         ModelSource modelSource;
         try {
             AtomicReference<Parent> modified = new AtomicReference<>();
-            modelSource = modelResolver.resolveModel(request.getSession(), parent, modified);
+            Session session = request.getSession()
+                    .withRemoteRepositories(request.getModelRepositoryHolder().getRepositories());
+            modelSource = modelResolver.resolveModel(session, parent, modified);
             if (modified.get() != null) {
                 parent = modified.get();
             }
@@ -1209,7 +1239,7 @@ public class DefaultModelBuilder implements ModelBuilder {
             return null;
         }
 
-        DependencyManagement importMgmt = cache(
+        Model importModel = cache(
                 getModelCache(request),
                 groupId,
                 artifactId,
@@ -1217,6 +1247,10 @@ public class DefaultModelBuilder implements ModelBuilder {
                 IMPORT,
                 () -> doLoadDependencyManagement(
                         model, request, problems, dependency, groupId, artifactId, version, importIds));
+        DependencyManagement importMgmt = importModel.getDependencyManagement();
+        if (importMgmt == null) {
+            importMgmt = DependencyManagement.newInstance();
+        }
 
         // [MNG-5600] Dependency management import should support exclusions.
         List<Exclusion> exclusions = dependency.getExclusions();
@@ -1242,7 +1276,7 @@ public class DefaultModelBuilder implements ModelBuilder {
     }
 
     @SuppressWarnings("checkstyle:parameternumber")
-    private DependencyManagement doLoadDependencyManagement(
+    private Model doLoadDependencyManagement(
             Model model,
             ModelBuilderRequest request,
             DefaultModelProblemCollector problems,
@@ -1251,7 +1285,6 @@ public class DefaultModelBuilder implements ModelBuilder {
             String artifactId,
             String version,
             Collection<String> importIds) {
-        DependencyManagement importMgmt;
         final WorkspaceModelResolver workspaceResolver = getWorkspaceModelResolver(request);
         final ModelResolver modelResolver = getModelResolver(request);
         if (workspaceResolver == null && modelResolver == null) {
@@ -1274,7 +1307,10 @@ public class DefaultModelBuilder implements ModelBuilder {
         if (importModel == null) {
             final ModelSource importSource;
             try {
-                importSource = modelResolver.resolveModel(request.getSession(), dependency, new AtomicReference<>());
+                Session session = request.getSession()
+                        .withRemoteRepositories(
+                                request.getModelRepositoryHolder().getRepositories());
+                importSource = modelResolver.resolveModel(session, dependency, new AtomicReference<>());
             } catch (ModelBuilderException e) {
                 StringBuilder buffer = new StringBuilder(256);
                 buffer.append("Non-resolvable import POM");
@@ -1308,12 +1344,17 @@ public class DefaultModelBuilder implements ModelBuilder {
             final ModelBuilderResult importResult;
             try {
                 ModelBuilderRequest importRequest = ModelBuilderRequest.builder()
-                        .session(request.getSession())
+                        .session(request.getSession()
+                                .withRemoteRepositories(
+                                        request.getModelRepositoryHolder().getRepositories()))
                         .validationLevel(ModelBuilderRequest.VALIDATION_LEVEL_MINIMAL)
                         .systemProperties(request.getSystemProperties())
                         .userProperties(request.getUserProperties())
                         .source(importSource)
-                        .modelResolver(modelResolver.newCopy())
+                        .modelResolver(modelResolver)
+                        .modelCache(request.getModelCache())
+                        .modelRepositoryHolder(
+                                request.getModelRepositoryHolder().copy())
                         .twoPhaseBuilding(false)
                         .build();
                 importResult = build(importRequest, importIds);
@@ -1327,12 +1368,7 @@ public class DefaultModelBuilder implements ModelBuilder {
             importModel = importResult.getEffectiveModel();
         }
 
-        importMgmt = importModel.getDependencyManagement();
-
-        if (importMgmt == null) {
-            importMgmt = DependencyManagement.newInstance();
-        }
-        return importMgmt;
+        return importModel;
     }
 
     private static <T> T cache(
@@ -1409,10 +1445,7 @@ public class DefaultModelBuilder implements ModelBuilder {
     }
 
     private static ModelCache getModelCache(ModelBuilderRequest request) {
-        return request.isProjectBuild()
-                ? DefaultModelCache.newInstance(
-                        InternalSession.from(request.getSession()).getSession())
-                : null;
+        return request.getModelCache();
     }
 
     private static ModelBuildingListener getModelBuildingListener(ModelBuilderRequest request) {
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultArtifactDescriptorReader.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultArtifactDescriptorReader.java
index 4614067f9c..d8af5b4bfa 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultArtifactDescriptorReader.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultArtifactDescriptorReader.java
@@ -32,6 +32,7 @@ import org.apache.maven.api.services.ModelBuilder;
 import org.apache.maven.api.services.ModelBuilderException;
 import org.apache.maven.api.services.ModelBuilderRequest;
 import org.apache.maven.api.services.ModelProblem;
+import org.apache.maven.api.services.ModelRepositoryHolder;
 import org.apache.maven.api.services.ModelResolver;
 import org.apache.maven.api.services.ModelResolverException;
 import org.apache.maven.api.services.ModelSource;
@@ -189,14 +190,20 @@ public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader
             }
 
             try {
-                Session iSession = InternalSession.from(session);
+                InternalSession iSession = InternalSession.from(session);
+                Session iSessionWithRepos = iSession.withRemoteRepositories(request.getRepositories().stream()
+                        .map(iSession::getRemoteRepository)
+                        .toList());
                 String gav =
                         pomArtifact.getGroupId() + ":" + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion();
-                ModelResolver modelResolver =
-                        new DefaultModelResolver(remoteRepositoryManager, request.getRepositories());
+                ModelResolver modelResolver = new DefaultModelResolver();
+                ModelRepositoryHolder modelRepositoryHolder = new DefaultModelRepositoryHolder(
+                        iSessionWithRepos,
+                        DefaultModelRepositoryHolder.RepositoryMerging.REQUEST_DOMINANT,
+                        iSessionWithRepos.getRemoteRepositories());
                 ModelBuilderRequest modelRequest = ModelBuilderRequest.builder()
-                        .session(iSession)
-                        .projectBuild(true)
+                        .session(iSessionWithRepos)
+                        .projectBuild(false)
                         .processPlugins(false)
                         .twoPhaseBuilding(false)
                         .source(ModelSource.fromPath(pomArtifact.getPath(), gav))
@@ -205,6 +212,8 @@ public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader
                         .systemProperties(toProperties(session.getUserProperties(), session.getSystemProperties()))
                         .userProperties(Map.of())
                         .modelResolver(modelResolver)
+                        .modelRepositoryHolder(modelRepositoryHolder)
+                        .modelCache(DefaultModelCache.newInstance(session, false))
                         .build();
 
                 model = modelBuilder.build(modelRequest).getEffectiveModel();
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelCache.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelCache.java
index 2cc6fcba34..f21eaa8f26 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelCache.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelCache.java
@@ -23,8 +23,8 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Supplier;
 
+import org.apache.maven.api.services.ModelCache;
 import org.apache.maven.api.services.Source;
-import org.apache.maven.api.services.model.ModelCache;
 import org.eclipse.aether.RepositoryCache;
 import org.eclipse.aether.RepositorySystemSession;
 
@@ -38,20 +38,29 @@ public class DefaultModelCache implements ModelCache {
     private static final String KEY = DefaultModelCache.class.getName();
 
     @SuppressWarnings("unchecked")
-    public static ModelCache newInstance(RepositorySystemSession session) {
+    public static ModelCache newInstance(RepositorySystemSession session, boolean anew) {
         ConcurrentHashMap<Object, Supplier<?>> cache;
-        RepositoryCache repositoryCache = session.getCache();
+        RepositoryCache repositoryCache = session != null ? session.getCache() : null;
         if (repositoryCache == null) {
-            cache = new ConcurrentHashMap<>();
+            return new DefaultModelCache(new ConcurrentHashMap<>());
         } else {
-            cache = (ConcurrentHashMap<Object, Supplier<?>>)
-                    repositoryCache.computeIfAbsent(session, KEY, ConcurrentHashMap::new);
+            if (anew) {
+                cache = new ConcurrentHashMap<>();
+                repositoryCache.put(session, KEY, cache);
+            } else {
+                cache = (ConcurrentHashMap<Object, Supplier<?>>)
+                        repositoryCache.computeIfAbsent(session, KEY, ConcurrentHashMap::new);
+            }
+            return new DefaultModelCache(cache);
         }
-        return new DefaultModelCache(cache);
     }
 
     private final ConcurrentMap<Object, Supplier<?>> cache;
 
+    public DefaultModelCache() {
+        this(new ConcurrentHashMap<>());
+    }
+
     private DefaultModelCache(ConcurrentMap<Object, Supplier<?>> cache) {
         this.cache = requireNonNull(cache);
     }
@@ -125,7 +134,7 @@ public class DefaultModelCache implements ModelCache {
 
         @Override
         public String toString() {
-            return "GavCacheKey{" + "gav='" + gav + '\'' + ", tag='" + tag + '\'' + '}';
+            return "GavCacheKey[" + "gav='" + gav + '\'' + ", tag='" + tag + '\'' + ']';
         }
     }
 
@@ -144,7 +153,8 @@ public class DefaultModelCache implements ModelCache {
 
         @Override
         public String toString() {
-            return "SourceCacheKey{" + "source=" + source + ", tag='" + tag + '\'' + '}';
+            return "SourceCacheKey[" + "location=" + source.getLocation() + ", tag=" + tag + ", path="
+                    + source.getPath() + ']';
         }
 
         @Override
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelRepositoryHolder.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelRepositoryHolder.java
new file mode 100644
index 0000000000..155825408b
--- /dev/null
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelRepositoryHolder.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.apache.maven.internal.impl.resolver;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.api.RemoteRepository;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.model.Repository;
+import org.apache.maven.api.services.ModelRepositoryHolder;
+import org.apache.maven.api.services.RepositoryFactory;
+
+public class DefaultModelRepositoryHolder implements ModelRepositoryHolder {
+
+    /**
+     * The possible merge modes for combining remote repositories.
+     */
+    public enum RepositoryMerging {
+
+        /**
+         * The repositories declared in the POM have precedence over the repositories specified in the request.
+         */
+        POM_DOMINANT,
+
+        /**
+         * The repositories specified in the request have precedence over the repositories declared in the POM.
+         */
+        REQUEST_DOMINANT,
+    }
+
+    final Session session;
+    final RepositoryMerging repositoryMerging;
+
+    List<RemoteRepository> pomRepositories;
+    List<RemoteRepository> repositories;
+    List<RemoteRepository> externalRepositories;
+    Set<String> ids;
+
+    public DefaultModelRepositoryHolder(
+            Session session, RepositoryMerging repositoryMerging, List<RemoteRepository> externalRepositories) {
+        this.session = session;
+        this.repositoryMerging = repositoryMerging;
+        this.pomRepositories = List.of();
+        this.externalRepositories = List.copyOf(externalRepositories);
+        this.repositories = List.copyOf(externalRepositories);
+        this.ids = new HashSet<>();
+    }
+
+    protected DefaultModelRepositoryHolder(DefaultModelRepositoryHolder holder) {
+        this.session = holder.session;
+        this.repositoryMerging = holder.repositoryMerging;
+        this.pomRepositories = List.copyOf(holder.pomRepositories);
+        this.externalRepositories = List.copyOf(holder.externalRepositories);
+        this.repositories = List.copyOf(holder.repositories);
+    }
+
+    @Override
+    public void merge(List<Repository> toAdd, boolean replace) {
+        List<RemoteRepository> repos =
+                toAdd.stream().map(session::createRemoteRepository).toList();
+        if (replace) {
+            Set<String> ids = repos.stream().map(RemoteRepository::getId).collect(Collectors.toSet());
+            repositories =
+                    repositories.stream().filter(r -> !ids.contains(r.getId())).toList();
+            pomRepositories = pomRepositories.stream()
+                    .filter(r -> !ids.contains(r.getId()))
+                    .toList();
+        } else {
+            Set<String> ids =
+                    pomRepositories.stream().map(RemoteRepository::getId).collect(Collectors.toSet());
+            repos = repos.stream().filter(r -> !ids.contains(r.getId())).toList();
+        }
+
+        RepositoryFactory repositoryFactory = session.getService(RepositoryFactory.class);
+        if (repositoryMerging == RepositoryMerging.REQUEST_DOMINANT) {
+            repositories = repositoryFactory.aggregate(session, repositories, repos, true);
+            pomRepositories = repositories;
+        } else {
+            pomRepositories = repositoryFactory.aggregate(session, pomRepositories, repos, true);
+            repositories = repositoryFactory.aggregate(session, pomRepositories, externalRepositories, false);
+        }
+    }
+
+    @Override
+    public List<org.apache.maven.api.RemoteRepository> getRepositories() {
+        return List.copyOf(repositories);
+    }
+
+    @Override
+    public ModelRepositoryHolder copy() {
+        return new DefaultModelRepositoryHolder(this);
+    }
+}
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelResolver.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelResolver.java
index 94efcb2902..a3e251294e 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelResolver.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/resolver/DefaultModelResolver.java
@@ -19,232 +19,72 @@
 package org.apache.maven.internal.impl.resolver;
 
 import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 import org.apache.maven.api.ArtifactCoordinate;
 import org.apache.maven.api.Session;
 import org.apache.maven.api.Version;
-import org.apache.maven.api.annotations.Nonnull;
-import org.apache.maven.api.di.Inject;
-import org.apache.maven.api.model.Dependency;
-import org.apache.maven.api.model.Parent;
-import org.apache.maven.api.model.Repository;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Singleton;
 import org.apache.maven.api.services.ArtifactResolverException;
 import org.apache.maven.api.services.ModelResolver;
 import org.apache.maven.api.services.ModelResolverException;
 import org.apache.maven.api.services.ModelSource;
 import org.apache.maven.api.services.VersionRangeResolverException;
-import org.apache.maven.internal.impl.InternalSession;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.impl.RemoteRepositoryManager;
-import org.eclipse.aether.repository.RemoteRepository;
 
 /**
- * A model resolver to assist building of dependency POMs. This resolver gives priority to those repositories that have
- * been initially specified and repositories discovered in dependency POMs are recessively merged into the search chain.
+ * A model resolver to assist building of dependency POMs.
  *
  * @see DefaultArtifactDescriptorReader
  */
+@Named
+@Singleton
 public class DefaultModelResolver implements ModelResolver {
 
-    private List<RemoteRepository> repositories;
-
-    private final List<RemoteRepository> externalRepositories;
-
-    private final RemoteRepositoryManager remoteRepositoryManager;
-
-    private final Set<String> repositoryIds;
-
-    @Inject
-    public DefaultModelResolver(RemoteRepositoryManager remoteRepositoryManager) {
-        this(remoteRepositoryManager, List.of());
-    }
-
-    public DefaultModelResolver(RemoteRepositoryManager remoteRepositoryManager, List<RemoteRepository> repositories) {
-        this.remoteRepositoryManager = remoteRepositoryManager;
-        this.repositories = repositories;
-        this.externalRepositories = Collections.unmodifiableList(new ArrayList<>(repositories));
-
-        this.repositoryIds = new HashSet<>();
-    }
-
-    private DefaultModelResolver(DefaultModelResolver original) {
-        this.remoteRepositoryManager = original.remoteRepositoryManager;
-        this.repositories = new ArrayList<>(original.repositories);
-        this.externalRepositories = original.externalRepositories;
-        this.repositoryIds = new HashSet<>(original.repositoryIds);
-    }
-
     @Override
-    public void addRepository(@Nonnull Session session, Repository repository) {
-        addRepository(session, repository, false);
-    }
-
-    @Override
-    public void addRepository(Session session, Repository repository, boolean replace) {
-        RepositorySystemSession rsession = InternalSession.from(session).getSession();
-        if (rsession.isIgnoreArtifactDescriptorRepositories()) {
-            return;
-        }
-
-        if (!repositoryIds.add(repository.getId())) {
-            if (!replace) {
-                return;
-            }
-
-            removeMatchingRepository(repositories, repository.getId());
-        }
-
-        List<RemoteRepository> newRepositories =
-                Collections.singletonList(ArtifactDescriptorUtils.toRemoteRepository(repository));
-
-        this.repositories =
-                remoteRepositoryManager.aggregateRepositories(rsession, repositories, newRepositories, true);
-    }
-
-    private static void removeMatchingRepository(Iterable<RemoteRepository> repositories, final String id) {
-        Iterator<RemoteRepository> iterator = repositories.iterator();
-        while (iterator.hasNext()) {
-            RemoteRepository remoteRepository = iterator.next();
-            if (remoteRepository.getId().equals(id)) {
-                iterator.remove();
-            }
-        }
-    }
-
-    @Override
-    public ModelResolver newCopy() {
-        return new DefaultModelResolver(this);
-    }
-
-    @Override
-    public ModelSource resolveModel(Session session, String groupId, String artifactId, String version)
+    public ModelSource resolveModel(
+            Session session, String groupId, String artifactId, String version, Consumer<String> resolvedVersion)
             throws ModelResolverException {
         try {
-            session = session.withRemoteRepositories(repositories.stream()
-                    .map(InternalSession.from(session)::getRemoteRepository)
-                    .toList());
-            Map.Entry<org.apache.maven.api.Artifact, Path> resolved =
-                    session.resolveArtifact(session.createArtifactCoordinate(groupId, artifactId, version, "pom"));
-            return ModelSource.fromPath(resolved.getValue(), groupId + ":" + artifactId + ":" + version);
-        } catch (ArtifactResolverException e) {
-            throw new ModelResolverException(
-                    e.getMessage() + " (remote repositories: "
-                            + session.getRemoteRepositories().stream()
-                                    .map(Object::toString)
-                                    .collect(Collectors.joining(", "))
-                            + ")",
-                    groupId,
-                    artifactId,
-                    version,
-                    e);
-        }
-    }
-
-    @Override
-    public ModelSource resolveModel(Session session, Parent parent, AtomicReference<Parent> modified)
-            throws ModelResolverException {
-        try {
-            session = session.withRemoteRepositories(repositories.stream()
-                    .map(InternalSession.from(session)::getRemoteRepository)
-                    .toList());
-            ArtifactCoordinate coord = session.createArtifactCoordinate(
-                    parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), "pom");
+            ArtifactCoordinate coord = session.createArtifactCoordinate(groupId, artifactId, version, "pom");
             if (coord.getVersion().getVersionRange() != null
                     && coord.getVersion().getVersionRange().getUpperBoundary() == null) {
                 // Message below is checked for in the MNG-2199 core IT.
                 throw new ModelResolverException(
-                        String.format(
-                                "The requested parent version range '%s' does not specify an upper bound",
-                                parent.getVersion()),
-                        parent.getGroupId(),
-                        parent.getArtifactId(),
-                        parent.getVersion());
+                        String.format("The requested version range '%s' does not specify an upper bound", version),
+                        groupId,
+                        artifactId,
+                        version);
             }
             List<Version> versions = session.resolveVersionRange(coord);
             if (versions.isEmpty()) {
                 throw new ModelResolverException(
-                        String.format(
-                                "No versions matched the requested parent version range '%s'", parent.getVersion()),
-                        parent.getGroupId(),
-                        parent.getArtifactId(),
-                        parent.getVersion());
+                        String.format("No versions matched the requested version range '%s'", version),
+                        groupId,
+                        artifactId,
+                        version);
             }
             String newVersion = versions.get(versions.size() - 1).asString();
-            if (!parent.getVersion().equals(newVersion)) {
-                modified.set(parent.withVersion(newVersion));
-            }
-
-            return resolveModel(session, parent.getGroupId(), parent.getArtifactId(), newVersion);
-        } catch (final VersionRangeResolverException e) {
-            throw new ModelResolverException(
-                    e.getMessage() + " (remote repositories: "
-                            + session.getRemoteRepositories().stream()
-                                    .map(Object::toString)
-                                    .collect(Collectors.joining(", "))
-                            + ")",
-                    parent.getGroupId(),
-                    parent.getArtifactId(),
-                    parent.getVersion(),
-                    e);
-        }
-    }
-
-    @Override
-    public ModelSource resolveModel(Session session, Dependency dependency, AtomicReference<Dependency> modified)
-            throws ModelResolverException {
-        try {
-            session = session.withRemoteRepositories(repositories.stream()
-                    .map(InternalSession.from(session)::getRemoteRepository)
-                    .toList());
-            ArtifactCoordinate coord = session.createArtifactCoordinate(
-                    dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), "pom");
-            if (coord.getVersion().getVersionRange() != null
-                    && coord.getVersion().getVersionRange().getUpperBoundary() == null) {
-                // Message below is checked for in the MNG-2199 core IT.
-                throw new ModelResolverException(
-                        String.format(
-                                "The requested dependency version range '%s' does not specify an upper bound",
-                                dependency.getVersion()),
-                        dependency.getGroupId(),
-                        dependency.getArtifactId(),
-                        dependency.getVersion());
-            }
-            List<Version> versions = session.resolveVersionRange(coord);
-            if (versions.isEmpty()) {
-                throw new ModelResolverException(
-                        String.format(
-                                "No versions matched the requested dependency version range '%s'",
-                                dependency.getVersion()),
-                        dependency.getGroupId(),
-                        dependency.getArtifactId(),
-                        dependency.getVersion());
-            }
-
-            String newVersion = versions.get(versions.size() - 1).toString();
-            if (!dependency.getVersion().equals(newVersion)) {
-                modified.set(dependency.withVersion(newVersion));
+            if (!version.equals(newVersion)) {
+                resolvedVersion.accept(newVersion);
             }
 
-            return resolveModel(session, dependency.getGroupId(), dependency.getArtifactId(), newVersion);
-        } catch (VersionRangeResolverException e) {
+            Map.Entry<org.apache.maven.api.Artifact, Path> resolved =
+                    session.resolveArtifact(session.createArtifactCoordinate(groupId, artifactId, newVersion, "pom"));
+            return ModelSource.fromPath(resolved.getValue(), groupId + ":" + artifactId + ":" + newVersion);
+        } catch (VersionRangeResolverException | ArtifactResolverException e) {
             throw new ModelResolverException(
                     e.getMessage() + " (remote repositories: "
                             + session.getRemoteRepositories().stream()
                                     .map(Object::toString)
                                     .collect(Collectors.joining(", "))
                             + ")",
-                    dependency.getGroupId(),
-                    dependency.getArtifactId(),
-                    dependency.getVersion(),
+                    groupId,
+                    artifactId,
+                    version,
                     e);
         }
     }
diff --git a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/resolver/DefaultModelResolverTest.java b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/resolver/DefaultModelResolverTest.java
new file mode 100644
index 0000000000..a6088b80f0
--- /dev/null
+++ b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/resolver/DefaultModelResolverTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+package org.apache.maven.internal.impl.resolver;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.maven.api.LocalRepository;
+import org.apache.maven.api.RemoteRepository;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.model.Dependency;
+import org.apache.maven.api.model.Parent;
+import org.apache.maven.api.services.ModelResolver;
+import org.apache.maven.api.services.ModelResolverException;
+import org.apache.maven.internal.impl.standalone.ApiRunner;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Test cases for the project {@code ModelResolver} implementation.
+ */
+class DefaultModelResolverTest {
+
+    Session session;
+
+    @BeforeEach
+    void setup() {
+        Path basedir = Paths.get(System.getProperty("basedir", ""));
+        Path localRepoPath = basedir.resolve("target/local-repo");
+        Path remoteRepoPath = basedir.resolve("src/test/remote-repo");
+        Session s = ApiRunner.createSession();
+        LocalRepository localRepository = s.createLocalRepository(localRepoPath);
+        RemoteRepository remoteRepository = s.createRemoteRepository(
+                RemoteRepository.CENTRAL_ID, remoteRepoPath.toUri().toString());
+        session = s.withLocalRepository(localRepository).withRemoteRepositories(List.of(remoteRepository));
+    }
+
+    @Test
+    void testResolveParentThrowsModelResolverExceptionWhenNotFound() throws Exception {
+        final Parent parent = Parent.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("0")
+                .build();
+
+        ModelResolverException e = assertThrows(
+                ModelResolverException.class,
+                () -> newModelResolver().resolveModel(session, parent, new AtomicReference<>()),
+                "Expected 'ModelResolverException' not thrown.");
+        assertNotNull(e.getMessage());
+        assertThat(e.getMessage(), containsString("Could not find artifact org.apache:apache:pom:0 in central"));
+    }
+
+    @Test
+    void testResolveParentThrowsModelResolverExceptionWhenNoMatchingVersionFound() throws Exception {
+        final Parent parent = Parent.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("[2.0,2.1)")
+                .build();
+
+        ModelResolverException e = assertThrows(
+                ModelResolverException.class,
+                () -> newModelResolver().resolveModel(session, parent, new AtomicReference<>()),
+                "Expected 'ModelResolverException' not thrown.");
+        assertEquals("No versions matched the requested version range '[2.0,2.1)'", e.getMessage());
+    }
+
+    @Test
+    void testResolveParentThrowsModelResolverExceptionWhenUsingRangesWithoutUpperBound() throws Exception {
+        final Parent parent = Parent.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("[1,)")
+                .build();
+
+        ModelResolverException e = assertThrows(
+                ModelResolverException.class,
+                () -> newModelResolver().resolveModel(session, parent, new AtomicReference<>()),
+                "Expected 'ModelResolverException' not thrown.");
+        assertEquals("The requested version range '[1,)' does not specify an upper bound", e.getMessage());
+    }
+
+    @Test
+    void testResolveParentSuccessfullyResolvesExistingParentWithoutRange() throws Exception {
+        final Parent parent = Parent.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("1")
+                .build();
+
+        assertNotNull(this.newModelResolver().resolveModel(session, parent, new AtomicReference<>()));
+        assertEquals("1", parent.getVersion());
+    }
+
+    @Test
+    void testResolveParentSuccessfullyResolvesExistingParentUsingHighestVersion() throws Exception {
+        final Parent parent = Parent.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("(,2.0)")
+                .build();
+
+        AtomicReference<org.apache.maven.api.model.Parent> modified = new AtomicReference<>();
+        assertNotNull(this.newModelResolver().resolveModel(session, parent, modified));
+        assertEquals("1", modified.get().getVersion());
+    }
+
+    @Test
+    void testResolveDependencyThrowsModelResolverExceptionWhenNotFound() throws Exception {
+        final Dependency dependency = Dependency.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("0")
+                .build();
+
+        ModelResolverException e = assertThrows(
+                ModelResolverException.class,
+                () -> newModelResolver().resolveModel(session, dependency, new AtomicReference<>()),
+                "Expected 'ModelResolverException' not thrown.");
+        assertNotNull(e.getMessage());
+        assertThat(e.getMessage(), containsString("Could not find artifact org.apache:apache:pom:0 in central"));
+    }
+
+    @Test
+    void testResolveDependencyThrowsModelResolverExceptionWhenNoMatchingVersionFound() throws Exception {
+        final Dependency dependency = Dependency.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("[2.0,2.1)")
+                .build();
+
+        ModelResolverException e = assertThrows(
+                ModelResolverException.class,
+                () -> newModelResolver().resolveModel(session, dependency, new AtomicReference<>()),
+                "Expected 'ModelResolverException' not thrown.");
+        assertEquals("No versions matched the requested version range '[2.0,2.1)'", e.getMessage());
+    }
+
+    @Test
+    void testResolveDependencyThrowsModelResolverExceptionWhenUsingRangesWithoutUpperBound() throws Exception {
+        final Dependency dependency = Dependency.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("[1,)")
+                .build();
+
+        ModelResolverException e = assertThrows(
+                ModelResolverException.class,
+                () -> newModelResolver().resolveModel(session, dependency, new AtomicReference<>()),
+                "Expected 'ModelResolverException' not thrown.");
+        assertEquals("The requested version range '[1,)' does not specify an upper bound", e.getMessage());
+    }
+
+    @Test
+    void testResolveDependencySuccessfullyResolvesExistingDependencyWithoutRange() throws Exception {
+        final Dependency dependency = Dependency.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("1")
+                .build();
+
+        assertNotNull(this.newModelResolver().resolveModel(session, dependency, new AtomicReference<>()));
+        assertEquals("1", dependency.getVersion());
+    }
+
+    @Test
+    void testResolveDependencySuccessfullyResolvesExistingDependencyUsingHighestVersion() throws Exception {
+        final Dependency dependency = Dependency.newBuilder()
+                .groupId("org.apache")
+                .artifactId("apache")
+                .version("(,2.0)")
+                .build();
+
+        AtomicReference<org.apache.maven.api.model.Dependency> modified = new AtomicReference<>();
+        assertNotNull(this.newModelResolver().resolveModel(session, dependency, modified));
+        assertEquals("1", modified.get().getVersion());
+    }
+
+    private ModelResolver newModelResolver() throws Exception {
+        return new DefaultModelResolver();
+    }
+}
diff --git a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java
index e60bdbd081..e556174b8a 100644
--- a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java
+++ b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java
@@ -1033,8 +1033,7 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> {
                 new DefaultPluginConfigurationExpander(),
                 new ProfileActivationFilePathInterpolator(new DefaultPathTranslator(), new DefaultRootLocator()),
                 new BuildModelTransformer(),
-                new DefaultModelVersionParser(getVersionScheme()),
-                getRemoteRepositoryManager());
+                new DefaultModelVersionParser(getVersionScheme()));
     }
 
     private RepositorySystem repositorySystem;
diff --git a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/TestApiStandalone.java b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/TestApiStandalone.java
index e17bd9ed12..dacb2c9316 100644
--- a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/TestApiStandalone.java
+++ b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/TestApiStandalone.java
@@ -30,6 +30,7 @@ import org.apache.maven.api.Session;
 import org.apache.maven.api.services.ModelBuilder;
 import org.apache.maven.api.services.ModelBuilderRequest;
 import org.apache.maven.api.services.ModelBuilderResult;
+import org.apache.maven.api.services.ModelSource;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -43,8 +44,11 @@ class TestApiStandalone {
         Session session = ApiRunner.createSession();
 
         ModelBuilder builder = session.getService(ModelBuilder.class);
-        ModelBuilderResult result = builder.build(
-                ModelBuilderRequest.build(session, Paths.get("pom.xml").toAbsolutePath()));
+        ModelBuilderResult result = builder.build(ModelBuilderRequest.builder()
+                .session(session)
+                .source(ModelSource.fromPath(Paths.get("pom.xml").toAbsolutePath()))
+                .projectBuild(true)
+                .build());
         assertNotNull(result.getEffectiveModel());
 
         ArtifactCoordinate coord = session.createArtifactCoordinate("org.apache.maven:maven-api-core:4.0.0-alpha-13");
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/apache/1/apache-1.pom b/maven-api-impl/src/test/remote-repo/org/apache/apache/1/apache-1.pom
new file mode 100644
index 0000000000..88d8db4aa0
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/apache/1/apache-1.pom
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Copyright 2005-2006 The Apache Software Foundation.
+  ~
+  ~ Licensed 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <!-- Shared parent. Doesn't define a lot of things about Apache like general mailing lists, but does
+       define the settings common to all projects at Apache -->
+  <groupId>org.apache</groupId>
+  <artifactId>apache</artifactId>
+  <version>1</version>
+  <packaging>pom</packaging>
+  <name>The Apache Software Foundation</name>
+  <description>
+    The Apache Software Foundation provides support for the Apache community of open-source software projects.
+    The Apache projects are characterized by a collaborative, consensus based development process, an open and
+    pragmatic software license, and a desire to create high quality software that leads the way in its field.
+    We consider ourselves not simply a group of projects sharing a server, but rather a community of developers
+    and users.
+  </description>
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <organization>
+    <name>Apache Software Foundation</name>
+    <url>http://www.apache.org/</url>
+  </organization>
+  <url>http://www.apache.org/</url>
+  <repositories>
+    <repository>
+      <id>apache.snapshots</id>
+      <name>Apache Snapshot Repository</name>
+      <url>http://svn.apache.org/maven-snapshot-repository</url>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+    </repository>
+  </repositories>
+  <distributionManagement>
+    <!-- Site omitted - each project must provide their own -->
+    <repository>
+      <id>apache.releases</id>
+      <name>Apache Release Distribution Repository</name>
+      <url>scp://minotaur.apache.org/www/www.apache.org/dist/maven-repository</url>
+    </repository>
+    <snapshotRepository>
+      <id>apache.snapshots</id>
+      <name>Apache Development Snapshot Repository</name>
+      <url>scp://minotaur.apache.org/www/cvs.apache.org/maven-snapshot-repository</url>
+    </snapshotRepository>
+  </distributionManagement>
+  <mailingLists>
+    <mailingList>
+      <name>Apache Announce List</name>
+      <subscribe>announce-subscribe@apache.org</subscribe>
+      <unsubscribe>announce-unsubscribe@apache.org</unsubscribe>
+      <post>announce@apache.org</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/www-announce/</archive>
+    </mailingList>
+  </mailingLists>
+</project>
+
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/apache/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/apache/maven-metadata.xml
new file mode 100644
index 0000000000..596f967e40
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/apache/maven-metadata.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache</groupId>
+  <artifactId>apache</artifactId>
+  <versioning>
+    <latest>1</latest>
+    <release>1</release>
+    <versions>
+      <version>1</version>
+    </versions>
+    <lastUpdated>20150428055824</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/0.1/a-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/0.1/a-0.1.jar
new file mode 100644
index 0000000000..609ec21bca
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/0.1/a-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/0.1/a-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/0.1/a-0.1.pom
new file mode 100644
index 0000000000..03caa12ee8
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/0.1/a-0.1.pom
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>a</artifactId>
+  <version>0.1</version>
+  <packaging>jar</packaging>
+
+  <name>Maven Integration Test :: Dummy Artifact</name>
+  <description>
+
+  </description>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/maven-metadata.xml
new file mode 100644
index 0000000000..8099175ec0
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/a/maven-metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>a</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023222756</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/0.1/b-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/0.1/b-0.1.jar
new file mode 100644
index 0000000000..19df0485a7
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/0.1/b-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/0.1/b-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/0.1/b-0.1.pom
new file mode 100644
index 0000000000..149a241088
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/0.1/b-0.1.pom
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>b</artifactId>
+  <version>0.1</version>
+  <packaging>jar</packaging>
+
+  <name>Maven Integration Test :: Dummy Artifact</name>
+  <description>
+
+  </description>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.its</groupId>
+      <artifactId>a</artifactId>
+      <version>0.1</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/maven-metadata.xml
new file mode 100644
index 0000000000..e77af628fa
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/b/maven-metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>b</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023222817</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/bom/0.1/bom-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/bom/0.1/bom-0.1.pom
new file mode 100644
index 0000000000..65973c895d
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/bom/0.1/bom-0.1.pom
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.maven.its</groupId>
+    <artifactId>bom</artifactId>
+    <version>0.1</version>
+    <packaging>pom</packaging>
+
+    <name>Maven Integration Test :: Dummy BOM</name>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.maven.its</groupId>
+                <artifactId>a</artifactId>
+                <version>0.1</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/bom/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/bom/maven-metadata.xml
new file mode 100644
index 0000000000..073330928a
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/bom/maven-metadata.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>bom</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <versions>
+      <version>0.1</version>
+    </versions>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/parent/0.1/parent-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/parent/0.1/parent-0.1.pom
new file mode 100644
index 0000000000..8b149f2d73
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/parent/0.1/parent-0.1.pom
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.maven.its</groupId>
+    <artifactId>parent</artifactId>
+    <version>0.1</version>
+    <packaging>pom</packaging>
+
+    <name>Maven Integration Test :: Dummy Parent</name>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <version>0.1</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/parent/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/parent/maven-metadata.xml
new file mode 100644
index 0000000000..3a76b19e67
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/parent/maven-metadata.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>parent</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <versions>
+      <version>0.1</version>
+    </versions>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/maven-it-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/maven-it-plugin-0.1.jar
new file mode 100644
index 0000000000..84a4bf7ac6
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/maven-it-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/maven-it-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/maven-it-plugin-0.1.pom
new file mode 100644
index 0000000000..3e2a57bdd1
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/maven-it-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.plugins</groupId>
+  <artifactId>maven-it-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/pom.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/pom.xml
new file mode 100644
index 0000000000..3e2a57bdd1
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/0.1/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.plugins</groupId>
+  <artifactId>maven-it-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..65155293ae
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-it-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.its.plugins</groupId>
+  <artifactId>maven-it-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023233513</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-metadata.xml
new file mode 100644
index 0000000000..637ec122a3
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/its/plugins/maven-metadata.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <plugins>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>it</prefix>
+      <artifactId>maven-it-plugin</artifactId>
+    </plugin>
+  </plugins>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/maven-plugin-api/2.0/maven-plugin-api-2.0.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/maven-plugin-api/2.0/maven-plugin-api-2.0.jar
new file mode 100644
index 0000000000..5150c162d9
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/maven-plugin-api/2.0/maven-plugin-api-2.0.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/maven-plugin-api/2.0/maven-plugin-api-2.0.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/maven-plugin-api/2.0/maven-plugin-api-2.0.pom
new file mode 100644
index 0000000000..c1d5cc0b83
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/maven-plugin-api/2.0/maven-plugin-api-2.0.pom
@@ -0,0 +1,23 @@
+<project>
+  <parent>
+    <artifactId>maven</artifactId>
+    <groupId>org.apache.maven</groupId>
+    <version>2.0</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven</groupId>
+  <artifactId>maven-plugin-api</artifactId>
+  <name>Maven Plugin API</name>
+  <version>2.0</version>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <distributionManagement>
+    <status>deployed</status>
+  </distributionManagement>
+</project>
\ No newline at end of file
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/maven/2.0/maven-2.0.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/maven/2.0/maven-2.0.pom
new file mode 100644
index 0000000000..5944be2bd8
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/maven/2.0/maven-2.0.pom
@@ -0,0 +1,264 @@
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven</groupId>
+  <artifactId>maven</artifactId>
+  <packaging>pom</packaging>
+  <name>Maven</name>
+  <version>2.0</version>
+  <description>Maven is a project development management and comprehension tool. Based on the concept of a project object model: builds, dependency management, documentation creation, site publication, and distribution publication are all controlled from the declarative file. Maven can be extended by plugins to utilise a number of other development tools for reporting or the build process.</description>
+  <url>http://maven.apache.org/maven2/</url>
+  <issueManagement>
+    <system>jira</system>
+    <url>http://jira.codehaus.org/browse/MNG</url>
+  </issueManagement>
+  <ciManagement>
+    <system>continuum</system>
+    <notifiers>
+      <notifier>
+        <configuration>
+          <address>commits@maven.apache.org</address>
+        </configuration>
+      </notifier>
+    </notifiers>
+  </ciManagement>
+  <mailingLists>
+    <mailingList>
+      <name>Maven User List</name>
+      <subscribe>users-subscribe@maven.apache.org</subscribe>
+      <unsubscribe>users-unsubscribe@maven.apache.org</unsubscribe>
+      <post>users@maven.apache.org</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/maven-users</archive>
+    </mailingList>
+    <mailingList>
+      <name>Maven Developer List</name>
+      <subscribe>dev-subscribe@maven.apache.org</subscribe>
+      <unsubscribe>dev-unsubscribe@maven.apache.org</unsubscribe>
+      <post>dev@maven.apache.org</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/maven-dev</archive>
+    </mailingList>
+    <mailingList>
+      <name>Maven Commits List</name>
+      <subscribe>commits-subscribe@maven.apache.org</subscribe>
+      <unsubscribe>commits-unsubscribe@maven.apache.org</unsubscribe>
+      <post>commits@maven.apache.org</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/maven-dev</archive>
+    </mailingList>
+    <mailingList>
+      <name>Apache Announce List</name>
+      <subscribe>announce-subscribe@apache.org</subscribe>
+      <unsubscribe>announce-unsubscribe@apache.org</unsubscribe>
+      <post>announce@apache.org</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/www-announce/</archive>
+    </mailingList>
+  </mailingLists>
+  <developers>
+    <developer>
+      <id>jvanzyl</id>
+      <name>Jason van Zyl</name>
+      <email>jason@maven.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>PMC Chair</role>
+      </roles>
+      <timezone>-5</timezone>
+    </developer>
+    <developer>
+      <id>brett</id>
+      <name>Brett Porter</name>
+      <email>brett@apache.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>PMC Member</role>
+      </roles>
+      <timezone>+10</timezone>
+    </developer>
+    <developer>
+      <id>evenisse</id>
+      <name>Emmanuel Venisse</name>
+      <email>evenisse@apache.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>PMC Member</role>
+      </roles>
+      <timezone>+1</timezone>
+    </developer>
+    <developer>
+      <id>jdcasey</id>
+      <name>John Casey</name>
+      <email>jdcasey@apache.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>PMC Member</role>
+      </roles>
+      <timezone>-5</timezone>
+    </developer>
+    <developer>
+      <id>kenney</id>
+      <name>Kenney Westerhof</name>
+      <email>kenney@apache.org</email>
+      <organization>Neonics</organization>
+      <roles>
+        <role>PMC Member</role>
+      </roles>
+      <timezone>+1</timezone>
+    </developer>
+    <developer>
+      <id>trygvis</id>
+      <name>Trygve Laugstol</name>
+      <email>trygvis@apache.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>PMC Member</role>
+      </roles>
+      <timezone>+1</timezone>
+    </developer>
+    <developer>
+      <id>vmassol</id>
+      <name>Vincent Massol</name>
+      <email>vmassol@apache.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>PMC Member</role>
+      </roles>
+      <timezone>+1</timezone>
+    </developer>
+    <developer>
+      <id>vsiveton</id>
+      <name>Vincent Siveton</name>
+      <email>vsiveton@apache.org</email>
+      <organization>ASF</organization>
+      <roles>
+        <role>Committer</role>
+      </roles>
+      <timezone>-5</timezone>
+    </developer>
+  </developers>
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/maven/components/tags/maven-2.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/components/tags/maven-2.0</developerConnection>
+    <url>http://svn.apache.org/viewcvs.cgi/maven/components/tags/maven-2.0</url>
+  </scm>
+  <organization>
+    <name>Apache Software Foundation</name>
+    <url>http://www.apache.org/</url>
+  </organization>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-release-plugin</artifactId>
+          <configuration>
+            <tagBase>https://svn.apache.org/repos/asf/maven/components/tags</tagBase>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+  <modules>
+    <module>maven-archiver</module>
+    <module>maven-artifact</module>
+    <module>maven-artifact-manager</module>
+    <module>maven-artifact-ant</module>
+    <module>maven-artifact-test</module>
+    <module>maven-core</module>
+    <module>maven-error-diagnostics</module>
+    <module>maven-model</module>
+    <module>maven-monitor</module>
+    <module>maven-plugin-api</module>
+    <module>maven-plugin-descriptor</module>
+    <module>maven-plugin-parameter-documenter</module>
+    <module>maven-plugin-registry</module>
+    <module>maven-plugin-tools</module>
+    <module>maven-profile</module>
+    <module>maven-project</module>
+    <module>maven-reporting</module>
+    <module>maven-repository-metadata</module>
+    <module>maven-script</module>
+    <module>maven-settings</module>
+  </modules>
+  <repositories>
+    <repository>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+      <id>snapshots</id>
+      <name>Maven Central Development Repository</name>
+      <url>http://snapshots.maven.codehaus.org/maven2</url>
+    </repository>
+  </repositories>
+  <pluginRepositories>
+    <pluginRepository>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+      <id>snapshots</id>
+      <name>Maven Central Plugins Development Repository</name>
+      <url>http://snapshots.maven.codehaus.org/maven2</url>
+    </pluginRepository>
+  </pluginRepositories>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-container-default</artifactId>
+        <version>1.0-alpha-8</version>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-utils</artifactId>
+        <version>1.0.4</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.wagon</groupId>
+        <artifactId>wagon-provider-api</artifactId>
+        <version>1.0-alpha-5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.wagon</groupId>
+        <artifactId>wagon-ssh</artifactId>
+        <version>1.0-alpha-5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.wagon</groupId>
+        <artifactId>wagon-file</artifactId>
+        <version>1.0-alpha-5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven.wagon</groupId>
+        <artifactId>wagon-http-lightweight</artifactId>
+        <version>1.0-alpha-5</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <distributionManagement>
+    <repository>
+      <id>repo1</id>
+      <name>Maven Central Repository</name>
+      <url>scp://repo1.maven.org/home/projects/maven/repository-staging/to-ibiblio/maven2</url>
+    </repository>
+    <snapshotRepository>
+      <id>snapshots</id>
+      <name>Maven Central Development Repository</name>
+      <url>scp://repo1.maven.org/home/projects/maven/repository-staging/snapshots/maven2</url>
+    </snapshotRepository>
+    <site>
+      <id>website</id>
+      <url>scp://minotaur.apache.org/www/maven.apache.org/maven2/</url>
+    </site>
+  </distributionManagement>
+</project>
\ No newline at end of file
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/0.1/maven-clean-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/0.1/maven-clean-plugin-0.1.jar
new file mode 100644
index 0000000000..ee01f1017a
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/0.1/maven-clean-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/0.1/maven-clean-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/0.1/maven-clean-plugin-0.1.pom
new file mode 100644
index 0000000000..345b42631e
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/0.1/maven-clean-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-clean-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..91261b37b9
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-clean-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-clean-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023224342</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/0.1/maven-compiler-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/0.1/maven-compiler-plugin-0.1.jar
new file mode 100644
index 0000000000..e5ef44649a
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/0.1/maven-compiler-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/0.1/maven-compiler-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/0.1/maven-compiler-plugin-0.1.pom
new file mode 100644
index 0000000000..4fade1b5c1
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/0.1/maven-compiler-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-compiler-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..544f16ea87
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-compiler-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023224813</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/0.1/maven-deploy-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/0.1/maven-deploy-plugin-0.1.jar
new file mode 100644
index 0000000000..f2432a6d36
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/0.1/maven-deploy-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/0.1/maven-deploy-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/0.1/maven-deploy-plugin-0.1.pom
new file mode 100644
index 0000000000..eef47c9ead
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/0.1/maven-deploy-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-deploy-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..f0af94c7f4
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-deploy-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-deploy-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023224421</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/0.1/maven-install-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/0.1/maven-install-plugin-0.1.jar
new file mode 100644
index 0000000000..a6adb9882e
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/0.1/maven-install-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/0.1/maven-install-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/0.1/maven-install-plugin-0.1.pom
new file mode 100644
index 0000000000..3be92b8dab
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/0.1/maven-install-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-install-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..bb52879137
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-install-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-install-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023224444</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/0.1/maven-jar-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/0.1/maven-jar-plugin-0.1.jar
new file mode 100644
index 0000000000..0b03b350dc
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/0.1/maven-jar-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/0.1/maven-jar-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/0.1/maven-jar-plugin-0.1.pom
new file mode 100644
index 0000000000..405308268a
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/0.1/maven-jar-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-jar-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..6b734ad588
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-jar-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-jar-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023232454</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-metadata.xml
new file mode 100644
index 0000000000..615714ccdd
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-metadata.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <plugins>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>clean</prefix>
+      <artifactId>maven-clean-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>deploy</prefix>
+      <artifactId>maven-deploy-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>install</prefix>
+      <artifactId>maven-install-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>jar</prefix>
+      <artifactId>maven-jar-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>surefire</prefix>
+      <artifactId>maven-surefire-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>compiler</prefix>
+      <artifactId>maven-compiler-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>resources</prefix>
+      <artifactId>maven-resources-plugin</artifactId>
+    </plugin>
+    <plugin>
+      <name>Maven Integration Test Plugin</name>
+      <prefix>plugin</prefix>
+      <artifactId>maven-plugin-plugin</artifactId>
+    </plugin>
+  </plugins>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/0.1/maven-plugin-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/0.1/maven-plugin-plugin-0.1.jar
new file mode 100644
index 0000000000..e2eab46e7b
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/0.1/maven-plugin-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/0.1/maven-plugin-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/0.1/maven-plugin-plugin-0.1.pom
new file mode 100644
index 0000000000..a65d84db13
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/0.1/maven-plugin-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-plugin-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..4c29db7d17
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-plugin-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-plugin-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023225046</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/0.1/maven-resources-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/0.1/maven-resources-plugin-0.1.jar
new file mode 100644
index 0000000000..ffa11df47a
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/0.1/maven-resources-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/0.1/maven-resources-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/0.1/maven-resources-plugin-0.1.pom
new file mode 100644
index 0000000000..1a0cbd2c7d
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/0.1/maven-resources-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-resources-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..38c5503ad0
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-resources-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-resources-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023224958</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/0.1/maven-surefire-plugin-0.1.jar b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/0.1/maven-surefire-plugin-0.1.jar
new file mode 100644
index 0000000000..989e58379a
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/0.1/maven-surefire-plugin-0.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/0.1/maven-surefire-plugin-0.1.pom b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/0.1/maven-surefire-plugin-0.1.pom
new file mode 100644
index 0000000000..348afb2719
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/0.1/maven-surefire-plugin-0.1.pom
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-surefire-plugin</artifactId>
+  <version>0.1</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>Maven Integration Test Plugin</name>
+  <description>
+    A test plugin to assist testing of Maven core.
+  </description>
+  <inceptionYear>2009</inceptionYear>
+
+  <distributionManagement>
+    <repository>
+      <id>maven-core-it</id>
+      <url>file:///${basedir}/repo</url>
+    </repository>
+  </distributionManagement>
+
+  <properties>
+    <maven.test.skip>true</maven.test.skip>
+    <updateReleaseInfo>true</updateReleaseInfo>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory></directory>
+        <includes>
+          <include>pom.xml</include>
+          <include>src/**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/maven-metadata.xml b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/maven-metadata.xml
new file mode 100644
index 0000000000..c6d1df93d0
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/apache/maven/plugins/maven-surefire-plugin/maven-metadata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>org.apache.maven.plugins</groupId>
+  <artifactId>maven-surefire-plugin</artifactId>
+  <version>0.1</version>
+  <versioning>
+    <latest>0.1</latest>
+    <release>0.1</release>
+    <versions>
+      <version>0.1</version>
+    </versions>
+    <lastUpdated>20091023225125</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/maven-api-impl/src/test/remote-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar b/maven-api-impl/src/test/remote-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar
new file mode 100644
index 0000000000..5c50e1779f
Binary files /dev/null and b/maven-api-impl/src/test/remote-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar differ
diff --git a/maven-api-impl/src/test/remote-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom b/maven-api-impl/src/test/remote-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom
new file mode 100644
index 0000000000..6cf9079989
--- /dev/null
+++ b/maven-api-impl/src/test/remote-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?><project>
+  <parent>
+    <artifactId>plexus</artifactId>
+    <groupId>org.codehaus.plexus</groupId>
+    <version>1.0.4</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>plexus-utils</artifactId>
+  <name>Plexus Common Utilities</name>
+  <version>1.1</version>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>org/codehaus/plexus/util/FileBasedTestCase.java</exclude>
+            <exclude>**/Test*.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <distributionManagement>
+    <status>deployed</status>
+  </distributionManagement>
+</project>
\ No newline at end of file
diff --git a/maven-compat/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java b/maven-compat/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java
index 9340c12a28..36c9110f9e 100644
--- a/maven-compat/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java
+++ b/maven-compat/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java
@@ -34,6 +34,7 @@ import org.apache.maven.execution.DefaultMavenExecutionRequest;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.internal.impl.DefaultRepositoryFactory;
 import org.apache.maven.internal.impl.DefaultSession;
 import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.model.Build;
@@ -52,6 +53,9 @@ import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.testing.PlexusTest;
 import org.codehaus.plexus.util.FileUtils;
 import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
+import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
+import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
 import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
 import org.eclipse.aether.repository.LocalRepository;
 
@@ -128,8 +132,14 @@ public abstract class AbstractCoreMavenComponentTestCase {
 
         MavenSession session = new MavenSession(
                 getContainer(), configuration.getRepositorySession(), request, new DefaultMavenExecutionResult());
-        DefaultSession iSession =
-                new DefaultSession(session, mock(org.eclipse.aether.RepositorySystem.class), null, null, null, null);
+        DefaultSession iSession = new DefaultSession(
+                session,
+                mock(org.eclipse.aether.RepositorySystem.class),
+                null,
+                null,
+                new SimpleLookup(List.of(new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
+                        new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider())))),
+                null);
         InternalSession.associate(session.getRepositorySession(), iSession);
         session.setSession(iSession);
 
diff --git a/maven-compat/src/test/java/org/apache/maven/SimpleLookup.java b/maven-compat/src/test/java/org/apache/maven/SimpleLookup.java
new file mode 100644
index 0000000000..79370b9982
--- /dev/null
+++ b/maven-compat/src/test/java/org/apache/maven/SimpleLookup.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.maven;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.maven.api.services.Lookup;
+import org.apache.maven.api.services.LookupException;
+
+public class SimpleLookup implements Lookup {
+    private final List<Object> objects;
+
+    public SimpleLookup(List<Object> objects) {
+        this.objects = objects;
+    }
+
+    @Override
+    public <T> T lookup(Class<T> type) {
+        return objects.stream()
+                .filter(type::isInstance)
+                .map(type::cast)
+                .findAny()
+                .orElseThrow(() -> new LookupException("No service of type " + type));
+    }
+
+    @Override
+    public <T> T lookup(Class<T> type, String name) {
+        return null;
+    }
+
+    @Override
+    public <T> Optional<T> lookupOptional(Class<T> type) {
+        return Optional.empty();
+    }
+
+    @Override
+    public <T> Optional<T> lookupOptional(Class<T> type, String name) {
+        return Optional.empty();
+    }
+
+    @Override
+    public <T> List<T> lookupList(Class<T> type) {
+        return List.of();
+    }
+
+    @Override
+    public <T> Map<String, T> lookupMap(Class<T> type) {
+        return Map.of();
+    }
+}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java b/maven-compat/src/test/java/org/apache/maven/project/TestModelResolver.java
similarity index 59%
copy from api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
copy to maven-compat/src/test/java/org/apache/maven/project/TestModelResolver.java
index b72d04b76e..1d83b8ccf8 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java
+++ b/maven-compat/src/test/java/org/apache/maven/project/TestModelResolver.java
@@ -16,29 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.api.services;
+package org.apache.maven.project;
 
-import org.apache.maven.api.annotations.Experimental;
+import javax.inject.Named;
+import javax.inject.Singleton;
 
-/**
- * The Exception class throw by the {@link Lookup} service.
- *
- * @since 4.0.0
- */
-@Experimental
-public class LookupException extends MavenException {
-    /**
-     * @param message the message to give
-     * @param e the {@link Exception}
-     */
-    public LookupException(String message, Exception e) {
-        super(message, e);
-    }
+import org.apache.maven.internal.impl.resolver.DefaultModelResolver;
 
-    /**
-     * @param e the {@link Exception}
-     */
-    public LookupException(Exception e) {
-        super(e);
-    }
-}
+@Named
+@Singleton
+@Deprecated
+public class TestModelResolver extends DefaultModelResolver {}
diff --git a/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java b/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java
index 3a00b5e0c4..5feff15253 100644
--- a/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java
+++ b/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java
@@ -24,6 +24,7 @@ import java.io.File;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.maven.SimpleLookup;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.metadata.SwitchableMetadataSource;
 import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -33,6 +34,7 @@ import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
 import org.apache.maven.execution.DefaultMavenExecutionRequest;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.internal.impl.DefaultRepositoryFactory;
 import org.apache.maven.internal.impl.DefaultSession;
 import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.model.Dependency;
@@ -45,6 +47,9 @@ import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException;
 import org.codehaus.plexus.testing.PlexusTest;
 import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
+import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
+import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
 import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
 import org.eclipse.aether.repository.LocalRepository;
 import org.junit.jupiter.api.BeforeEach;
@@ -122,7 +127,14 @@ class LegacyRepositorySystemTest {
         MavenSession mavenSession =
                 new MavenSession(container, session, mavenExecutionRequest, new DefaultMavenExecutionResult());
         legacySupport.setSession(mavenSession);
-        InternalSession iSession = new DefaultSession(mavenSession, null, null, null, null, null);
+        InternalSession iSession = new DefaultSession(
+                mavenSession,
+                null,
+                null,
+                null,
+                new SimpleLookup(List.of(new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
+                        new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider())))),
+                null);
         InternalSession.associate(session, iSession);
 
         ArtifactResolutionResult result = repositorySystem.resolve(request);
diff --git a/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
index c551dc4ae1..8fab6a84bf 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
@@ -26,6 +26,7 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import org.apache.maven.api.model.Dependency;
@@ -39,6 +40,7 @@ import org.apache.maven.api.services.ModelBuilderException;
 import org.apache.maven.api.services.ModelBuilderRequest;
 import org.apache.maven.api.services.ModelBuilderResult;
 import org.apache.maven.api.services.ModelProblemCollector;
+import org.apache.maven.api.services.ModelResolver;
 import org.apache.maven.api.services.ModelSource;
 import org.apache.maven.api.services.ModelTransformer;
 import org.apache.maven.api.services.SuperPomProvider;
@@ -62,12 +64,14 @@ import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.internal.impl.model.DefaultModelBuilder;
 import org.apache.maven.internal.impl.model.DefaultProfileSelector;
 import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
-import org.apache.maven.internal.impl.resolver.DefaultModelResolver;
+import org.apache.maven.internal.impl.resolver.DefaultModelCache;
 import org.apache.maven.model.v4.MavenModelVersion;
 import org.apache.maven.project.MavenProject;
 import org.eclipse.aether.RepositorySystem;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.impl.RemoteRepositoryManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Named
 class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
@@ -133,6 +137,11 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
     @Inject
     private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
 
+    @Inject
+    private ModelResolver modelResolver;
+
+    Logger logger = LoggerFactory.getLogger(getClass());
+
     @Override
     public Model build(RepositorySystemSession session, MavenProject project, Path src) throws ModelBuilderException {
         Model model = project.getModel().getDelegate();
@@ -184,21 +193,32 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
                 dependencyManagementImporter,
                 lifecycleBindingsInjector,
                 pluginConfigurationExpander,
-                profileActivationFilePathInterpolator,
+                null,
                 modelTransformer,
-                versionParser,
-                remoteRepositoryManager);
+                versionParser);
         ModelBuilderRequest.ModelBuilderRequestBuilder request = ModelBuilderRequest.builder();
         request.projectBuild(true);
         request.session(InternalSession.from(session));
         request.source(ModelSource.fromPath(src));
         request.validationLevel(ModelBuilderRequest.VALIDATION_LEVEL_MINIMAL);
         request.locationTracking(false);
-        request.modelResolver(
-                new DefaultModelResolver(remoteRepositoryManager, project.getRemoteProjectRepositories()));
+        request.modelResolver(modelResolver);
         request.transformerContextBuilder(modelBuilder.newTransformerContextBuilder());
         request.systemProperties(session.getSystemProperties());
         request.userProperties(session.getUserProperties());
+        request.modelCache(DefaultModelCache.newInstance(session, false));
+        if (session.getCache() != null) {
+            Map<?, ?> map = (Map) session.getCache().get(session, DefaultModelCache.class.getName());
+            List<String> paths = map.keySet().stream()
+                    .map(Object::toString)
+                    .filter(s -> s.startsWith("SourceCacheKey"))
+                    .map(s -> s.substring("SourceCacheKey[location=".length(), s.indexOf(", tag")))
+                    .sorted()
+                    .distinct()
+                    .toList();
+            logger.info("ModelCache contains " + paths.size());
+            paths.forEach(s -> logger.info("    " + s));
+        }
         return modelBuilder.build(request.build());
     }
 
diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
index 4e04415085..75bf08c9a5 100644
--- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
@@ -32,6 +32,7 @@ import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -41,11 +42,11 @@ import org.apache.maven.RepositoryUtils;
 import org.apache.maven.api.Session;
 import org.apache.maven.api.feature.Features;
 import org.apache.maven.api.model.*;
-import org.apache.maven.api.services.MavenException;
 import org.apache.maven.api.services.ModelBuilder;
 import org.apache.maven.api.services.ModelBuilderException;
 import org.apache.maven.api.services.ModelBuilderRequest;
 import org.apache.maven.api.services.ModelBuilderResult;
+import org.apache.maven.api.services.ModelCache;
 import org.apache.maven.api.services.ModelProblem;
 import org.apache.maven.api.services.ModelResolver;
 import org.apache.maven.api.services.ModelResolverException;
@@ -61,6 +62,8 @@ import org.apache.maven.artifact.InvalidRepositoryException;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.bridge.MavenRepositorySystem;
 import org.apache.maven.internal.impl.InternalSession;
+import org.apache.maven.internal.impl.resolver.DefaultModelCache;
+import org.apache.maven.internal.impl.resolver.DefaultModelRepositoryHolder;
 import org.apache.maven.model.building.ArtifactModelSource;
 import org.apache.maven.model.building.DefaultModelProblem;
 import org.apache.maven.model.building.FileModelSource;
@@ -143,7 +146,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
     }
 
     @Deprecated
-    private ModelSource toSource(org.apache.maven.model.building.ModelSource modelSource) {
+    static ModelSource toSource(org.apache.maven.model.building.ModelSource modelSource) {
         if (modelSource instanceof FileModelSource fms) {
             return ModelSource.fromPath(fms.getPath());
         } else if (modelSource instanceof ArtifactModelSource ams) {
@@ -277,6 +280,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
         private final ConcurrentMap<String, Object> parentCache;
         private final ModelTransformerContextBuilder transformerContextBuilder;
         private final ExecutorService executor;
+        private final ModelCache modelCache;
 
         BuildSession(ProjectBuildingRequest request, boolean localProjects) {
             this.request = request;
@@ -293,6 +297,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
                 this.transformerContextBuilder = null;
             }
             this.parentCache = new ConcurrentHashMap<>();
+            this.modelCache = DefaultModelCache.newInstance(session, true);
         }
 
         ExecutorService createExecutor(int parallelism) {
@@ -368,6 +373,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
                     ModelBuilderRequest.ModelBuilderRequestBuilder builder = getModelBuildingRequest();
                     ModelBuilderRequest request = builder.projectBuild(modelPool != null)
                             .source(modelSource)
+                            .projectBuild(true)
                             .locationTracking(true)
                             .listener(listener)
                             .build();
@@ -1001,18 +1007,26 @@ public class DefaultProjectBuilder implements ProjectBuilder {
 
             RequestTrace trace = RequestTrace.newChild(null, request).newChild(modelBuildingRequest);
 
-            ProjectModelResolver pmr = new ProjectModelResolver(
-                    session,
-                    trace,
-                    repoSystem,
-                    repositoryManager,
-                    repositories,
-                    request.getRepositoryMerging(),
-                    modelPool,
-                    parentCache);
-            ModelResolver resolver = new ModelResolverWrapper(pmr);
-
-            modelBuildingRequest.session(InternalSession.from(session));
+            ModelResolver resolver = new ModelResolverWrapper() {
+                @Override
+                protected org.apache.maven.model.resolution.ModelResolver getResolver(
+                        List<RemoteRepository> repositories) {
+                    return new ProjectModelResolver(
+                            session,
+                            trace,
+                            repoSystem,
+                            repositoryManager,
+                            repositories,
+                            request.getRepositoryMerging(),
+                            modelPool,
+                            parentCache);
+                }
+            };
+
+            InternalSession internalSession = InternalSession.from(session);
+            modelBuildingRequest.session(internalSession.withRemoteRepositories(request.getRemoteRepositories().stream()
+                    .map(r -> internalSession.getRemoteRepository(RepositoryUtils.toRepo(r)))
+                    .toList()));
             modelBuildingRequest.validationLevel(request.getValidationLevel());
             modelBuildingRequest.processPlugins(request.isProcessPlugins());
             modelBuildingRequest.profiles(
@@ -1027,6 +1041,14 @@ public class DefaultProjectBuilder implements ProjectBuilder {
             modelBuildingRequest.userProperties(toMap(request.getUserProperties()));
             // bv4: modelBuildingRequest.setBuildStartTime(request.getBuildStartTime());
             modelBuildingRequest.modelResolver(resolver);
+            modelBuildingRequest.modelRepositoryHolder(new DefaultModelRepositoryHolder(
+                    internalSession,
+                    DefaultModelRepositoryHolder.RepositoryMerging.valueOf(
+                            request.getRepositoryMerging().name()),
+                    repositories.stream()
+                            .map(internalSession::getRemoteRepository)
+                            .toList()));
+            modelBuildingRequest.modelCache(modelCache);
             modelBuildingRequest.transformerContextBuilder(transformerContextBuilder);
             /* TODO: bv4
             InternalMavenSession session =
@@ -1185,18 +1207,29 @@ public class DefaultProjectBuilder implements ProjectBuilder {
         }
     }
 
-    protected class ModelResolverWrapper implements ModelResolver {
-        protected final org.apache.maven.model.resolution.ModelResolver resolver;
+    protected abstract class ModelResolverWrapper implements ModelResolver {
 
-        protected ModelResolverWrapper(org.apache.maven.model.resolution.ModelResolver resolver) {
-            this.resolver = resolver;
-        }
+        protected abstract org.apache.maven.model.resolution.ModelResolver getResolver(
+                List<RemoteRepository> repositories);
 
         @Override
-        public ModelSource resolveModel(Session session, String groupId, String artifactId, String version)
+        public ModelSource resolveModel(
+                Session session, String groupId, String artifactId, String version, Consumer<String> resolved)
                 throws ModelResolverException {
             try {
-                return toSource(resolver.resolveModel(groupId, artifactId, version));
+                InternalSession internalSession = InternalSession.from(session);
+                org.apache.maven.model.resolution.ModelResolver resolver =
+                        getResolver(internalSession.toRepositories(internalSession.getRemoteRepositories()));
+                org.apache.maven.model.Parent p = new org.apache.maven.model.Parent(Parent.newBuilder()
+                        .groupId(groupId)
+                        .artifactId(artifactId)
+                        .version(version)
+                        .build());
+                org.apache.maven.model.building.ModelSource modelSource = resolver.resolveModel(p);
+                if (!p.getVersion().equals(version)) {
+                    resolved.accept(p.getVersion());
+                }
+                return toSource(modelSource);
             } catch (UnresolvableModelException e) {
                 throw new ModelResolverException(e.getMessage(), e.getGroupId(), e.getArtifactId(), e.getVersion(), e);
             }
@@ -1207,6 +1240,9 @@ public class DefaultProjectBuilder implements ProjectBuilder {
                 throws ModelResolverException {
             try {
                 org.apache.maven.model.Parent p = new org.apache.maven.model.Parent(parent);
+                InternalSession internalSession = InternalSession.from(session);
+                org.apache.maven.model.resolution.ModelResolver resolver =
+                        getResolver(internalSession.toRepositories(internalSession.getRemoteRepositories()));
                 ModelSource source = toSource(resolver.resolveModel(p));
                 if (p.getDelegate() != parent) {
                     modified.set(p.getDelegate());
@@ -1222,6 +1258,9 @@ public class DefaultProjectBuilder implements ProjectBuilder {
                 throws ModelResolverException {
             try {
                 org.apache.maven.model.Dependency d = new org.apache.maven.model.Dependency(dependency);
+                InternalSession internalSession = InternalSession.from(session);
+                org.apache.maven.model.resolution.ModelResolver resolver =
+                        getResolver(internalSession.toRepositories(internalSession.getRemoteRepositories()));
                 ModelSource source = toSource(resolver.resolveModel(d));
                 if (d.getDelegate() != dependency) {
                     modified.set(d.getDelegate());
@@ -1231,25 +1270,5 @@ public class DefaultProjectBuilder implements ProjectBuilder {
                 throw new ModelResolverException(e.getMessage(), e.getGroupId(), e.getArtifactId(), e.getVersion(), e);
             }
         }
-
-        @Override
-        public void addRepository(Session session, Repository repository) throws ModelResolverException {
-            addRepository(session, repository, false);
-        }
-
-        @Override
-        public void addRepository(Session session, Repository repository, boolean replace)
-                throws ModelResolverException {
-            try {
-                resolver.addRepository(new org.apache.maven.model.Repository(repository), replace);
-            } catch (org.apache.maven.model.resolution.InvalidRepositoryException e) {
-                throw new MavenException(e);
-            }
-        }
-
-        @Override
-        public ModelResolver newCopy() {
-            return new ModelResolverWrapper(resolver.newCopy());
-        }
     }
 }
diff --git a/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject b/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
index 07598c7664..285f768d41 100644
--- a/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
+++ b/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
@@ -15,55 +15,56 @@ org.apache.maven.internal.impl.DefaultDependencyCollector
 org.apache.maven.internal.impl.DefaultDependencyCoordinateFactory
 org.apache.maven.internal.impl.DefaultLocalRepositoryManager
 org.apache.maven.internal.impl.DefaultMessageBuilderFactory
+org.apache.maven.internal.impl.DefaultModelUrlNormalizer
+org.apache.maven.internal.impl.DefaultModelVersionParser
 org.apache.maven.internal.impl.DefaultModelXmlFactory
+org.apache.maven.internal.impl.DefaultPluginConfigurationExpander
 org.apache.maven.internal.impl.DefaultRepositoryFactory
 org.apache.maven.internal.impl.DefaultSettingsBuilder
 org.apache.maven.internal.impl.DefaultSettingsXmlFactory
+org.apache.maven.internal.impl.DefaultSuperPomProvider
 org.apache.maven.internal.impl.DefaultToolchainsBuilder
 org.apache.maven.internal.impl.DefaultToolchainsXmlFactory
 org.apache.maven.internal.impl.DefaultTransportProvider
+org.apache.maven.internal.impl.DefaultUrlNormalizer
 org.apache.maven.internal.impl.DefaultVersionParser
 org.apache.maven.internal.impl.DefaultVersionRangeResolver
 org.apache.maven.internal.impl.DefaultVersionResolver
-org.apache.maven.internal.impl.DefaultModelVersionParser
-org.apache.maven.internal.impl.DefaultUrlNormalizer
-org.apache.maven.internal.impl.DefaultModelUrlNormalizer
-org.apache.maven.internal.impl.DefaultSuperPomProvider
-org.apache.maven.internal.impl.DefaultPluginConfigurationExpander
 org.apache.maven.internal.impl.ExtensibleEnumRegistries$DefaultLanguageRegistry
 org.apache.maven.internal.impl.ExtensibleEnumRegistries$DefaultPathScopeRegistry
 org.apache.maven.internal.impl.ExtensibleEnumRegistries$DefaultProjectScopeRegistry
+org.apache.maven.internal.impl.model.BuildModelTransformer
+org.apache.maven.internal.impl.model.DefaultDependencyManagementImporter
+org.apache.maven.internal.impl.model.DefaultDependencyManagementInjector
+org.apache.maven.internal.impl.model.DefaultInheritanceAssembler
+org.apache.maven.internal.impl.model.DefaultLifecycleBindingsInjector
 org.apache.maven.internal.impl.model.DefaultModelBuilder
+org.apache.maven.internal.impl.model.DefaultModelInterpolator
+org.apache.maven.internal.impl.model.DefaultModelNormalizer
+org.apache.maven.internal.impl.model.DefaultModelPathTranslator
 org.apache.maven.internal.impl.model.DefaultModelProcessor
 org.apache.maven.internal.impl.model.DefaultModelValidator
 org.apache.maven.internal.impl.model.DefaultModelVersionProcessor
-org.apache.maven.internal.impl.model.DefaultModelNormalizer
-org.apache.maven.internal.impl.model.DefaultModelInterpolator
 org.apache.maven.internal.impl.model.DefaultPathTranslator
-org.apache.maven.internal.impl.model.DefaultRootLocator
-org.apache.maven.internal.impl.model.DefaultModelPathTranslator
-org.apache.maven.internal.impl.model.DefaultInheritanceAssembler
-org.apache.maven.internal.impl.model.DefaultProfileSelector
-org.apache.maven.internal.impl.model.DefaultProfileInjector
 org.apache.maven.internal.impl.model.DefaultPluginManagementInjector
-org.apache.maven.internal.impl.model.DefaultDependencyManagementInjector
-org.apache.maven.internal.impl.model.DefaultDependencyManagementImporter
-org.apache.maven.internal.impl.model.DefaultLifecycleBindingsInjector
+org.apache.maven.internal.impl.model.DefaultProfileInjector
+org.apache.maven.internal.impl.model.DefaultProfileSelector
+org.apache.maven.internal.impl.model.DefaultRootLocator
 org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator
-org.apache.maven.internal.impl.model.BuildModelTransformer
 org.apache.maven.internal.impl.model.profile.FileProfileActivator
 org.apache.maven.internal.impl.model.profile.JdkVersionProfileActivator
 org.apache.maven.internal.impl.model.profile.OperatingSystemProfileActivator
 org.apache.maven.internal.impl.model.profile.PackagingProfileActivator
 org.apache.maven.internal.impl.model.profile.PropertyProfileActivator
-org.apache.maven.internal.impl.resolver.PluginsMetadataGeneratorFactory
-org.apache.maven.internal.impl.resolver.SnapshotMetadataGeneratorFactory
-org.apache.maven.internal.impl.resolver.VersionsMetadataGeneratorFactory
-org.apache.maven.internal.impl.resolver.DefaultVersionResolver
-org.apache.maven.internal.impl.resolver.DefaultVersionRangeResolver
 org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader
 org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader
+org.apache.maven.internal.impl.resolver.DefaultModelResolver
+org.apache.maven.internal.impl.resolver.DefaultVersionRangeResolver
+org.apache.maven.internal.impl.resolver.DefaultVersionResolver
 org.apache.maven.internal.impl.resolver.MavenVersionScheme
+org.apache.maven.internal.impl.resolver.PluginsMetadataGeneratorFactory
+org.apache.maven.internal.impl.resolver.SnapshotMetadataGeneratorFactory
+org.apache.maven.internal.impl.resolver.VersionsMetadataGeneratorFactory
 org.apache.maven.internal.impl.resolver.relocation.DistributionManagementArtifactRelocationSource
 org.apache.maven.internal.impl.resolver.relocation.UserPropertiesArtifactRelocationSource
-org.apache.maven.internal.impl.resolver.type.DefaultTypeProvider
\ No newline at end of file
+org.apache.maven.internal.impl.resolver.type.DefaultTypeProvider
diff --git a/maven-core/src/test/java/org/apache/maven/MavenTestHelper.java b/maven-core/src/test/java/org/apache/maven/MavenTestHelper.java
index 9cb2b347ef..3176a9473b 100644
--- a/maven-core/src/test/java/org/apache/maven/MavenTestHelper.java
+++ b/maven-core/src/test/java/org/apache/maven/MavenTestHelper.java
@@ -18,20 +18,33 @@
  */
 package org.apache.maven;
 
+import java.util.List;
+
 import org.apache.maven.bridge.MavenRepositorySystem;
 import org.apache.maven.execution.DefaultMavenExecutionRequest;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.internal.impl.DefaultRepositoryFactory;
 import org.apache.maven.internal.impl.DefaultSession;
 import org.apache.maven.internal.impl.InternalSession;
 import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
+import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
+import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
 
 public class MavenTestHelper {
     public static DefaultRepositorySystemSession createSession(MavenRepositorySystem repositorySystem) {
         DefaultRepositorySystemSession repoSession = new DefaultRepositorySystemSession(h -> false);
         DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
         MavenSession mavenSession = new MavenSession(repoSession, request, new DefaultMavenExecutionResult());
-        DefaultSession session = new DefaultSession(mavenSession, null, null, repositorySystem, null, null);
+        DefaultSession session = new DefaultSession(
+                mavenSession,
+                null,
+                null,
+                repositorySystem,
+                new SimpleLookup(List.of(new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
+                        new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider())))),
+                null);
         InternalSession.associate(repoSession, session);
         return repoSession;
     }
diff --git a/maven-core/src/test/java/org/apache/maven/SimpleLookup.java b/maven-core/src/test/java/org/apache/maven/SimpleLookup.java
new file mode 100644
index 0000000000..79370b9982
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/SimpleLookup.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.maven;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.maven.api.services.Lookup;
+import org.apache.maven.api.services.LookupException;
+
+public class SimpleLookup implements Lookup {
+    private final List<Object> objects;
+
+    public SimpleLookup(List<Object> objects) {
+        this.objects = objects;
+    }
+
+    @Override
+    public <T> T lookup(Class<T> type) {
+        return objects.stream()
+                .filter(type::isInstance)
+                .map(type::cast)
+                .findAny()
+                .orElseThrow(() -> new LookupException("No service of type " + type));
+    }
+
+    @Override
+    public <T> T lookup(Class<T> type, String name) {
+        return null;
+    }
+
+    @Override
+    public <T> Optional<T> lookupOptional(Class<T> type) {
+        return Optional.empty();
+    }
+
+    @Override
+    public <T> Optional<T> lookupOptional(Class<T> type, String name) {
+        return Optional.empty();
+    }
+
+    @Override
+    public <T> List<T> lookupList(Class<T> type) {
+        return List.of();
+    }
+
+    @Override
+    public <T> Map<String, T> lookupMap(Class<T> type) {
+        return Map.of();
+    }
+}
diff --git a/maven-core/src/test/java/org/apache/maven/internal/transformation/AbstractRepositoryTestCase.java b/maven-core/src/test/java/org/apache/maven/internal/transformation/AbstractRepositoryTestCase.java
index ac48d1d918..6b8298ffd5 100644
--- a/maven-core/src/test/java/org/apache/maven/internal/transformation/AbstractRepositoryTestCase.java
+++ b/maven-core/src/test/java/org/apache/maven/internal/transformation/AbstractRepositoryTestCase.java
@@ -21,10 +21,13 @@ package org.apache.maven.internal.transformation;
 import javax.inject.Inject;
 
 import java.net.MalformedURLException;
+import java.util.List;
 
+import org.apache.maven.SimpleLookup;
 import org.apache.maven.execution.DefaultMavenExecutionRequest;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.internal.impl.DefaultRepositoryFactory;
 import org.apache.maven.internal.impl.DefaultSession;
 import org.apache.maven.internal.impl.InternalSession;
 import org.codehaus.plexus.PlexusContainer;
@@ -33,6 +36,9 @@ import org.eclipse.aether.DefaultRepositorySystemSession;
 import org.eclipse.aether.RepositoryListener;
 import org.eclipse.aether.RepositorySystem;
 import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
+import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
+import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
 import org.eclipse.aether.repository.LocalRepository;
 import org.eclipse.aether.repository.RemoteRepository;
 import org.eclipse.aether.transfer.TransferListener;
@@ -71,7 +77,14 @@ public abstract class AbstractRepositoryTestCase {
 
         DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
         MavenSession mavenSession = new MavenSession(rsession, request, new DefaultMavenExecutionResult());
-        DefaultSession session = new DefaultSession(mavenSession, null, null, null, null, null);
+        DefaultSession session = new DefaultSession(
+                mavenSession,
+                null,
+                null,
+                null,
+                new SimpleLookup(List.of(new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
+                        new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider())))),
+                null);
         InternalSession.associate(rsession, session);
 
         return rsession;
diff --git a/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java b/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java
index 5c48786b51..0fc8db8708 100644
--- a/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java
+++ b/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java
@@ -18,15 +18,23 @@
  */
 package org.apache.maven.internal.transformation.impl;
 
+import javax.annotation.Priority;
 import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
 
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collections;
+import java.util.function.Consumer;
 
+import org.apache.maven.api.Session;
 import org.apache.maven.api.model.Model;
+import org.apache.maven.api.services.ModelResolver;
+import org.apache.maven.api.services.ModelResolverException;
+import org.apache.maven.api.services.ModelSource;
 import org.apache.maven.artifact.repository.MavenArtifactRepository;
 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
 import org.apache.maven.internal.impl.InternalMavenSession;
@@ -86,4 +94,24 @@ public class ConsumerPomBuilderTest extends AbstractRepositoryTestCase {
         assertNotNull(model);
         assertTrue(model.getProfiles().isEmpty());
     }
+
+    @Named
+    @Singleton
+    @Priority(10)
+    public static class MyModelResolver implements ModelResolver {
+        @Override
+        public ModelSource resolveModel(
+                Session session, String groupId, String artifactId, String version, Consumer<String> resolvedVersion)
+                throws ModelResolverException {
+            String id = groupId + ":" + artifactId + ":" + version;
+            if (id.startsWith("org.sonatype.mavenbook.multi:parent:")) {
+                return ModelSource.fromPath(Paths.get("src/test/resources/consumer/simple/pom.xml"));
+            } else if (id.startsWith("org.sonatype.mavenbook.multi:simple-parent:")) {
+                return ModelSource.fromPath(Paths.get("src/test/resources/consumer/simple/simple-parent/pom.xml"));
+            } else if (id.startsWith("org.my.group:parent:")) {
+                return ModelSource.fromPath(Paths.get("src/test/resources/consumer/trivial/pom.xml"));
+            }
+            return null;
+        }
+    }
 }
diff --git a/maven-core/src/test/java/org/apache/maven/model/ModelBuilderTest.java b/maven-core/src/test/java/org/apache/maven/model/ModelBuilderTest.java
index f52cc73aab..4596e69814 100644
--- a/maven-core/src/test/java/org/apache/maven/model/ModelBuilderTest.java
+++ b/maven-core/src/test/java/org/apache/maven/model/ModelBuilderTest.java
@@ -24,11 +24,13 @@ import java.io.File;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.maven.SimpleLookup;
 import org.apache.maven.bridge.MavenRepositorySystem;
 import org.apache.maven.execution.DefaultMavenExecutionRequest;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.internal.impl.DefaultRepositoryFactory;
 import org.apache.maven.internal.impl.DefaultSession;
 import org.apache.maven.internal.impl.InternalSession;
 import org.apache.maven.project.DefaultProjectBuildingRequest;
@@ -38,6 +40,9 @@ import org.apache.maven.resolver.RepositorySystemSessionFactory;
 import org.codehaus.plexus.testing.PlexusTest;
 import org.eclipse.aether.RepositorySystem;
 import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
+import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
+import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -68,8 +73,14 @@ public class ModelBuilderTest {
                 .build();
         request.setRepositorySession(rsession);
         MavenSession msession = new MavenSession(rsession, mavenRequest, new DefaultMavenExecutionResult());
-        InternalSession session =
-                new DefaultSession(msession, repositorySystem, null, mavenRepositorySystem, null, null);
+        InternalSession session = new DefaultSession(
+                msession,
+                repositorySystem,
+                null,
+                mavenRepositorySystem,
+                new SimpleLookup(List.of(new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
+                        new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider())))),
+                null);
         InternalSession.associate(rsession, session);
 
         List<ProjectBuildingResult> results = projectBuilder.build(
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
index ea647749cd..64c616b405 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
@@ -71,6 +71,9 @@ import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.RepositorySystemSession.CloseableSession;
 import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
+import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager;
+import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer;
 import org.eclipse.aether.repository.RemoteRepository;
 import org.eclipse.aether.repository.WorkspaceReader;
 import org.eclipse.aether.resolution.ArtifactResult;
@@ -264,7 +267,8 @@ public class BootstrapCoreExtensionManager {
             } else if (clazz == ArtifactManager.class) {
                 return (T) new DefaultArtifactManager(this);
             } else if (clazz == RepositoryFactory.class) {
-                return (T) new DefaultRepositoryFactory();
+                return (T) new DefaultRepositoryFactory(new DefaultRemoteRepositoryManager(
+                        new DefaultUpdatePolicyAnalyzer(), new DefaultChecksumPolicyProvider()));
                 // } else if (clazz == ModelResolver.class) {
                 //    return (T) new DefaultModelResolver();
             }
diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java
index 5348f9e3a6..9b321edba4 100644
--- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java
+++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java
@@ -1061,8 +1061,7 @@ public class MavenRepositorySystemSupplier implements Supplier<RepositorySystem>
                 new DefaultPluginConfigurationExpander(),
                 new ProfileActivationFilePathInterpolator(new DefaultPathTranslator(), new DefaultRootLocator()),
                 new BuildModelTransformer(),
-                new DefaultModelVersionParser(getVersionScheme()),
-                getRemoteRepositoryManager());
+                new DefaultModelVersionParser(getVersionScheme()));
     }
 
     private RepositorySystem repositorySystem;