gnodet commented on issue #12306:
URL: https://github.com/apache/maven/issues/12306#issuecomment-4738562108

   ## Root Cause Analysis: `<targetPath>.</targetPath>` → empty string → 
absolute path at filesystem root
   
   ### The triggering config in `taglibs-rdc/pom.xml`
   
   ```xml
   <resource>
     <directory>src/main/resources</directory>
     <targetPath>.</targetPath>   <!-- a literal dot -->
   </resource>
   ```
   
   ### The bug chain (Maven 4 only)
   
   1. **`DefaultSourceRoot.java:111`** — constructor normalizes targetPath via 
Java NIO:
      ```java
      this.targetPathOrNull = (targetPathOrNull != null) ? 
targetPathOrNull.normalize() : null;
      ```
      `Path.of(".").normalize()` returns an **empty path** (zero name elements, 
`toString()=""`) because `.` is a redundant element. The result is **not 
null**, so it gets stored as a non-null empty Path.
   
   2. **`ConnectedResource.java:46`** — converts it to an empty string for the 
legacy plugin:
      ```java
      .targetPath(sourceRoot.targetPath().map(Path::toString).orElse(null))
      // → ""   (empty string, NOT null)
      ```
   
   3. **`DefaultMavenResourcesFiltering.getDestinationFile()`** — the plugin 
concatenates:
      ```java
      destination = "" + "/" + 
"org/apache/taglibs/rdc/resources/RDCBundle_en_US.properties"
                  = 
"/org/apache/taglibs/rdc/resources/RDCBundle_en_US.properties"  // absolute!
      ```
      Java's `File("/org/...").isAbsolute() == true`, so `outputDirectory` 
(`/project/target/classes`) is **completely bypassed**. Maven tries to write to 
the filesystem root → `NoSuchFileException`.
   
   ### Why Maven 3 worked
   
   Maven 3 passed the original `"."` string to the plugin without NIO 
normalization. The plugin computed `"." + "/" + filename = "./filename"` 
(relative), which was correctly resolved against the output directory.
   
   ### Fix location
   
   **`DefaultSourceRoot.java:111`** — treat empty normalized paths as null 
(same semantics as no targetPath):
   ```java
   if (targetPathOrNull != null) {
       Path normalized = targetPathOrNull.normalize();
       // "." normalizes to empty path = "copy to output root" = same as null
       this.targetPathOrNull = (normalized.getNameCount() == 0) ? null : 
normalized;
   } else {
       this.targetPathOrNull = null;
   }
   ```
   
   The existing test `testHandlesEmptyTargetPathFromResource` tests explicit 
`""` (handled by `nonBlank()` → null, never reaches the normalization path), 
but **there's no test for `"."` which takes a completely different code path**. 
A test for `targetPath="."` would have caught this.
   
   _Claude Code on behalf of Guillaume Nodet_


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to