Fix resource targetPath resolution to be relative to output directory (fixes #11381) by gnodet · Pull Request #11394 · apache/maven (original) (raw)

added 2 commits

November 5, 2025 15:13

@gnodet

… output directory

This commit fixes a regression in Maven 4 where resource targetPath was being resolved relative to the project base directory instead of the output directory (target/classes or target/test-classes).

The issue was in the DefaultSourceRoot constructor that takes a Resource parameter. It was resolving targetPath relative to baseDir instead of the output directory.

Changes made:

This restores Maven 3.x behavior where relative targetPath values in resources are correctly resolved relative to the output directory.

Fixes apache#11381

@gnodet

…elative targetPath

This commit fixes two issues in ConnectedResource:

  1. Handle null output directories: When the Build object doesn't have output directories set (e.g., in tests), use default values (target/classes for main scope, target/test-classes for test scope).

  2. Compute relative targetPath: The SourceRoot stores the targetPath as a resolved path (absolute or relative to baseDir), but the Resource model expects it to be relative to the output directory. Added a helper method computeRelativeTargetPath() to extract the relative path from the resolved path by relativizing it against the output directory.

Also updated ResourceIncludeTest to:

This ensures that the targetPath is correctly preserved through the conversion chain from Resource -> SourceRoot -> ConnectedResource.

@gnodet gnodet changed the title[GH-11381] Fix resource targetPath resolution to be relative to output directory Fix resource targetPath resolution to be relative to output directory (fixes #11381)

Nov 5, 2025

@gnodet gnodet marked this pull request as draft

November 5, 2025 22:43

@gnodet

The root cause of the issue was that DefaultSourceRoot was resolving the targetPath against baseDir (or baseDir + outputDir), which required complex logic in ConnectedResource to extract the relative path back out.

This commit simplifies the approach by keeping the targetPath as a relative path in DefaultSourceRoot (using Path::of instead of resolving it). This eliminates the need for:

Changes:

This ensures that the targetPath is correctly preserved through the conversion chain from Resource -> SourceRoot -> ConnectedResource.

@gnodet

…rojectBuilder

Since the targetPath is now kept as a relative path in DefaultSourceRoot, the outputDir parameter is no longer needed when creating DefaultSourceRoot instances from Resources.

Changes:

@gnodet gnodet marked this pull request as ready for review

November 6, 2025 09:08

cstamas

@gnodet

Based on PR comments, the solution has been updated:

  1. SourceRoot.targetPath() returns a Path relative to the project's basedir (e.g., 'target/classes/custom-output')

    • Reverted DefaultSourceRoot to resolve targetPath against baseDir
  2. ConnectedResource.getTargetPath() (Maven 3 API) returns a path relative to the output directory (e.g., 'custom-output')

    • Added computeRelativeTargetPath() method to make the path relative to the output directory when converting from SourceRoot to Resource

This maintains backward compatibility with Maven 3 API while using the new Maven 4 API internally.

Changes:

desruisseaux

@gnodet

…directory

This commit fixes the regression where resources with a relative targetPath were being copied to the project root instead of relative to the output directory (target/classes or target/test-classes).

Changes:

  1. DefaultSourceRoot.fromModel: Store targetPath as a relative path instead of resolving it against baseDir and outputDir. This ensures that SourceRoot.targetPath() returns a relative path as intended by the Maven 4 API javadoc.

  2. ConnectedResource.computeRelativeTargetPath: Simplified to directly return the relative targetPath from SourceRoot, since it's now always stored as relative.

  3. Updated tests to expect relative paths from SourceRoot.targetPath().

Maven 4 API Conformance:

Maven 3 Compatibility:

Example: With custom-dir:

Fixes apache#11381

@gnodet

Enhanced the javadoc for SourceRoot.targetPath() and targetPath(Project) to make it explicit that:

  1. targetPath() returns a path that is typically relative to the output directory (e.g., 'custom-dir' or 'META-INF/resources'), but may be absolute if explicitly specified.

  2. targetPath(Project) returns the fully resolved absolute path where files should be copied, with clear examples of how it handles:

    • Empty Optional: returns the default output directory
    • Relative path: resolves against the output directory
    • Absolute path: returns unchanged

These clarifications help implementers understand the intended behavior and prevent regressions like apacheGH-11381 where targetPath was incorrectly stored as an absolute path.

@gnodet

desruisseaux

@gnodet

…ctory()

This commit improves the documentation for resource targetPath handling to clarify the Maven 4 API semantics while preserving Maven 3 backward compatibility.

Key documentation improvements:

  1. SourceRoot.targetPath():

    • Clarifies that relative paths are resolved relative to the output directory (target/classes for MAIN scope, target/test-classes for TEST scope)
    • Documents that absolute paths are used as-is
    • Explicitly states Maven 3 compatibility is maintained
    • Adds concrete examples showing path resolution
  2. SourceRoot.targetPath(Project):

    • Documents the complete resolution algorithm step-by-step
    • Provides detailed examples with actual paths
    • Cross-references Project.getOutputDirectory()
  3. Project.getOutputDirectory():

    • Clarifies that it returns the directory for both compiled classes AND resources
    • Documents its role in SourceRoot targetPath resolution
    • Explicitly states Maven 3 compatibility semantics
  4. DefaultSourceRoot constructor from Resource:

    • Documents that targetPath is stored as-is (not resolved against basedir)
    • Clarifies that baseDir parameter is only used for source directory resolution
    • Explains how this preserves Maven 3.x behavior

Implementation details:

Related to apache#11381

@gnodet

This commit significantly enhances the javadoc documentation to make the targetPath handling semantics even more explicit and clear for all audiences: API consumers, plugin developers, and implementers.

Key improvements:

  1. SourceRoot.targetPath():

    • Explicitly states this returns the path AS CONFIGURED (no resolution)
    • Clearly distinguishes between storage (this method) and resolution (targetPath(Project))
    • Provides detailed "Return Value Semantics" section explaining empty/relative/absolute cases
    • Adds "Usage Guidance" section for different audiences:
      • Maven 4 API consumers: use targetPath(Project)
      • Maven 3 compatibility: use this method for legacy plugins
      • Implementers: store path as-is, don't resolve at storage time
    • Emphasizes Maven 3 compatibility with explicit reference to project.build.outputDirectory and project.build.testOutputDirectory
  2. SourceRoot.targetPath(Project):

    • Adds "Purpose" section explaining this is THE resolution method
    • Provides detailed step-by-step resolution algorithm with all cases
    • Includes comprehensive table with concrete examples showing:
      • Configuration input
      • Output directory
      • Final resolved result
      • Explanation of each case
    • Adds "Relationship to targetPath()" section explaining storage vs resolution
    • Includes implementation note with equivalent code for clarity
  3. Project.getOutputDirectory():

    • Adds comprehensive table showing scope-to-directory mapping
    • Includes "Role in SourceRoot Path Resolution" section with concrete examples
    • Expands Maven 3 compatibility section with actual XML configuration example
    • Shows how maven-resources-plugin uses this in Maven 3
    • Provides code examples demonstrating usage
  4. HTML5 Compliance:

    • Replaced deprecated table attributes (cellpadding, cellspacing, border)
    • Uses modern HTML5 table styling with class="striped"

The refined documentation makes it crystal clear that:

Related to apache#11381

gnodet added a commit to gnodet/maven that referenced this pull request

Nov 7, 2025

@gnodet

…fixes apache#11381) (apache#11394)

This commit fixes the regression where resources with a relative targetPath were being copied to the project root instead of relative to the output directory (target/classes or target/test-classes).

Changes:

  1. DefaultSourceRoot.fromModel: Store targetPath as a relative path instead of resolving it against baseDir and outputDir. This ensures that SourceRoot.targetPath() returns a relative path as intended by the Maven 4 API javadoc.

  2. ConnectedResource.computeRelativeTargetPath: Simplified to directly return the relative targetPath from SourceRoot, since it's now always stored as relative.

  3. Updated tests to expect relative paths from SourceRoot.targetPath().

Maven 4 API Conformance:

Maven 3 Compatibility:

Example: With custom-dir:

Fixes apache#11381

(cherry picked from commit 9b95526)

gnodet added a commit to gnodet/maven that referenced this pull request

Nov 7, 2025

@gnodet

…fixes apache#11381) (apache#11394)

This commit fixes the regression where resources with a relative targetPath were being copied to the project root instead of relative to the output directory (target/classes or target/test-classes).

Changes:

  1. DefaultSourceRoot.fromModel: Store targetPath as a relative path instead of resolving it against baseDir and outputDir. This ensures that SourceRoot.targetPath() returns a relative path as intended by the Maven 4 API javadoc.

  2. ConnectedResource.computeRelativeTargetPath: Simplified to directly return the relative targetPath from SourceRoot, since it's now always stored as relative.

  3. Updated tests to expect relative paths from SourceRoot.targetPath().

Maven 4 API Conformance:

Maven 3 Compatibility:

Example: With custom-dir:

Fixes apache#11381

(cherry picked from commit 9b95526)

@gnodet gnodet deleted the fix-gh-11381-resource-targetpath branch

November 7, 2025 13:12

gnodet added a commit that referenced this pull request

Nov 7, 2025

@gnodet

…fixes #11381) (#11394) (#11406)

This commit fixes the regression where resources with a relative targetPath were being copied to the project root instead of relative to the output directory (target/classes or target/test-classes).

Changes:

  1. DefaultSourceRoot.fromModel: Store targetPath as a relative path instead of resolving it against baseDir and outputDir. This ensures that SourceRoot.targetPath() returns a relative path as intended by the Maven 4 API javadoc.

  2. ConnectedResource.computeRelativeTargetPath: Simplified to directly return the relative targetPath from SourceRoot, since it's now always stored as relative.

  3. Updated tests to expect relative paths from SourceRoot.targetPath().

Maven 4 API Conformance:

Maven 3 Compatibility:

Example: With custom-dir:

Fixes #11381

(cherry picked from commit 9b95526)

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})