Skip to content

Commit d71c3a3

Browse files
gnodetclaude
andcommitted
Fix Source.targetPath incorrectly aligned to basedir (PR #12206)
Cherry-pick from fix/resource-targetpath-compat branch. Supersedes earlier #12178 cherry-pick with expanded fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9a6f7a5 commit d71c3a3

4 files changed

Lines changed: 78 additions & 88 deletions

File tree

impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java

Lines changed: 76 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,6 @@
4545
import org.junit.jupiter.api.Test;
4646
import org.junit.jupiter.api.io.TempDir;
4747

48-
import static org.apache.maven.project.ProjectBuildingResultWithLocationMatcher.projectBuildingResultWithLocation;
49-
import static org.apache.maven.project.ProjectBuildingResultWithProblemMessageMatcher.projectBuildingResultWithProblemMessage;
50-
import static org.hamcrest.MatcherAssert.assertThat;
51-
import static org.hamcrest.Matchers.contains;
52-
import static org.hamcrest.Matchers.containsString;
53-
import static org.hamcrest.Matchers.empty;
54-
import static org.hamcrest.Matchers.greaterThan;
55-
import static org.hamcrest.Matchers.hasKey;
56-
import static org.hamcrest.Matchers.is;
5748
import static org.junit.jupiter.api.Assertions.assertEquals;
5849
import static org.junit.jupiter.api.Assertions.assertFalse;
5950
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -102,15 +93,17 @@ void testVersionlessManagedDependency() throws Exception {
10293
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
10394
configuration.setRepositorySession(mavenSession.getRepositorySession());
10495

105-
ProjectBuildingException e = assertThrows(ProjectBuildingException.class, () -> getContainer()
106-
.lookup(org.apache.maven.project.ProjectBuilder.class)
107-
.build(pomFile, configuration));
108-
assertThat(
109-
e.getResults(),
110-
contains(
111-
projectBuildingResultWithProblemMessage(
112-
"'dependencies.dependency.version' for groupId='org.apache.maven.its', artifactId='a', type='jar' is missing")));
113-
assertThat(e.getResults(), contains(projectBuildingResultWithLocation(5, 9)));
96+
ProjectBuildingException e = assertThrows(
97+
ProjectBuildingException.class,
98+
() -> getContainer()
99+
.lookup(org.apache.maven.project.ProjectBuilder.class)
100+
.build(pomFile, configuration));
101+
assertEquals(1, e.getResults().size());
102+
ProjectBuildingResultWithProblemMessageAssert.assertThat(e.getResults().get(0))
103+
.hasProblemMessage(
104+
"'dependencies.dependency.version' for groupId='org.apache.maven.its', artifactId='a', type='jar' is missing");
105+
ProjectBuildingResultWithLocationAssert.assertThat(e.getResults().get(0))
106+
.hasLocation(5, 9);
114107
}
115108

116109
@Test
@@ -194,7 +187,7 @@ void testReadModifiedPoms(@TempDir Path tempDir) throws Exception {
194187
Files.write(parent.toPath(), parentContent.getBytes(StandardCharsets.UTF_8));
195188
// re-build pom with modified parent
196189
ProjectBuildingResult result = projectBuilder.build(child, configuration);
197-
assertThat(result.getProject().getProperties(), hasKey((Object) "addedProperty"));
190+
assertTrue(result.getProject().getProperties().containsKey("addedProperty"));
198191
}
199192

200193
@Test
@@ -242,19 +235,18 @@ void testReadInvalidPom() throws Exception {
242235

243236
// single project build entry point
244237
Exception ex = assertThrows(Exception.class, () -> projectBuilder.build(pomFile, configuration));
245-
assertThat(ex.getMessage(), containsString("Received non-all-whitespace CHARACTERS or CDATA event"));
238+
assertTrue(ex.getMessage().contains("Received non-all-whitespace CHARACTERS or CDATA event"));
246239

247240
// multi projects build entry point
248241
ProjectBuildingException pex = assertThrows(
249242
ProjectBuildingException.class,
250243
() -> projectBuilder.build(Collections.singletonList(pomFile), false, configuration));
251244
assertEquals(1, pex.getResults().size());
252245
assertNotNull(pex.getResults().get(0).getPomFile());
253-
assertThat(pex.getResults().get(0).getProblems().size(), greaterThan(0));
254-
assertThat(
255-
pex.getResults(),
256-
contains(projectBuildingResultWithProblemMessage(
257-
"Received non-all-whitespace CHARACTERS or CDATA event in nextTag()")));
246+
assertTrue(pex.getResults().get(0).getProblems().size() > 0);
247+
ProjectBuildingResultWithProblemMessageAssert.assertThat(
248+
pex.getResults().get(0))
249+
.hasProblemMessage("Received non-all-whitespace CHARACTERS or CDATA event in nextTag()");
258250
}
259251

260252
@Test
@@ -305,7 +297,7 @@ private MavenProject findChildProject(List<ProjectBuildingResult> results) {
305297

306298
private void assertResultShowNoError(List<ProjectBuildingResult> results) {
307299
for (ProjectBuildingResult result : results) {
308-
assertThat(result.getProblems(), is(empty()));
300+
assertTrue(result.getProblems().isEmpty());
309301
assertNotNull(result.getProject());
310302
}
311303
}
@@ -653,10 +645,11 @@ void testNonModularResourcesOnlyWithImplicitJavaFallback() throws Exception {
653645
List<SourceRoot> mainResources = project.getEnabledSourceRoots(ProjectScope.MAIN, Language.RESOURCES)
654646
.toList();
655647
assertTrue(
656-
mainResources.stream().anyMatch(sr -> sr.directory()
657-
.toString()
658-
.replace(File.separatorChar, '/')
659-
.contains("src/main/custom-resources")),
648+
mainResources.stream()
649+
.anyMatch(sr -> sr.directory()
650+
.toString()
651+
.replace(File.separatorChar, '/')
652+
.contains("src/main/custom-resources")),
660653
"Should have custom main resources from <sources>");
661654

662655
// Verify legacy Java directories are used as fallback
@@ -726,10 +719,11 @@ void testNonModularResourcesOnlyWithExplicitLegacyDirectoriesRejected() throws E
726719
List<SourceRoot> mainResources = project.getEnabledSourceRoots(ProjectScope.MAIN, Language.RESOURCES)
727720
.toList();
728721
assertTrue(
729-
mainResources.stream().anyMatch(sr -> sr.directory()
730-
.toString()
731-
.replace(File.separatorChar, '/')
732-
.contains("src/main/custom-resources")),
722+
mainResources.stream()
723+
.anyMatch(sr -> sr.directory()
724+
.toString()
725+
.replace(File.separatorChar, '/')
726+
.contains("src/main/custom-resources")),
733727
"Should have custom main resources from <sources>");
734728

735729
// Verify NO Java source roots (legacy was rejected, none in <sources>)
@@ -900,14 +894,16 @@ void testMultipleDirectoriesSameModule() throws Exception {
900894
assertEquals(2, moduleCount, "Both main sources should be for com.example.app module");
901895

902896
// One should be implicit directory, one should be generated-sources
903-
boolean hasImplicitDir = mainJavaRoots.stream().anyMatch(sr -> sr.directory()
904-
.toString()
905-
.replace(File.separatorChar, '/')
906-
.contains("src/com.example.app/main/java"));
907-
boolean hasGeneratedDir = mainJavaRoots.stream().anyMatch(sr -> sr.directory()
908-
.toString()
909-
.replace(File.separatorChar, '/')
910-
.contains("target/generated-sources/com.example.app/java"));
897+
boolean hasImplicitDir = mainJavaRoots.stream()
898+
.anyMatch(sr -> sr.directory()
899+
.toString()
900+
.replace(File.separatorChar, '/')
901+
.contains("src/com.example.app/main/java"));
902+
boolean hasGeneratedDir = mainJavaRoots.stream()
903+
.anyMatch(sr -> sr.directory()
904+
.toString()
905+
.replace(File.separatorChar, '/')
906+
.contains("target/generated-sources/com.example.app/java"));
911907

912908
assertTrue(hasImplicitDir, "Should have implicit source directory for module");
913909
assertTrue(hasGeneratedDir, "Should have generated-sources directory for module");
@@ -1002,8 +998,8 @@ void testDuplicateEnabledSources() throws Exception {
1002998
}
1003999

10041000
@Test
1005-
void testSourceTargetPathRemainsRelative() throws Exception {
1006-
File pom = getProject("source-target-path");
1001+
void testResourceTargetPathRemainsRelativeInCompatLayer() throws Exception {
1002+
File pom = getProject("resource-target-path");
10071003

10081004
MavenSession mavenSession = createMavenSession(null);
10091005
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
@@ -1015,34 +1011,51 @@ void testSourceTargetPathRemainsRelative() throws Exception {
10151011

10161012
MavenProject project = result.getProject();
10171013

1018-
// Verify main resources have relative targetPath preserved
1014+
// Verify main resources via SourceRoot API
10191015
List<SourceRoot> mainResources = project.getEnabledSourceRoots(ProjectScope.MAIN, Language.RESOURCES)
10201016
.toList();
10211017
assertEquals(1, mainResources.size());
1022-
assertTrue(mainResources.get(0).targetPath().isPresent());
1023-
assertEquals(Path.of(".grammar"), mainResources.get(0).targetPath().get());
1018+
assertTrue(mainResources.get(0).targetPath().isPresent(), "Main resource should have a targetPath");
1019+
assertFalse(
1020+
mainResources.get(0).targetPath().get().isAbsolute(),
1021+
"SourceRoot targetPath must be relative, got: "
1022+
+ mainResources.get(0).targetPath().get());
1023+
assertEquals(
1024+
Path.of("META-INF/tags/rdc"), mainResources.get(0).targetPath().get());
10241025

1025-
// Verify test resources have relative targetPath preserved
1026+
// Verify test resources via SourceRoot API
10261027
List<SourceRoot> testResources = project.getEnabledSourceRoots(ProjectScope.TEST, Language.RESOURCES)
10271028
.toList();
10281029
assertEquals(1, testResources.size());
1029-
assertTrue(testResources.get(0).targetPath().isPresent());
1030-
assertEquals(Path.of("META-INF/test"), testResources.get(0).targetPath().get());
1030+
assertTrue(testResources.get(0).targetPath().isPresent(), "Test resource should have a targetPath");
1031+
assertFalse(
1032+
testResources.get(0).targetPath().get().isAbsolute(),
1033+
"SourceRoot targetPath must be relative, got: "
1034+
+ testResources.get(0).targetPath().get());
1035+
assertEquals(
1036+
Path.of("org/apache/maven/messages"),
1037+
testResources.get(0).targetPath().get());
10311038

1032-
// Verify the compat layer also returns relative targetPath
1039+
// Verify compat layer: MavenProject.getResources() must return relative targetPath
10331040
List<org.apache.maven.model.Resource> resources = project.getResources();
10341041
assertEquals(1, resources.size());
1035-
assertEquals(".grammar", resources.get(0).getTargetPath());
1042+
assertFalse(
1043+
Path.of(resources.get(0).getTargetPath()).isAbsolute(),
1044+
"Resource targetPath from getResources() must be relative, got: "
1045+
+ resources.get(0).getTargetPath());
10361046

1047+
// Verify compat layer: MavenProject.getTestResources() must return relative targetPath
10371048
List<org.apache.maven.model.Resource> testResourceList = project.getTestResources();
10381049
assertEquals(1, testResourceList.size());
1039-
assertEquals(
1040-
"META-INF" + File.separator + "test", testResourceList.get(0).getTargetPath());
1050+
assertFalse(
1051+
Path.of(testResourceList.get(0).getTargetPath()).isAbsolute(),
1052+
"Test resource targetPath from getTestResources() must be relative, got: "
1053+
+ testResourceList.get(0).getTargetPath());
10411054
}
10421055

10431056
@Test
1044-
void testResourceTargetPathRemainsRelativeInCompatLayer() throws Exception {
1045-
File pom = getProject("resource-target-path");
1057+
void testSourceTargetPathRemainsRelative() throws Exception {
1058+
File pom = getProject("source-target-path");
10461059

10471060
MavenSession mavenSession = createMavenSession(null);
10481061
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
@@ -1054,45 +1067,28 @@ void testResourceTargetPathRemainsRelativeInCompatLayer() throws Exception {
10541067

10551068
MavenProject project = result.getProject();
10561069

1057-
// Verify main resources via SourceRoot API
1070+
// Verify main resources have relative targetPath preserved
10581071
List<SourceRoot> mainResources = project.getEnabledSourceRoots(ProjectScope.MAIN, Language.RESOURCES)
10591072
.toList();
10601073
assertEquals(1, mainResources.size());
10611074
assertTrue(mainResources.get(0).targetPath().isPresent());
1062-
assertFalse(
1063-
mainResources.get(0).targetPath().get().isAbsolute(),
1064-
"SourceRoot targetPath must be relative, got: "
1065-
+ mainResources.get(0).targetPath().get());
1066-
assertEquals(
1067-
Path.of("META-INF/tags/rdc"), mainResources.get(0).targetPath().get());
1075+
assertEquals(Path.of(".grammar"), mainResources.get(0).targetPath().get());
10681076

1069-
// Verify test resources via SourceRoot API
1077+
// Verify test resources have relative targetPath preserved
10701078
List<SourceRoot> testResources = project.getEnabledSourceRoots(ProjectScope.TEST, Language.RESOURCES)
10711079
.toList();
10721080
assertEquals(1, testResources.size());
10731081
assertTrue(testResources.get(0).targetPath().isPresent());
1074-
assertFalse(
1075-
testResources.get(0).targetPath().get().isAbsolute(),
1076-
"SourceRoot targetPath must be relative, got: "
1077-
+ testResources.get(0).targetPath().get());
1078-
assertEquals(
1079-
Path.of("org/apache/maven/messages"),
1080-
testResources.get(0).targetPath().get());
1082+
assertEquals(Path.of("META-INF/test"), testResources.get(0).targetPath().get());
10811083

1082-
// Verify compat layer: MavenProject.getResources() must return relative targetPath
1084+
// Verify the compat layer also returns relative targetPath
10831085
List<org.apache.maven.model.Resource> resources = project.getResources();
10841086
assertEquals(1, resources.size());
1085-
assertEquals(
1086-
"META-INF" + File.separator + "tags" + File.separator + "rdc",
1087-
resources.get(0).getTargetPath(),
1088-
"Resource targetPath from getResources() must remain relative");
1087+
assertEquals(".grammar", resources.get(0).getTargetPath());
10891088

1090-
// Verify compat layer: MavenProject.getTestResources() must return relative targetPath
10911089
List<org.apache.maven.model.Resource> testResourceList = project.getTestResources();
10921090
assertEquals(1, testResourceList.size());
10931091
assertEquals(
1094-
"org" + File.separator + "apache" + File.separator + "maven" + File.separator + "messages",
1095-
testResourceList.get(0).getTargetPath(),
1096-
"Test resource targetPath from getTestResources() must remain relative");
1092+
"META-INF" + File.separator + "test", testResourceList.get(0).getTargetPath());
10971093
}
10981094
}

impl/maven-core/src/test/projects/project-builder/resource-target-path/pom.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ under the License.
2828
<version>1.0-SNAPSHOT</version>
2929
<packaging>jar</packaging>
3030

31-
<name>Resource TargetPath Compat Test</name>
32-
<description>Test that targetPath in legacy resource elements remains relative through the compat layer</description>
33-
3431
<build>
3532
<resources>
3633
<resource>

impl/maven-core/src/test/projects/project-builder/source-target-path/pom.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ under the License.
2828
<version>1.0-SNAPSHOT</version>
2929
<packaging>jar</packaging>
3030

31-
<name>Source TargetPath Test</name>
32-
<description>Test that targetPath in source elements remains relative to output directory</description>
33-
3431
<build>
3532
<sources>
3633
<source>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ private Source alignToBaseDirectory(Source source, Path basedir) {
134134
if (newDir != oldDir) {
135135
source = source.withDirectory(newDir);
136136
}
137-
// Note: targetPath is intentionally NOT aligned to basedir.
137+
// targetPath is intentionally NOT aligned to basedir.
138138
// It is relative to the output directory (target/classes or target/test-classes),
139-
// not to the project base directory. See maven.mdo Source.targetPath documentation.
139+
// not to the project base directory.
140140
}
141141
return source;
142142
}

0 commit comments

Comments
 (0)