diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml
index f98c7e019fc5..be93a2a485e4 100644
--- a/maven-model-builder/pom.xml
+++ b/maven-model-builder/pom.xml
@@ -179,6 +179,7 @@ under the License.
org.apache.maven.model.superpom.SuperPomProvider#getSuperModel(java.lang.String):METHOD_RETURN_TYPE_CHANGED
org.apache.maven.model.validation.DefaultModelValidator#validateDependencyVersion(org.apache.maven.model.building.ModelProblemCollector,org.apache.maven.model.Dependency,java.lang.String):METHOD_REMOVED
org.apache.maven.model.validation.ModelValidator#validateFileModel(org.apache.maven.model.Model,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT
+ org.apache.maven.model.validation.ModelValidator#validateExternalProfiles(java.util.List,org.apache.maven.model.Model,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
index 704557951342..73d5f3b14a58 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
@@ -754,6 +754,7 @@ private void activateFileModel(
profileInjector.injectProfile(inputModel, activeProfile, request, problems);
}
+ modelValidator.validateExternalProfiles(activeExternalProfiles, inputModel, request, problems);
for (Profile activeProfile : activeExternalProfiles) {
profileInjector.injectProfile(inputModel, activeProfile, request, problems);
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java
index 246e2f8b1314..b51bbc22c73f 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java
@@ -24,6 +24,7 @@
import java.io.File;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
@@ -788,6 +789,54 @@ public void validateEffectiveModel(Model ma, ModelBuildingRequest request, Model
}
}
+ @Override
+ public void validateExternalProfiles(
+ List activeExternalProfiles,
+ Model ma,
+ ModelBuildingRequest request,
+ ModelProblemCollector problems) {
+ org.apache.maven.api.model.Model m = ma.getDelegate();
+ // check for id clashes in repositories
+ for (Profile profile : activeExternalProfiles.stream()
+ .map(org.apache.maven.model.Profile::getDelegate)
+ .collect(Collectors.toList())) {
+ String externalRepositoriesSource = "external profile with id '" + profile.getId() + "' in settings.xml";
+ validateUniqueRepositoryIds(
+ false, m.getRepositories(), profile.getRepositories(), externalRepositoriesSource, problems);
+ validateUniqueRepositoryIds(
+ true,
+ m.getPluginRepositories(),
+ profile.getPluginRepositories(),
+ externalRepositoriesSource,
+ problems);
+ }
+ }
+
+ private void validateUniqueRepositoryIds(
+ boolean isPluginRepository,
+ Collection pomRepositories,
+ Collection externalRepositories,
+ String externalRepositoriesSource,
+ ModelProblemCollector problems) {
+ for (Repository externalRepository : externalRepositories) {
+ Optional clashingPomRepository = pomRepositories.stream()
+ .filter(r -> Objects.equals(r.getId(), externalRepository.getId()))
+ .filter(r -> !Objects.equals(r.getUrl(), externalRepository.getUrl()))
+ .findFirst();
+ if (clashingPomRepository.isPresent()) {
+ addViolation(
+ problems,
+ Severity.WARNING,
+ Version.BASE,
+ isPluginRepository ? "pluginRepositories.repository" : "repositories.repository",
+ clashingPomRepository.get().getId(),
+ "is overwritten by the repository with same id but having a different url from "
+ + externalRepositoriesSource,
+ clashingPomRepository.get());
+ }
+ }
+ }
+
private void validate20RawDependencies(
ModelProblemCollector problems,
List dependencies,
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java
index 2817d95fc66d..bb87370e0ef9 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java
@@ -18,7 +18,10 @@
*/
package org.apache.maven.model.validation;
+import java.util.List;
+
import org.apache.maven.model.Model;
+import org.apache.maven.model.Profile;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblemCollector;
@@ -49,6 +52,24 @@ default void validateFileModel(Model model, ModelBuildingRequest request, ModelP
*/
void validateRawModel(Model model, ModelBuildingRequest request, ModelProblemCollector problems);
+ /**
+ * Checks the specified (raw) model for clashes with the passed active external profiles. The raw model is the
+ * file model + buildpom filter transformation and has not been subjected to inheritance, interpolation or profile/default injection.
+ *
+ * @param activeExternalProfiles the active profiles coming from external sources (settings.xml), must not be {@code null}
+ * @param model The model to validate, must not be {@code null}.
+ * @param request The model building request that holds further settings, must not be {@code null}.
+ * @param problems The container used to collect problems that were encountered, must not be {@code null}.
+ * @since 4.0.0
+ */
+ default void validateExternalProfiles(
+ List activeExternalProfiles,
+ Model model,
+ ModelBuildingRequest request,
+ ModelProblemCollector problems) {
+ // do nothing
+ }
+
/**
* Checks the specified (effective) model for missing or invalid values. The effective model is fully assembled and
* has undergone inheritance, interpolation and other model operations.