From 10e68531522b58e098714f455b11e28fd024f5f5 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 31 Mar 2026 11:41:57 +0200 Subject: [PATCH 1/3] fix: propagate addResource() to model Build for Maven 3 compat When a Maven 3 plugin dynamically adds a resource via project.addResource() or project.getResources().add(), the resource was only added to the internal sources set but not to the model's Build.resources. This caused project.getBuild().getResources() to be out of sync with project.getResources(), breaking plugins like maven-source-plugin that access resources through the Build model. Co-Authored-By: Claude Opus 4.6 --- .../apache/maven/project/MavenProject.java | 7 +++ .../maven/project/ResourceIncludeTest.java | 58 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java b/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java index 45731697a77c..72a81e64a437 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java +++ b/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java @@ -838,6 +838,13 @@ private Resource toConnectedResource(SourceRoot sourceRoot, ProjectScope scope) private void addResource(ProjectScope scope, Resource resource) { addSourceRoot(new DefaultSourceRoot(getBaseDirectory(), scope, resource.getDelegate())); + // Also update the model's Build to maintain compatibility with code that + // accesses resources via project.getBuild().getResources() + if (scope == ProjectScope.MAIN) { + getModelBuild().addResource(resource); + } else { + getModelBuild().addTestResource(resource); + } } /** diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ResourceIncludeTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/ResourceIncludeTest.java index 519dbd57709c..57ad0dbfc825 100644 --- a/impl/maven-core/src/test/java/org/apache/maven/project/ResourceIncludeTest.java +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ResourceIncludeTest.java @@ -281,4 +281,62 @@ void testTargetPathEdgeCases() { placeholderResult.getTargetPath(), "Property placeholder in targetPath should be preserved"); } + + /** + * Verifies that resources added via {@code project.addResource()} or + * {@code project.getResources().add()} are visible through both + * {@code project.getResources()} and {@code project.getBuild().getResources()}. + * This is important for Maven 3 compatibility, since plugins may access + * resources through either path. + * + * @see maven-source-plugin#281 + */ + @Test + void testAddResourceVisibleViaBuildGetResources() { + // Initial state: one resource in sources, none added dynamically + assertEquals(1, project.getResources().size()); + int initialBuildResources = project.getBuild().getResources().size(); + + // Add a resource dynamically (simulating what maven-remote-resources-plugin does) + Resource dynamicResource = new Resource(); + dynamicResource.setDirectory("target/maven-shared-archive-resources"); + project.addResource(dynamicResource); + + // Verify visible via project.getResources() + List projectResources = project.getResources(); + assertEquals(2, projectResources.size(), "Dynamic resource should be visible via project.getResources()"); + + // Verify ALSO visible via project.getBuild().getResources() + List buildResources = project.getBuild().getResources(); + assertEquals( + initialBuildResources + 1, + buildResources.size(), + "Dynamic resource should also be visible via project.getBuild().getResources()"); + + boolean found = + buildResources.stream().anyMatch(r -> r.getDirectory().contains("maven-shared-archive-resources")); + assertTrue(found, "getBuild().getResources() should contain the dynamically added resource"); + } + + /** + * Same as above but using {@code project.getResources().add()} path. + */ + @Test + void testAddResourceViaListVisibleViaBuildGetResources() { + int initialBuildResources = project.getBuild().getResources().size(); + + Resource dynamicResource = new Resource(); + dynamicResource.setDirectory("target/maven-shared-archive-resources"); + project.getResources().add(dynamicResource); + + List buildResources = project.getBuild().getResources(); + assertEquals( + initialBuildResources + 1, + buildResources.size(), + "Resource added via getResources().add() should be visible via getBuild().getResources()"); + + boolean found = + buildResources.stream().anyMatch(r -> r.getDirectory().contains("maven-shared-archive-resources")); + assertTrue(found, "getBuild().getResources() should contain the resource added via getResources().add()"); + } } From 1b40da8f012275b8a57f5052336507a8ff46fe68 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 1 Apr 2026 10:41:25 +0200 Subject: [PATCH 2/3] fix: sync Build.resources from sources set for Maven 3 compat Also sync the model's Build.resources after project building so that project.getBuild().getResources() is consistent with project.getResources() even when resources are defined via (Maven 4.1.0 model) rather than legacy . Co-Authored-By: Claude Opus 4.6 --- .../apache/maven/project/DefaultProjectBuilder.java | 6 ++++++ .../java/org/apache/maven/project/MavenProject.java | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index bcc0e28abba9..efa4ce2efc13 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -771,6 +771,12 @@ implicit fallback (only if they match the default, e.g., inherited) sourceContext.handleResourceConfiguration(ProjectScope.MAIN); sourceContext.handleResourceConfiguration(ProjectScope.TEST); } + + // Sync model Build resources from sources set so that + // project.getBuild().getResources() is consistent with project.getResources(). + // This is needed for Maven 3 plugin compatibility, since some plugins + // (e.g. maven-source-plugin) access resources via project.getBuild().getResources(). + project.syncBuildResources(); } project.setActiveProfiles( diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java b/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java index 72a81e64a437..e6c2c05acbf0 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java +++ b/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java @@ -848,16 +848,21 @@ private void addResource(ProjectScope scope, Resource resource) { } /** - * @deprecated {@link Resource} is replaced by {@link SourceRoot}. + * Syncs {@code Build.resources/testResources} from the {@code sources} set + * for Maven 3 plugin compatibility (e.g. when resources come from {@code }). */ + void syncBuildResources() { + getModelBuild().setResources(new java.util.ArrayList<>(getResources())); + getModelBuild().setTestResources(new java.util.ArrayList<>(getTestResources())); + } + + /** @deprecated {@link Resource} is replaced by {@link SourceRoot}. */ @Deprecated(since = "4.0.0") public void addResource(Resource resource) { addResource(ProjectScope.MAIN, resource); } - /** - * @deprecated {@link Resource} is replaced by {@link SourceRoot}. - */ + /** @deprecated {@link Resource} is replaced by {@link SourceRoot}. */ @Deprecated(since = "4.0.0") public void addTestResource(Resource testResource) { addResource(ProjectScope.TEST, testResource); From 33bfd7931aa37ba247f6f68f1aedf9badc8c715e Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 1 Apr 2026 11:09:40 +0200 Subject: [PATCH 3/3] fix: only sync Build.resources for projects Avoid syncing Build.resources for legacy projects to prevent Path.toString() from converting forward slashes to backslashes on Windows (fixes PomConstructionTest.testTargetPathResourceRegression). Co-Authored-By: Claude Opus 4.6 --- .../apache/maven/project/DefaultProjectBuilder.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index efa4ce2efc13..f9c645be335e 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -772,11 +772,13 @@ implicit fallback (only if they match the default, e.g., inherited) sourceContext.handleResourceConfiguration(ProjectScope.TEST); } - // Sync model Build resources from sources set so that - // project.getBuild().getResources() is consistent with project.getResources(). - // This is needed for Maven 3 plugin compatibility, since some plugins - // (e.g. maven-source-plugin) access resources via project.getBuild().getResources(). - project.syncBuildResources(); + // When resources are defined via (4.1.0 model), sync them to + // the model's Build so project.getBuild().getResources() is consistent. + // For legacy , the model already has the correct resources. + if (sourceContext.hasSources(Language.RESOURCES, ProjectScope.MAIN) + || sourceContext.hasSources(Language.RESOURCES, ProjectScope.TEST)) { + project.syncBuildResources(); + } } project.setActiveProfiles(