Skip to content

Commit f25ce51

Browse files
gnodetclaude
andauthored
[maven-4.0.x] Fix #11920: skip expression validation for profile repository URLs (#12055)
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) <noreply@anthropic.com>
1 parent 1631eac commit f25ce51

3 files changed

Lines changed: 113 additions & 31 deletions

File tree

impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -618,39 +618,43 @@ public void validateRawModel(Session s, Model m, int validationLevel, ModelProbl
618618
}
619619

620620
if (validationLevel > VALIDATION_LEVEL_MINIMAL) {
621-
validateRawRepositories(problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel);
621+
validateRawRepositories(
622+
problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel, false);
622623

623624
validateRawRepositories(
624625
problems,
625626
m.getPluginRepositories(),
626627
"pluginRepositories.pluginRepository.",
627628
EMPTY,
628-
validationLevel);
629+
validationLevel,
630+
false);
629631

630632
for (Profile profile : m.getProfiles()) {
631633
String prefix = "profiles.profile[" + profile.getId() + "].";
632634

633635
validateRawRepositories(
634-
problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel);
636+
problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel, true);
635637

636638
validateRawRepositories(
637639
problems,
638640
profile.getPluginRepositories(),
639641
prefix,
640642
"pluginRepositories.pluginRepository.",
641-
validationLevel);
643+
validationLevel,
644+
true);
642645
}
643646

644647
DistributionManagement distMgmt = m.getDistributionManagement();
645648
if (distMgmt != null) {
646649
validateRawRepository(
647-
problems, distMgmt.getRepository(), "distributionManagement.repository.", "", true);
650+
problems, distMgmt.getRepository(), "distributionManagement.repository.", "", true, false);
648651
validateRawRepository(
649652
problems,
650653
distMgmt.getSnapshotRepository(),
651654
"distributionManagement.snapshotRepository.",
652655
"",
653-
true);
656+
true,
657+
false);
654658
}
655659
}
656660
}
@@ -1483,11 +1487,12 @@ private void validateRawRepositories(
14831487
List<Repository> repositories,
14841488
String prefix,
14851489
String prefix2,
1486-
int validationLevel) {
1490+
int validationLevel,
1491+
boolean skipExpressionCheck) {
14871492
Map<String, Repository> index = new HashMap<>();
14881493

14891494
for (Repository repository : repositories) {
1490-
validateRawRepository(problems, repository, prefix, prefix2, false);
1495+
validateRawRepository(problems, repository, prefix, prefix2, false, skipExpressionCheck);
14911496

14921497
String key = repository.getId();
14931498

@@ -1516,23 +1521,25 @@ private void validateRawRepository(
15161521
Repository repository,
15171522
String prefix,
15181523
String prefix2,
1519-
boolean allowEmptyUrl) {
1524+
boolean allowEmptyUrl,
1525+
boolean skipExpressionCheck) {
15201526
if (repository == null) {
15211527
return;
15221528
}
15231529
if (validateStringNotEmpty(
15241530
prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository)) {
1525-
// Check for uninterpolated expressions in ID - these should have been interpolated by now
1526-
Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getId());
1527-
if (matcher.find()) {
1528-
addViolation(
1529-
problems,
1530-
Severity.ERROR,
1531-
Version.V40,
1532-
prefix + prefix2 + "[" + repository.getId() + "].id",
1533-
null,
1534-
"contains an uninterpolated expression.",
1535-
repository);
1531+
if (!skipExpressionCheck) {
1532+
Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getId());
1533+
if (matcher.find()) {
1534+
addViolation(
1535+
problems,
1536+
Severity.ERROR,
1537+
Version.V40,
1538+
prefix + prefix2 + "[" + repository.getId() + "].id",
1539+
null,
1540+
"contains an uninterpolated expression.",
1541+
repository);
1542+
}
15361543
}
15371544
}
15381545

@@ -1547,17 +1554,18 @@ && validateStringNotEmpty(
15471554
repository.getUrl(),
15481555
null,
15491556
repository)) {
1550-
// Check for uninterpolated expressions in URL - these should have been interpolated by now
1551-
Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl());
1552-
if (matcher.find()) {
1553-
addViolation(
1554-
problems,
1555-
Severity.ERROR,
1556-
Version.V40,
1557-
prefix + prefix2 + "[" + repository.getId() + "].url",
1558-
null,
1559-
"contains an uninterpolated expression.",
1560-
repository);
1557+
if (!skipExpressionCheck) {
1558+
Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl());
1559+
if (matcher.find()) {
1560+
addViolation(
1561+
problems,
1562+
Severity.ERROR,
1563+
Version.V40,
1564+
prefix + prefix2 + "[" + repository.getId() + "].url",
1565+
null,
1566+
"contains an uninterpolated expression.",
1567+
repository);
1568+
}
15611569
}
15621570
}
15631571
}

impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,12 @@ void repositoryWithUninterpolatedId() throws Exception {
910910
&& error.contains("contains an uninterpolated expression")));
911911
}
912912

913+
@Test
914+
void profileWithPropertyInRepositoryUrl() throws Exception {
915+
SimpleProblemCollector result = validateRaw("raw-model/profile-with-property-in-repository-url.xml");
916+
assertViolations(result, 0, 0, 0);
917+
}
918+
913919
@Test
914920
void profileActivationWithAllowedExpression() throws Exception {
915921
SimpleProblemCollector result = validateRaw(
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
23+
24+
<modelVersion>4.0.0</modelVersion>
25+
26+
<groupId>org.apache.maven.validation</groupId>
27+
<artifactId>project</artifactId>
28+
<version>1.0.0-SNAPSHOT</version>
29+
30+
<profiles>
31+
<profile>
32+
<id>maven-mirror</id>
33+
<activation>
34+
<property><name>env.MAVEN_MIRROR_URL</name></property>
35+
</activation>
36+
<repositories>
37+
<repository>
38+
<id>maven-mirror</id>
39+
<url>${env.MAVEN_MIRROR_URL}</url>
40+
</repository>
41+
</repositories>
42+
</profile>
43+
<profile>
44+
<id>snapshots-and-staging</id>
45+
<properties>
46+
<asf.staging>https://repository.apache.org/content/groups/staging/</asf.staging>
47+
<asf.snapshots>https://repository.apache.org/content/repositories/snapshots/</asf.snapshots>
48+
</properties>
49+
<pluginRepositories>
50+
<pluginRepository>
51+
<id>ASF-Staging</id>
52+
<url>${asf.staging}</url>
53+
</pluginRepository>
54+
<pluginRepository>
55+
<id>ASF-Snapshots</id>
56+
<url>${asf.snapshots}</url>
57+
<snapshots>
58+
<enabled>true</enabled>
59+
</snapshots>
60+
<releases>
61+
<enabled>false</enabled>
62+
</releases>
63+
</pluginRepository>
64+
</pluginRepositories>
65+
</profile>
66+
</profiles>
67+
68+
</project>

0 commit comments

Comments
 (0)