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 f6343606de Introduce RepositoryAwareRequest interface to consolidate 
repository handling (#11238)
f6343606de is described below

commit f6343606dea8ddda99c01c14890d541c7585fcef
Author: Tamas Cservenak <[email protected]>
AuthorDate: Fri Oct 10 09:30:49 2025 +0200

    Introduce RepositoryAwareRequest interface to consolidate repository 
handling (#11238)
    
    This change introduces a new RepositoryAwareRequest interface that 
consolidates
    repository handling across multiple Maven service request types, addressing
    issues with duplicate repositories being passed to resolvers.
    
    Key changes:
    
    * Add RepositoryAwareRequest interface with repository validation:
      - Provides getRepositories() method and validate() logic
      - Prevents duplicate repositories and null entries
      - Consolidates common repository functionality
    
    * Refactor service request interfaces to extend RepositoryAwareRequest:
      - ArtifactResolverRequest, DependencyResolverRequest, ModelBuilderRequest
      - ProjectBuilderRequest, VersionRangeResolverRequest, 
VersionResolverRequest
      - Apply repository validation in all implementations
    
    * Fix repository leakage in DefaultProjectBuilder:
      - Store project-specific repositories in BuildSession
      - Implement proper repository merging based on strategy
      - Prevent cross-contamination between sibling projects
    
    * Update resolvers to use toResolvingRepositories() for consistent handling
    
    * Add RepositoryLeakageTest to verify proper isolation between projects
    
    This eliminates duplicate repositories being sent to resolvers and ensures
    consistent repository handling across all Maven service requests.
---
 .../api/services/ArtifactResolverRequest.java      |   7 +-
 .../api/services/DependencyResolverRequest.java    |   7 +-
 .../maven/api/services/ModelBuilderRequest.java    |   7 +-
 .../maven/api/services/ProjectBuilderRequest.java  |   4 +-
 .../maven/api/services/RepositoryAwareRequest.java | 117 +++++++++++
 .../api/services/VersionRangeResolverRequest.java  |   7 +-
 .../maven/api/services/VersionResolverRequest.java |   7 +-
 .../maven/project/DefaultProjectBuilder.java       |  48 ++++-
 .../maven/project/RepositoryLeakageTest.java       | 214 +++++++++++++++++++++
 .../org/apache/maven/impl/AbstractSession.java     |   6 +
 .../apache/maven/impl/DefaultArtifactResolver.java |   2 +-
 .../maven/impl/DefaultDependencyResolver.java      |   2 +-
 .../maven/impl/DefaultVersionRangeResolver.java    |   2 +-
 .../apache/maven/impl/DefaultVersionResolver.java  |   2 +-
 .../org/apache/maven/impl/InternalSession.java     |   2 +
 15 files changed, 398 insertions(+), 36 deletions(-)

diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
index fb012fab30..7e832a95e4 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
@@ -40,14 +40,11 @@
  */
 @Experimental
 @Immutable
-public interface ArtifactResolverRequest extends Request<Session> {
+public interface ArtifactResolverRequest extends RepositoryAwareRequest {
 
     @Nonnull
     Collection<? extends ArtifactCoordinates> getCoordinates();
 
-    @Nullable
-    List<RemoteRepository> getRepositories();
-
     @Nonnull
     static ArtifactResolverRequestBuilder builder() {
         return new ArtifactResolverRequestBuilder();
@@ -127,7 +124,7 @@ private static class DefaultArtifactResolverRequest extends 
BaseRequest<Session>
                     @Nonnull List<RemoteRepository> repositories) {
                 super(session, trace);
                 this.coordinates = List.copyOf(requireNonNull(coordinates, 
"coordinates cannot be null"));
-                this.repositories = repositories;
+                this.repositories = validate(repositories);
             }
 
             @Nonnull
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
index e9b3ab956b..5be250824d 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
@@ -55,7 +55,7 @@
  */
 @Experimental
 @Immutable
-public interface DependencyResolverRequest extends Request<Session> {
+public interface DependencyResolverRequest extends RepositoryAwareRequest {
 
     enum RequestType {
         COLLECT,
@@ -119,9 +119,6 @@ enum RequestType {
     @Nullable
     Version getTargetVersion();
 
-    @Nullable
-    List<RemoteRepository> getRepositories();
-
     @Nonnull
     static DependencyResolverRequestBuilder builder() {
         return new DependencyResolverRequestBuilder();
@@ -479,7 +476,7 @@ public String toString() {
                 this.pathScope = requireNonNull(pathScope, "pathScope cannot 
be null");
                 this.pathTypeFilter = (pathTypeFilter != null) ? 
pathTypeFilter : DEFAULT_FILTER;
                 this.targetVersion = targetVersion;
-                this.repositories = repositories;
+                this.repositories = validate(repositories);
                 if (verbose && requestType != RequestType.COLLECT) {
                     throw new IllegalArgumentException("verbose cannot only be 
true when collecting dependencies");
                 }
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 14141a6d0c..826ffe8fc4 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
@@ -43,7 +43,7 @@
  */
 @Experimental
 @Immutable
-public interface ModelBuilderRequest extends Request<Session> {
+public interface ModelBuilderRequest extends RepositoryAwareRequest {
 
     /**
      * The possible request types for building a model.
@@ -133,9 +133,6 @@ enum RepositoryMerging {
     @Nonnull
     RepositoryMerging getRepositoryMerging();
 
-    @Nullable
-    List<RemoteRepository> getRepositories();
-
     @Nullable
     ModelTransformer getLifecycleBindingsInjector();
 
@@ -338,7 +335,7 @@ private static class DefaultModelBuilderRequest extends 
BaseRequest<Session> imp
                         systemProperties != null ? 
Map.copyOf(systemProperties) : session.getSystemProperties();
                 this.userProperties = userProperties != null ? 
Map.copyOf(userProperties) : session.getUserProperties();
                 this.repositoryMerging = repositoryMerging;
-                this.repositories = repositories != null ? 
List.copyOf(repositories) : null;
+                this.repositories = repositories != null ? 
List.copyOf(validate(repositories)) : null;
                 this.lifecycleBindingsInjector = lifecycleBindingsInjector;
             }
 
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
index 82129b4f1b..307ee19559 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
@@ -43,7 +43,7 @@
  */
 @Experimental
 @Immutable
-public interface ProjectBuilderRequest extends Request<Session> {
+public interface ProjectBuilderRequest extends RepositoryAwareRequest {
 
     /**
      * Gets the path to the project to build.
@@ -265,7 +265,7 @@ private static class DefaultProjectBuilderRequest extends 
BaseRequest<Session>
                 this.allowStubModel = allowStubModel;
                 this.recursive = recursive;
                 this.processPlugins = processPlugins;
-                this.repositories = repositories;
+                this.repositories = validate(repositories);
             }
 
             @Nonnull
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryAwareRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryAwareRequest.java
new file mode 100644
index 0000000000..f948ecdea4
--- /dev/null
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryAwareRequest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.api.services;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.maven.api.RemoteRepository;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Immutable;
+import org.apache.maven.api.annotations.Nullable;
+
+/**
+ * Base interface for service requests that involve remote repository 
operations.
+ * This interface provides common functionality for requests that need to 
specify
+ * and validate remote repositories for artifact resolution, dependency 
collection,
+ * model building, and other Maven operations.
+ *
+ * <p>Implementations of this interface can specify a list of remote 
repositories
+ * to be used during the operation. If no repositories are specified (null),
+ * the session's default remote repositories will be used. The repositories
+ * are validated to ensure they don't contain duplicates or null entries.
+ *
+ * <p>Remote repositories are used for:
+ * <ul>
+ *   <li>Resolving artifacts and their metadata</li>
+ *   <li>Downloading parent POMs and dependency POMs</li>
+ *   <li>Retrieving version information and ranges</li>
+ *   <li>Accessing plugin artifacts and their dependencies</li>
+ * </ul>
+ *
+ * <p>Repository validation ensures data integrity by:
+ * <ul>
+ *   <li>Preventing duplicate repositories that could cause confusion</li>
+ *   <li>Rejecting null repository entries that would cause failures</li>
+ *   <li>Maintaining consistent repository ordering for reproducible 
builds</li>
+ * </ul>
+ *
+ * @since 4.0.0
+ * @see RemoteRepository
+ * @see Session#getRemoteRepositories()
+ */
+@Experimental
+@Immutable
+public interface RepositoryAwareRequest extends Request<Session> {
+
+    /**
+     * Returns the list of remote repositories to be used for this request.
+     *
+     * <p>If this method returns {@code null}, the session's default remote 
repositories
+     * will be used. If a non-null list is returned, it will be used instead 
of the
+     * session's repositories, allowing for request-specific repository 
configuration.
+     *
+     * <p>The returned list should not contain duplicate repositories (based 
on their
+     * equality) or null entries, as these will cause validation failures when 
the
+     * request is processed.
+     *
+     * @return the list of remote repositories to use, or {@code null} to use 
session defaults
+     * @see Session#getRemoteRepositories()
+     */
+    @Nullable
+    List<RemoteRepository> getRepositories();
+
+    /**
+     * Validates a list of remote repositories to ensure data integrity.
+     *
+     * <p>This method performs the following validations:
+     * <ul>
+     *   <li>Allows null input (returns null)</li>
+     *   <li>Ensures no duplicate repositories exist in the list</li>
+     *   <li>Ensures no null repository entries exist in the list</li>
+     * </ul>
+     *
+     * <p>Duplicate detection is based on the {@code 
RemoteRepository#equals(Object)}
+     * method, which typically compares repository IDs and URLs.
+     *
+     * @param repositories the list of repositories to validate, may be {@code 
null}
+     * @return the same list if validation passes, or {@code null} if input 
was {@code null}
+     * @throws IllegalArgumentException if the list contains duplicate 
repositories
+     * @throws IllegalArgumentException if the list contains null repository 
entries
+     */
+    default List<RemoteRepository> validate(List<RemoteRepository> 
repositories) {
+        if (repositories == null) {
+            return null;
+        }
+        HashSet<RemoteRepository> set = new HashSet<>(repositories);
+        if (repositories.size() != set.size()) {
+            throw new IllegalArgumentException(
+                    "Repository list contains duplicate entries. Each 
repository must be unique based on its ID and URL. "
+                            + "Found " + repositories.size() + " repositories 
but only " + set.size()
+                            + " unique entries.");
+        }
+        if (repositories.stream().anyMatch(Objects::isNull)) {
+            throw new IllegalArgumentException(
+                    "Repository list contains null entries. All repository 
entries must be non-null RemoteRepository instances.");
+        }
+        return repositories;
+    }
+}
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
index 52abe9e89a..2f69c574a3 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
@@ -36,14 +36,11 @@
  * @since 4.0.0
  */
 @Experimental
-public interface VersionRangeResolverRequest extends Request<Session> {
+public interface VersionRangeResolverRequest extends RepositoryAwareRequest {
 
     @Nonnull
     ArtifactCoordinates getArtifactCoordinates();
 
-    @Nullable
-    List<RemoteRepository> getRepositories();
-
     @Nonnull
     static VersionRangeResolverRequest build(
             @Nonnull Session session, @Nonnull ArtifactCoordinates 
artifactCoordinates) {
@@ -111,7 +108,7 @@ private static class DefaultVersionResolverRequest extends 
BaseRequest<Session>
                     @Nullable List<RemoteRepository> repositories) {
                 super(session, trace);
                 this.artifactCoordinates = artifactCoordinates;
-                this.repositories = repositories;
+                this.repositories = validate(repositories);
             }
 
             @Nonnull
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
index c8dee58a8f..b510dcc2de 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
@@ -36,14 +36,11 @@
  * @since 4.0.0
  */
 @Experimental
-public interface VersionResolverRequest extends Request<Session> {
+public interface VersionResolverRequest extends RepositoryAwareRequest {
 
     @Nonnull
     ArtifactCoordinates getArtifactCoordinates();
 
-    @Nullable
-    List<RemoteRepository> getRepositories();
-
     @Nonnull
     static VersionResolverRequest build(@Nonnull Session session, @Nonnull 
ArtifactCoordinates artifactCoordinates) {
         return builder()
@@ -113,7 +110,7 @@ private static class DefaultVersionResolverRequest extends 
BaseRequest<Session>
                     @Nullable List<RemoteRepository> repositories) {
                 super(session, trace);
                 this.artifactCoordinates = artifactCoordinates;
-                this.repositories = repositories;
+                this.repositories = validate(repositories);
             }
 
             @Nonnull
diff --git 
a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
 
b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
index ecf97e4b1b..1de9eeccc5 100644
--- 
a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
+++ 
b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
@@ -184,7 +184,7 @@ public ProjectBuildingResult build(Artifact artifact, 
ProjectBuildingRequest req
     public ProjectBuildingResult build(Artifact artifact, boolean 
allowStubModel, ProjectBuildingRequest request)
             throws ProjectBuildingException {
         try (BuildSession bs = new BuildSession(request)) {
-            return bs.build(false, artifact, allowStubModel);
+            return bs.build(false, artifact, allowStubModel, 
request.getRemoteRepositories());
         }
     }
 
@@ -318,6 +318,18 @@ class BuildSession implements AutoCloseable {
         private final ModelBuilder.ModelBuilderSession modelBuilderSession;
         private final Map<String, MavenProject> projectIndex = new 
ConcurrentHashMap<>(256);
 
+        // Store computed repositories per project to avoid leakage between 
projects
+        private final Map<String, List<ArtifactRepository>> 
projectRepositories = new ConcurrentHashMap<>();
+
+        /**
+         * Get the effective repositories for a project. If project-specific 
repositories
+         * have been computed and stored, use those; otherwise fall back to 
request repositories.
+         */
+        private List<ArtifactRepository> getEffectiveRepositories(String 
projectId) {
+            List<ArtifactRepository> stored = 
projectRepositories.get(projectId);
+            return stored != null ? stored : request.getRemoteRepositories();
+        }
+
         BuildSession(ProjectBuildingRequest request) {
             this.request = request;
             InternalSession session = 
InternalSession.from(request.getRepositorySession());
@@ -429,7 +441,8 @@ ProjectBuildingResult build(boolean parent, Path pomFile, 
ModelSource modelSourc
             }
         }
 
-        ProjectBuildingResult build(boolean parent, Artifact artifact, boolean 
allowStubModel)
+        ProjectBuildingResult build(
+                boolean parent, Artifact artifact, boolean allowStubModel, 
List<ArtifactRepository> repositories)
                 throws ProjectBuildingException {
             org.eclipse.aether.artifact.Artifact pomArtifact = 
RepositoryUtils.toArtifact(artifact);
             pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact);
@@ -438,9 +451,10 @@ ProjectBuildingResult build(boolean parent, Artifact 
artifact, boolean allowStub
 
             try {
                 ArtifactCoordinates coordinates = 
session.createArtifactCoordinates(session.getArtifact(pomArtifact));
+                // Use provided repositories if available, otherwise fall back 
to request repositories
                 ArtifactResolverRequest req = ArtifactResolverRequest.builder()
                         .session(session)
-                        .repositories(request.getRemoteRepositories().stream()
+                        .repositories(repositories.stream()
                                 .map(RepositoryUtils::toRepo)
                                 .map(session::getRemoteRepository)
                                 .toList())
@@ -850,7 +864,30 @@ private void initParent(MavenProject project, 
ModelBuilderResult result) {
                     // remote repositories with those found in the pom.xml, 
along with the existing externally
                     // defined repositories.
                     //
-                    
request.getRemoteRepositories().addAll(project.getRemoteArtifactRepositories());
+                    // Compute merged repositories for this project and store 
in session
+                    // instead of mutating the shared request to avoid leakage 
between projects
+                    List<ArtifactRepository> mergedRepositories;
+                    switch (request.getRepositoryMerging()) {
+                        case POM_DOMINANT -> {
+                            LinkedHashSet<ArtifactRepository> reposes =
+                                    new 
LinkedHashSet<>(project.getRemoteArtifactRepositories());
+                            reposes.addAll(request.getRemoteRepositories());
+                            mergedRepositories = List.copyOf(reposes);
+                        }
+                        case REQUEST_DOMINANT -> {
+                            LinkedHashSet<ArtifactRepository> reposes =
+                                    new 
LinkedHashSet<>(request.getRemoteRepositories());
+                            
reposes.addAll(project.getRemoteArtifactRepositories());
+                            mergedRepositories = List.copyOf(reposes);
+                        }
+                        default -> throw new IllegalArgumentException(
+                                "Unsupported repository merging: " + 
request.getRepositoryMerging());
+                    }
+
+                    // Store the computed repositories for this project in 
BuildSession storage
+                    // to avoid mutating the shared request and causing 
leakage between projects
+                    projectRepositories.put(project.getId(), 
mergedRepositories);
+
                     Path parentPomFile = parentModel.getPomFile();
                     if (parentPomFile != null) {
                         project.setParentFile(parentPomFile.toFile());
@@ -870,7 +907,8 @@ private void initParent(MavenProject project, 
ModelBuilderResult result) {
                     } else {
                         Artifact parentArtifact = project.getParentArtifact();
                         try {
-                            parent = build(true, parentArtifact, 
false).getProject();
+                            parent = build(true, parentArtifact, false, 
getEffectiveRepositories(project.getId()))
+                                    .getProject();
                         } catch (ProjectBuildingException e) {
                             // MNG-4488 where let invalid parents slide on by
                             if (logger.isDebugEnabled()) {
diff --git 
a/impl/maven-core/src/test/java/org/apache/maven/project/RepositoryLeakageTest.java
 
b/impl/maven-core/src/test/java/org/apache/maven/project/RepositoryLeakageTest.java
new file mode 100644
index 0000000000..b5ff18f872
--- /dev/null
+++ 
b/impl/maven-core/src/test/java/org/apache/maven/project/RepositoryLeakageTest.java
@@ -0,0 +1,214 @@
+/*
+ * 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.project;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.codehaus.plexus.testing.PlexusTest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * Test to verify that repositories from one project don't leak to sibling 
projects.
+ */
+@PlexusTest
+public class RepositoryLeakageTest extends AbstractMavenProjectTestCase {
+
+    @Test
+    @SuppressWarnings("checkstyle:MethodLength")
+    public void testRepositoryLeakageBetweenSiblings() throws Exception {
+        // Create a temporary directory structure for our test
+        Path tempDir = Files.createTempDirectory("maven-repo-leakage-test");
+
+        try {
+            // Create parent POM
+            Path parentPom = tempDir.resolve("pom.xml");
+            Files.writeString(
+                    parentPom,
+                    """
+                <?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>test</groupId>
+                    <artifactId>parent</artifactId>
+                    <version>1.0</version>
+                    <packaging>pom</packaging>
+
+                    <modules>
+                        <module>child1</module>
+                        <module>child2</module>
+                    </modules>
+                </project>
+                """);
+
+            // Create child1 with specific repository
+            Path child1Dir = tempDir.resolve("child1");
+            Files.createDirectories(child1Dir);
+            Path child1Pom = child1Dir.resolve("pom.xml");
+            Files.writeString(
+                    child1Pom,
+                    """
+                <?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>
+                    <parent>
+                        <groupId>test</groupId>
+                        <artifactId>parent</artifactId>
+                        <version>1.0</version>
+                    </parent>
+                    <artifactId>child1</artifactId>
+
+                    <repositories>
+                        <repository>
+                            <id>child1-repo</id>
+                            <url>https://child1.example.com/repo</url>
+                        </repository>
+                    </repositories>
+                </project>
+                """);
+
+            // Create child2 with different repository
+            Path child2Dir = tempDir.resolve("child2");
+            Files.createDirectories(child2Dir);
+            Path child2Pom = child2Dir.resolve("pom.xml");
+            Files.writeString(
+                    child2Pom,
+                    """
+                <?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>
+                    <parent>
+                        <groupId>test</groupId>
+                        <artifactId>parent</artifactId>
+                        <version>1.0</version>
+                    </parent>
+                    <artifactId>child2</artifactId>
+
+                    <repositories>
+                        <repository>
+                            <id>child2-repo</id>
+                            <url>https://child2.example.com/repo</url>
+                        </repository>
+                    </repositories>
+                </project>
+                """);
+
+            // Create a shared ProjectBuildingRequest
+            ProjectBuildingRequest sharedRequest = newBuildingRequest();
+
+            // Build child1 first
+            ProjectBuildingResult result1 = 
projectBuilder.build(child1Pom.toFile(), sharedRequest);
+            MavenProject child1Project = result1.getProject();
+
+            // Capture repositories after building child1
+
+            // Build child2 using the same shared request
+            ProjectBuildingResult result2 = 
projectBuilder.build(child2Pom.toFile(), sharedRequest);
+            MavenProject child2Project = result2.getProject();
+
+            // Capture repositories after building child2
+            List<ArtifactRepository> repositoriesAfterChild2 = 
List.copyOf(sharedRequest.getRemoteRepositories());
+
+            // Verify that child1 has its own repository
+            boolean child1HasOwnRepo = 
child1Project.getRemoteArtifactRepositories().stream()
+                    .anyMatch(repo -> "child1-repo".equals(repo.getId()));
+            assertTrue(child1HasOwnRepo, "Child1 should have its own 
repository");
+
+            // Verify that child2 has its own repository
+            boolean child2HasOwnRepo = 
child2Project.getRemoteArtifactRepositories().stream()
+                    .anyMatch(repo -> "child2-repo".equals(repo.getId()));
+            assertTrue(child2HasOwnRepo, "Child2 should have its own 
repository");
+
+            // Print debug information
+            System.out.println("=== REPOSITORY LEAKAGE TEST RESULTS ===");
+            System.out.println(
+                    "Repositories in shared request after building child2: " + 
repositoriesAfterChild2.size());
+            repositoriesAfterChild2.forEach(
+                    repo -> System.out.println("  - " + repo.getId() + " (" + 
repo.getUrl() + ")"));
+
+            System.out.println("Child1 project repositories:");
+            child1Project
+                    .getRemoteArtifactRepositories()
+                    .forEach(repo -> System.out.println("  - " + repo.getId() 
+ " (" + repo.getUrl() + ")"));
+
+            System.out.println("Child2 project repositories:");
+            child2Project
+                    .getRemoteArtifactRepositories()
+                    .forEach(repo -> System.out.println("  - " + repo.getId() 
+ " (" + repo.getUrl() + ")"));
+            System.out.println("=======================================");
+
+            // Check for leakage: child2 should NOT have child1's repository
+            boolean child2HasChild1Repo = 
child2Project.getRemoteArtifactRepositories().stream()
+                    .anyMatch(repo -> "child1-repo".equals(repo.getId()));
+            assertFalse(child2HasChild1Repo, "Child2 should NOT have child1's 
repository (leakage detected!)");
+
+            // Check for leakage in the shared request
+            boolean sharedRequestHasChild1Repo =
+                    repositoriesAfterChild2.stream().anyMatch(repo -> 
"child1-repo".equals(repo.getId()));
+            boolean sharedRequestHasChild2Repo =
+                    repositoriesAfterChild2.stream().anyMatch(repo -> 
"child2-repo".equals(repo.getId()));
+
+            // Print debug information
+            /*
+            System.out.println("Repositories after child1: " + 
repositoriesAfterChild1.size());
+            repositoriesAfterChild1.forEach(repo -> System.out.println("  - " 
+ repo.getId() + ": " + repo.getUrl()));
+
+            System.out.println("Repositories after child2: " + 
repositoriesAfterChild2.size());
+            repositoriesAfterChild2.forEach(repo -> System.out.println("  - " 
+ repo.getId() + ": " + repo.getUrl()));
+            */
+
+            // The shared request should not accumulate repositories from both 
children
+            if (sharedRequestHasChild1Repo && sharedRequestHasChild2Repo) {
+                fail("REPOSITORY LEAKAGE DETECTED: Shared request contains 
repositories from both children!");
+            }
+
+        } finally {
+            // Clean up
+            deleteRecursively(tempDir.toFile());
+        }
+    }
+
+    private void deleteRecursively(File file) {
+        if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            if (children != null) {
+                for (File child : children) {
+                    deleteRecursively(child);
+                }
+            }
+        }
+        file.delete();
+    }
+}
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java
index 642e8610d1..7992df53b0 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java
@@ -279,6 +279,12 @@ public 
List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<
         return repositories == null ? null : map(repositories, 
this::toRepository);
     }
 
+    @Override
+    public List<org.eclipse.aether.repository.RemoteRepository> 
toResolvingRepositories(
+            List<RemoteRepository> repositories) {
+        return getRepositorySystem().newResolutionRepositories(getSession(), 
toRepositories(repositories));
+    }
+
     @Override
     public org.eclipse.aether.repository.RemoteRepository 
toRepository(RemoteRepository repository) {
         if (repository instanceof DefaultRemoteRepository 
defaultRemoteRepository) {
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java
index 3614056b28..9f22790f39 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java
@@ -91,7 +91,7 @@ protected ArtifactResolverResult 
doResolve(ArtifactResolverRequest request) {
         InternalSession session = InternalSession.from(request.getSession());
         RequestTraceHelper.ResolverTrace trace = 
RequestTraceHelper.enter(session, request);
         try {
-            List<RemoteRepository> repositories = session.toRepositories(
+            List<RemoteRepository> repositories = 
session.toResolvingRepositories(
                     request.getRepositories() != null ? 
request.getRepositories() : session.getRemoteRepositories());
 
             List<ResolverRequest> requests = new ArrayList<>();
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
index 278d7feb7e..d29c3f369a 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
@@ -152,7 +152,7 @@ public DependencyResolverResult collect(@Nonnull 
DependencyResolverRequest reque
                     .setRoot(root != null ? session.toDependency(root, false) 
: null)
                     .setDependencies(session.toDependencies(dependencies, 
false))
                     
.setManagedDependencies(session.toDependencies(managedDependencies, true))
-                    
.setRepositories(session.toRepositories(remoteRepositories))
+                    
.setRepositories(session.toResolvingRepositories(remoteRepositories))
                     .setRequestContext(trace.context())
                     .setTrace(trace.trace());
             collectRequest.setResolutionScope(resolutionScope);
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java
index df182d976a..b0097d5248 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java
@@ -69,7 +69,7 @@ public VersionRangeResolverResult 
doResolve(VersionRangeResolverRequest request)
                     session.getSession(),
                     new VersionRangeRequest(
                                     
session.toArtifact(request.getArtifactCoordinates()),
-                                    session.toRepositories(
+                                    session.toResolvingRepositories(
                                             request.getRepositories() != null
                                                     ? request.getRepositories()
                                                     : 
session.getRemoteRepositories()),
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java
index c80a1d24ad..1f233f604b 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java
@@ -61,7 +61,7 @@ protected VersionResolverResult 
doResolve(VersionResolverRequest request) throws
         try {
             VersionRequest req = new VersionRequest(
                             
session.toArtifact(request.getArtifactCoordinates()),
-                            session.toRepositories(
+                            session.toResolvingRepositories(
                                     request.getRepositories() != null
                                             ? request.getRepositories()
                                             : session.getRemoteRepositories()),
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java
index b3ce36d47b..7d9945077f 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java
@@ -101,6 +101,8 @@ <REQ extends Request<?>, REP extends Result<REQ>> List<REP> 
requests(
 
     List<org.eclipse.aether.repository.RemoteRepository> 
toRepositories(List<RemoteRepository> repositories);
 
+    List<org.eclipse.aether.repository.RemoteRepository> 
toResolvingRepositories(List<RemoteRepository> repositories);
+
     org.eclipse.aether.repository.RemoteRepository 
toRepository(RemoteRepository repository);
 
     org.eclipse.aether.repository.LocalRepository toRepository(LocalRepository 
repository);


Reply via email to