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 2026/05/14 19:10:09 UTC
(maven) branch master updated: Fix #11920: skip expression validation for profile repository URLs
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 cee3c33c74 Fix #11920: skip expression validation for profile repository URLs
cee3c33c74 is described below
commit cee3c33c74a80263e227fb19c0a9ce1a2a9712f0
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu May 14 21:10:04 2026 +0200
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) <no...@anthropic.com>
---
.../maven/impl/model/DefaultModelValidator.java | 69 ++++++++++++----------
.../impl/model/DefaultModelValidatorTest.java | 6 ++
.../profile-with-property-in-repository-url.xml | 68 +++++++++++++++++++++
3 files changed, 112 insertions(+), 31 deletions(-)
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 72917cd7c6..6e73c57bcc 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
@@ -668,39 +668,42 @@ && equals(parent.getArtifactId(), model.getArtifactId())) {
if (validationLevel > VALIDATION_LEVEL_MINIMAL) {
validateRawRepositories(
- problems, model.getRepositories(), "repositories.repository.", EMPTY, validationLevel);
+ problems, model.getRepositories(), "repositories.repository.", EMPTY, validationLevel, false);
validateRawRepositories(
problems,
model.getPluginRepositories(),
"pluginRepositories.pluginRepository.",
EMPTY,
- validationLevel);
+ validationLevel,
+ false);
for (Profile profile : model.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 = model.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);
}
}
}
@@ -1575,11 +1578,12 @@ private void validateRawRepositories(
List<Repository> repositories,
String prefix,
String prefix2,
- int validationLevel) {
+ int validationLevel,
+ boolean skipExpressionCheck) {
Map<String, Repository> index = new HashMap<>();
for (Repository repository : repositories) {
- validateRawRepository(problems, repository, prefix, prefix2, false);
+ validateRawRepository(problems, repository, prefix, prefix2, false, skipExpressionCheck);
String key = repository.getId();
@@ -1608,23 +1612,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);
+ }
}
}
@@ -1639,17 +1645,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 df38b262f7..24ed0596ed 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
@@ -943,6 +943,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 0000000000..e954139c2c
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/validation/raw-model/profile-with-property-in-repository-url.xml
@@ -0,0 +1,68 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.validation</groupId>
+ <artifactId>project</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <profiles>
+ <profile>
+ <id>maven-mirror</id>
+ <activation>
+ <property><name>env.MAVEN_MIRROR_URL</name></property>
+ </activation>
+ <repositories>
+ <repository>
+ <id>maven-mirror</id>
+ <url>${env.MAVEN_MIRROR_URL}</url>
+ </repository>
+ </repositories>
+ </profile>
+ <profile>
+ <id>snapshots-and-staging</id>
+ <properties>
+ <asf.staging>https://repository.apache.org/content/groups/staging/</asf.staging>
+ <asf.snapshots>https://repository.apache.org/content/repositories/snapshots/</asf.snapshots>
+ </properties>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>ASF-Staging</id>
+ <url>${asf.staging}</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>ASF-Snapshots</id>
+ <url>${asf.snapshots}</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ </pluginRepository>
+ </pluginRepositories>
+ </profile>
+ </profiles>
+
+</project>