This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 3d5b1369bf Follow-up to PR #992.
3d5b1369bf is described below
commit 3d5b1369bf36f87a1723e91111b0a23c88afc0b1
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Apr 30 15:08:54 2026 +0100
Follow-up to PR #992.
Reduce code duplication. Extend patch to TagFileProcessor.
Partially inspired by a CoPilot review.
---
java/org/apache/jasper/compiler/Compiler.java | 23 ++++++++-----------
.../apache/jasper/compiler/TagFileProcessor.java | 25 ++++++++++++++++-----
.../apache/jasper/compiler/TagLibraryInfoImpl.java | 19 +---------------
java/org/apache/tomcat/Jar.java | 26 ++++++++++++++++++++++
webapps/docs/changelog.xml | 6 +++++
5 files changed, 61 insertions(+), 38 deletions(-)
diff --git a/java/org/apache/jasper/compiler/Compiler.java
b/java/org/apache/jasper/compiler/Compiler.java
index e43c13414c..4ec5ca071a 100644
--- a/java/org/apache/jasper/compiler/Compiler.java
+++ b/java/org/apache/jasper/compiler/Compiler.java
@@ -490,21 +490,16 @@ public abstract class Compiler {
if (tldPath == null) {
return true;
}
- if (bangSlash < 0) {
- // JAR-level key: check the JAR file's last-modified
- URLConnection urlConn =
tldPath.getUrl().openConnection();
- try {
- includeLastModified = urlConn.getLastModified();
- } finally {
- urlConn.getInputStream().close();
+ try (Jar jar = tldPath.openJar()) {
+ if (jar == null) {
+ return true;
}
- } else {
- // TLD-entry key: check the entry's last-modified
within the JAR
- String entryName = key.substring(bangSlash + 2);
- try (Jar jar = tldPath.openJar()) {
- if (jar == null) {
- return true;
- }
+ if (bangSlash < 0) {
+ // JAR-level key: check the JAR file's
last-modified
+ includeLastModified = jar.getLastModified();
+ } else {
+ // TLD-entry key: check the entry's last-modified
within the JAR
+ String entryName = key.substring(bangSlash + 2);
includeLastModified =
jar.getLastModified(entryName);
}
}
diff --git a/java/org/apache/jasper/compiler/TagFileProcessor.java
b/java/org/apache/jasper/compiler/TagFileProcessor.java
index 911a31d3ab..80207e0467 100644
--- a/java/org/apache/jasper/compiler/TagFileProcessor.java
+++ b/java/org/apache/jasper/compiler/TagFileProcessor.java
@@ -574,18 +574,31 @@ public class TagFileProcessor {
String tagFilePath = tagFileInfo.getPath();
if (tagFilePath.startsWith("/META-INF/")) {
// For tags in JARs, add the TLD and the tag as a
dependency
- TldResourcePath tldResourcePath =
compiler.getCompilationContext()
-
.getTldResourcePath(tagFileInfo.getTagInfo().getTagLibrary().getURI());
-
+ String tagLibraryUri =
tagFileInfo.getTagInfo().getTagLibrary().getURI();
+ TldResourcePath tldResourcePath =
+
compiler.getCompilationContext().getTldResourcePath(tagLibraryUri);
+ String tldWebAppPath = tldResourcePath.getWebappPath();
try (Jar jar = tldResourcePath.openJar()) {
if (jar != null) {
+ /*
+ * If the JAR is not in the web application path,
use the stable Tag Library URI as the
+ * dependency key to keep the generated code
deterministic across build environments.
+ */
+ String tldKey;
+ String tagKey;
+ if (tldWebAppPath == null) {
+ tldKey = "uri:" + tagLibraryUri + "!/" +
tldResourcePath.getEntryName();
+ tagKey = "uri:" + tagLibraryUri + "!/" +
tagFilePath.substring(1);
+ } else {
+ tldKey =
jar.getURL(tldResourcePath.getEntryName());
+ tagKey = jar.getURL(tagFilePath.substring(1));
+ }
// Add TLD
-
pageInfo.addDependant(jar.getURL(tldResourcePath.getEntryName()),
+ pageInfo.addDependant(tldKey,
Long.valueOf(jar.getLastModified(tldResourcePath.getEntryName())));
// Add Tag
-
pageInfo.addDependant(jar.getURL(tagFilePath.substring(1)),
-
Long.valueOf(jar.getLastModified(tagFilePath.substring(1))));
+ pageInfo.addDependant(tagKey,
Long.valueOf(jar.getLastModified(tagFilePath.substring(1))));
} else {
pageInfo.addDependant(tagFilePath,
compiler.getCompilationContext().getLastModified(tagFilePath));
diff --git a/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
b/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
index dab1355464..02aae498a4 100644
--- a/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
+++ b/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java
@@ -23,7 +23,6 @@ import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
-import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -137,23 +136,7 @@ class TagLibraryInfoImpl extends TagLibraryInfo implements
TagConstants {
// stable taglib URI as the dependency key instead of
the
// absolute JAR URL to keep the generated servlet code
// deterministic across build environments.
- URL jarUrl = jar.getJarFileURL();
- long lastMod;
- URLConnection urlConn = null;
- try {
- urlConn = jarUrl.openConnection();
- lastMod = urlConn.getLastModified();
- } catch (IOException ioe) {
- throw new JasperException(ioe);
- } finally {
- if (urlConn != null) {
- try {
- urlConn.getInputStream().close();
- } catch (IOException ignore) {
- // Ignore
- }
- }
- }
+ long lastMod = jar.getLastModified();
pageInfo.addDependant("uri:" + uriIn,
Long.valueOf(lastMod));
}
// Add TLD within the JAR to the dependency list. For
external
diff --git a/java/org/apache/tomcat/Jar.java b/java/org/apache/tomcat/Jar.java
index 6bb7226790..22aaaedc40 100644
--- a/java/org/apache/tomcat/Jar.java
+++ b/java/org/apache/tomcat/Jar.java
@@ -19,6 +19,7 @@ package org.apache.tomcat;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.net.URLConnection;
import java.util.jar.Manifest;
/**
@@ -47,6 +48,31 @@ public interface Jar extends AutoCloseable {
*/
InputStream getInputStream(String name) throws IOException;
+ /**
+ * Obtain the last modified time for the JAR.
+ *
+ * @return The time (in the same format as {@link
System#currentTimeMillis()}) that the resource was last modified.
+ * Returns -1 if the entry does not exist
+ *
+ * @throws IOException if an I/O error occurs while processing the JAR file
+ */
+ default long getLastModified() throws IOException {
+ URL jarUrl = getJarFileURL();
+ URLConnection urlConn = null;
+ try {
+ urlConn = jarUrl.openConnection();
+ return urlConn.getLastModified();
+ } finally {
+ if (urlConn != null) {
+ try {
+ urlConn.getInputStream().close();
+ } catch (IOException ignore) {
+ // Ignore
+ }
+ }
+ }
+ }
+
/**
* Obtain the last modified time for the given resource in the JAR.
*
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 44d53785bf..44c85caa18 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -358,6 +358,12 @@
<bug>69995</bug>: Make dependent ordering predictable. Patch submitted
by Jan Luehe. (remm)
</fix>
+ <fix>
+ <bug>70001</bug>: Ensure JSP compilation is reproducible when
+ dependencies exist for tag files and tag libraries located on the class
+ path but outside of the web application. <pr>992</pr> submitted by Jan
+ Luehe. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Cluster">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]