From 9519f87bbafa64665c9d7adc2a4eb38455a723cb Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 14 May 2026 21:10:04 +0200 Subject: [PATCH] Fix #11920: skip expression validation for profile repository URLs Profile properties are injected after raw model validation, so expressions in profile repository URLs/IDs cannot be validated at this stage. Skip the uninterpolated expression check for repositories inside profiles to allow deferred property interpolation. Co-authored-by: Claude Opus 4.6 (1M context) --- .../impl/model/DefaultModelValidator.java | 70 +++++++++++-------- .../impl/model/DefaultModelValidatorTest.java | 6 ++ ...rofile-with-property-in-repository-url.xml | 68 ++++++++++++++++++ 3 files changed, 113 insertions(+), 31 deletions(-) create mode 100644 impl/maven-impl/src/test/resources/poms/validation/raw-model/profile-with-property-in-repository-url.xml diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java index 159ac111d18a..79840fd52a11 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java @@ -618,39 +618,43 @@ public void validateRawModel(Session s, Model m, int validationLevel, ModelProbl } if (validationLevel > VALIDATION_LEVEL_MINIMAL) { - validateRawRepositories(problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel); + validateRawRepositories( + problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel, false); validateRawRepositories( problems, m.getPluginRepositories(), "pluginRepositories.pluginRepository.", EMPTY, - validationLevel); + validationLevel, + false); for (Profile profile : m.getProfiles()) { String prefix = "profiles.profile[" + profile.getId() + "]."; validateRawRepositories( - problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel); + problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel, true); validateRawRepositories( problems, profile.getPluginRepositories(), prefix, "pluginRepositories.pluginRepository.", - validationLevel); + validationLevel, + true); } DistributionManagement distMgmt = m.getDistributionManagement(); if (distMgmt != null) { validateRawRepository( - problems, distMgmt.getRepository(), "distributionManagement.repository.", "", true); + problems, distMgmt.getRepository(), "distributionManagement.repository.", "", true, false); validateRawRepository( problems, distMgmt.getSnapshotRepository(), "distributionManagement.snapshotRepository.", "", - true); + true, + false); } } } @@ -1483,11 +1487,12 @@ private void validateRawRepositories( List repositories, String prefix, String prefix2, - int validationLevel) { + int validationLevel, + boolean skipExpressionCheck) { Map index = new HashMap<>(); for (Repository repository : repositories) { - validateRawRepository(problems, repository, prefix, prefix2, false); + validateRawRepository(problems, repository, prefix, prefix2, false, skipExpressionCheck); String key = repository.getId(); @@ -1516,23 +1521,25 @@ private void validateRawRepository( Repository repository, String prefix, String prefix2, - boolean allowEmptyUrl) { + boolean allowEmptyUrl, + boolean skipExpressionCheck) { if (repository == null) { return; } if (validateStringNotEmpty( prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository)) { - // Check for uninterpolated expressions in ID - these should have been interpolated by now - Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getId()); - if (matcher.find()) { - addViolation( - problems, - Severity.ERROR, - Version.V40, - prefix + prefix2 + "[" + repository.getId() + "].id", - null, - "contains an uninterpolated expression.", - repository); + if (!skipExpressionCheck) { + Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getId()); + if (matcher.find()) { + addViolation( + problems, + Severity.ERROR, + Version.V40, + prefix + prefix2 + "[" + repository.getId() + "].id", + null, + "contains an uninterpolated expression.", + repository); + } } } @@ -1547,17 +1554,18 @@ && validateStringNotEmpty( repository.getUrl(), null, repository)) { - // Check for uninterpolated expressions in URL - these should have been interpolated by now - Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl()); - if (matcher.find()) { - addViolation( - problems, - Severity.ERROR, - Version.V40, - prefix + prefix2 + "[" + repository.getId() + "].url", - null, - "contains an uninterpolated expression.", - repository); + if (!skipExpressionCheck) { + Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl()); + if (matcher.find()) { + addViolation( + problems, + Severity.ERROR, + Version.V40, + prefix + prefix2 + "[" + repository.getId() + "].url", + null, + "contains an uninterpolated expression.", + repository); + } } } } diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java index dc118703bb4e..1624fd3cb074 100644 --- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java +++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java @@ -910,6 +910,12 @@ void repositoryWithUninterpolatedId() throws Exception { && error.contains("contains an uninterpolated expression"))); } + @Test + void profileWithPropertyInRepositoryUrl() throws Exception { + SimpleProblemCollector result = validateRaw("raw-model/profile-with-property-in-repository-url.xml"); + assertViolations(result, 0, 0, 0); + } + @Test void profileActivationWithAllowedExpression() throws Exception { SimpleProblemCollector result = validateRaw( diff --git a/impl/maven-impl/src/test/resources/poms/validation/raw-model/profile-with-property-in-repository-url.xml b/impl/maven-impl/src/test/resources/poms/validation/raw-model/profile-with-property-in-repository-url.xml new file mode 100644 index 000000000000..e954139c2c23 --- /dev/null +++ b/impl/maven-impl/src/test/resources/poms/validation/raw-model/profile-with-property-in-repository-url.xml @@ -0,0 +1,68 @@ + + + + + 4.0.0 + + org.apache.maven.validation + project + 1.0.0-SNAPSHOT + + + + maven-mirror + + env.MAVEN_MIRROR_URL + + + + maven-mirror + ${env.MAVEN_MIRROR_URL} + + + + + snapshots-and-staging + + https://repository.apache.org/content/groups/staging/ + https://repository.apache.org/content/repositories/snapshots/ + + + + ASF-Staging + ${asf.staging} + + + ASF-Snapshots + ${asf.snapshots} + + true + + + false + + + + + + +