diff --git a/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelInterpolator.java b/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelInterpolator.java
index ced2d1598c1..39a58ad05e3 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelInterpolator.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelInterpolator.java
@@ -211,7 +211,7 @@ String projectProperty(Model model, Path projectDir, String subExpr, boolean pre
return projectDir.toAbsolutePath().toString();
} else if (subExpr.startsWith("basedir.")) {
try {
- Object value = ReflectionValueExtractor.evaluate(subExpr, projectDir.toAbsolutePath(), false);
+ Object value = ReflectionValueExtractor.evaluate(subExpr, projectDir.toAbsolutePath(), true);
if (value != null) {
return value.toString();
}
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelValidator.java
index 278b6984d49..ec0ee2af7c5 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelValidator.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelValidator.java
@@ -1343,13 +1343,19 @@ private void validateRawRepositories(
// only allow ${basedir} and ${project.basedir}
Matcher m = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl());
while (m.find()) {
- if (!("basedir".equals(m.group(1)) || "project.basedir".equals(m.group(1)))) {
- validateStringNoExpression(
- prefix + prefix2 + "[" + repository.getId() + "].url",
+ String expr = m.group(1);
+ if (!("basedir".equals(expr)
+ || "project.basedir".equals(expr)
+ || expr.startsWith("project.basedir.")
+ || "project.rootDirectory".equals(expr)
+ || expr.startsWith("project.rootDirectory."))) {
+ addViolation(
problems,
Severity.ERROR,
Version.V40,
- repository.getUrl(),
+ prefix + prefix2 + "[" + repository.getId() + "].url",
+ null,
+ "contains an unsupported expression (only expressions starting with 'project.basedir' or 'project.rootDirectory' are supported).",
repository);
break;
}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultModelValidatorTest.java b/impl/maven-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultModelValidatorTest.java
index 3392a86b446..7c990ca21c7 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultModelValidatorTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultModelValidatorTest.java
@@ -805,7 +805,7 @@ void repositoryWithExpression() throws Exception {
SimpleProblemCollector result = validateFile("raw-model/repository-with-expression.xml");
assertViolations(result, 0, 1, 0);
assertEquals(
- "'repositories.repository.[repo].url' contains an expression but should be a constant.",
+ "'repositories.repository.[repo].url' contains an unsupported expression (only expressions starting with 'project.basedir' or 'project.rootDirectory' are supported).",
result.getErrors().get(0));
}
diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8465RepositoryWithProjectDirTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8465RepositoryWithProjectDirTest.java
new file mode 100644
index 00000000000..b90a239e22e
--- /dev/null
+++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8465RepositoryWithProjectDirTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.it;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * This is a test set for MNG-8465.
+ */
+class MavenITmng8465RepositoryWithProjectDirTest extends AbstractMavenIntegrationTestCase {
+
+ MavenITmng8465RepositoryWithProjectDirTest() {
+ super("[4.0.0-rc-3-SNAPSHOT,)");
+ }
+
+ /**
+ * Verify various supported repository URLs.
+ */
+ @Test
+ void testProjectDir() throws Exception {
+ Path basedir = extractResources("/mng-8465").getAbsoluteFile().toPath();
+
+ Verifier verifier = newVerifier(basedir.toString());
+ verifier.addCliArgument("help:effective-pom");
+ verifier.execute();
+ List urls = verifier.loadLogLines().stream()
+ .filter(s -> s.trim().contains("file://"))
+ .toList();
+ assertEquals(4, urls.size());
+ }
+}
diff --git a/its/core-it-suite/src/test/resources/mng-8465/pom.xml b/its/core-it-suite/src/test/resources/mng-8465/pom.xml
new file mode 100644
index 00000000000..d8e808d478e
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/mng-8465/pom.xml
@@ -0,0 +1,29 @@
+
+
+ org.apache.maven.its.mng8465
+ test
+ 1.0
+ pom
+
+ Maven Integration Test :: MNG-8465
+ Test repositories can be defined using ${project.basedir} and ${project.rootDirectory}.
+
+
+
+ test
+ file://${project.basedir}/repo
+
+
+ test2
+ ${project.basedir.uri}repo
+
+
+ test3
+ file://${project.rootDirectory}/repo
+
+
+ test4
+ ${project.rootDirectory.uri}repo
+
+
+