This is an automated email from the ASF dual-hosted git repository.
slachiewicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-javadoc-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new 1ec5f318 Close resource jars after copying from them
1ec5f318 is described below
commit 1ec5f31819ca050993aa573128b420d834faf31f
Author: Sylwester Lachiewicz <[email protected]>
AuthorDate: Wed Oct 28 22:02:30 2026 +0000
Close resource jars after copying from them
copyResource never closed the stream it copied, and read it through the
JVM-wide jar: cache, so a resourcesArtifacts jar stayed open for the
rest of the build (JDK-8239054): locked on Windows and read stale under
mvnd once rebuilt.
---
.../apache/maven/plugins/javadoc/JavadocUtil.java | 9 +++++-
.../maven/plugins/javadoc/JavadocUtilTest.java | 35 ++++++++++++++++++++++
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/maven/plugins/javadoc/JavadocUtil.java
b/src/main/java/org/apache/maven/plugins/javadoc/JavadocUtil.java
index 86b7670a..eca0ac4a 100644
--- a/src/main/java/org/apache/maven/plugins/javadoc/JavadocUtil.java
+++ b/src/main/java/org/apache/maven/plugins/javadoc/JavadocUtil.java
@@ -24,6 +24,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
@@ -34,6 +35,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.StandardCharsets;
@@ -724,7 +726,12 @@ public class JavadocUtil {
throw new NullPointerException("The url could not be null.");
}
- Files.copy(url.openStream(), file.toPath(),
StandardCopyOption.REPLACE_EXISTING);
+ URLConnection connection = url.openConnection();
+ // Uncached, so that closing the stream closes the jar (JDK-8239054)
+ connection.setUseCaches(false);
+ try (InputStream in = connection.getInputStream()) {
+ Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
}
/**
diff --git
a/src/test/java/org/apache/maven/plugins/javadoc/JavadocUtilTest.java
b/src/test/java/org/apache/maven/plugins/javadoc/JavadocUtilTest.java
index 5f118b83..337788ef 100644
--- a/src/test/java/org/apache/maven/plugins/javadoc/JavadocUtilTest.java
+++ b/src/test/java/org/apache/maven/plugins/javadoc/JavadocUtilTest.java
@@ -30,6 +30,8 @@ import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -41,6 +43,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
import org.apache.maven.plugins.javadoc.ProxyServer.AuthAsyncProxyServlet;
@@ -57,6 +61,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
+import org.junit.jupiter.api.io.TempDir;
import static org.apache.maven.api.plugin.testing.MojoExtension.getBasedir;
import static org.assertj.core.api.Assertions.assertThat;
@@ -74,6 +79,36 @@ import static org.junit.jupiter.api.Assumptions.abort;
@ExtendWith(JavadocUtilTest.AbortWhenRemoteUnreachable.class)
class JavadocUtilTest {
+ @Test
+ void copyResourceReadsRewrittenJar(@TempDir Path tempDir) throws Exception
{
+ Path jar = tempDir.resolve("resources.jar");
+ File target = tempDir.resolve("stylesheet.css").toFile();
+ URL url = new URL("jar:" + jar.toUri() + "!/stylesheet.css");
+
+ writeJar(jar, "first");
+ JavadocUtil.copyResource(url, target);
+ assertEquals("first", new String(Files.readAllBytes(target.toPath()),
StandardCharsets.UTF_8));
+
+ // Rewritten in place, as a resources module rebuilt in the reactor is.
+ writeJar(jar, "second, and longer than the first");
+ JavadocUtil.copyResource(url, target);
+ assertEquals(
+ "second, and longer than the first",
+ new String(Files.readAllBytes(target.toPath()),
StandardCharsets.UTF_8));
+
+ // Nothing keeps the jar open, so it can be deleted (fails on Windows
while it is open).
+ Files.delete(jar);
+ }
+
+ private static void writeJar(Path jar, String content) throws IOException {
+ try (OutputStream out = Files.newOutputStream(jar);
+ JarOutputStream jarOut = new JarOutputStream(out)) {
+ jarOut.putNextEntry(new ZipEntry("stylesheet.css"));
+ jarOut.write(content.getBytes(StandardCharsets.UTF_8));
+ jarOut.closeEntry();
+ }
+ }
+
@Test
void testParseJavadocVersionNull() {
try {