This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push:
new 2b80587f9d Review "Avoid registering TLD listeners twice for a
duplicate taglib..."
2b80587f9d is described below
commit 2b80587f9dbe1de5ff1248a2e32dcdfacd8a3a54
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Nov 6 10:03:50 2026 +0000
Review "Avoid registering TLD listeners twice for a duplicate taglib..."
Refactor de-duplication to the same listener isn't added twice but
duplicate tablib URIs that define different listeners register all
listeners.
---
java/org/apache/jasper/servlet/TldScanner.java | 33 +++++-----
test/org/apache/jasper/servlet/TestTldScanner.java | 70 ++++++++++++++++++++++
2 files changed, 89 insertions(+), 14 deletions(-)
diff --git a/java/org/apache/jasper/servlet/TldScanner.java
b/java/org/apache/jasper/servlet/TldScanner.java
index da2fb0ac0d..718786c167 100644
--- a/java/org/apache/jasper/servlet/TldScanner.java
+++ b/java/org/apache/jasper/servlet/TldScanner.java
@@ -194,9 +194,7 @@ public class TldScanner {
TaglibXml tld = tldParser.parse(tldResourcePath);
uriTldResourcePathMap.put(taglibURI, tldResourcePath);
tldResourcePathTaglibXmlMap.put(tldResourcePath, tld);
- if (tld.getListeners() != null) {
- listeners.addAll(tld.getListeners());
- }
+ addListeners(tld);
} else {
log.warn(Localizer.getMessage(MSG +
".webxmlFailPathDoesNotExist", resourcePath, taglibURI));
}
@@ -309,14 +307,8 @@ public class TldScanner {
tld = tldParser.parse(path);
}
String uri = tld.getUri();
- // JSP.7.3.6.1: the first mapping for a taglib URI wins. A TLD with a
- // previously seen URI found via a different resource path (for
- // example, an unpacked JAR in WEB-INF/classes/META-INF or the same
- // TLD shipped in two JARs) is a duplicate.
- boolean duplicateUri = false;
if (uri != null) {
- duplicateUri = uriTldResourcePathMap.containsKey(uri);
- if (!duplicateUri) {
+ if (!uriTldResourcePathMap.containsKey(uri)) {
uriTldResourcePathMap.put(uri, path);
}
}
@@ -327,10 +319,23 @@ public class TldScanner {
}
tldResourcePathTaglibXmlMap.put(path, tld);
- if (tld.getListeners() != null && !duplicateUri) {
- // The listeners of a duplicate tag library have already been
- // registered when the tag library was first discovered.
- listeners.addAll(tld.getListeners());
+ addListeners(tld);
+ }
+
+ /*
+ * Registers the listeners declared by the TLD, ignoring any listener
class that has already been registered. The
+ * same TLD may be found via more than one resource path and under more
than one URI (for example, a taglib-uri in
+ * web.xml that differs from the URI declared in the TLD itself) and a
listener class must only be instantiated
+ * once.
+ */
+ private void addListeners(TaglibXml tld) {
+ if (tld.getListeners() == null) {
+ return;
+ }
+ for (String listener : tld.getListeners()) {
+ if (!listeners.contains(listener)) {
+ listeners.add(listener);
+ }
}
}
diff --git a/test/org/apache/jasper/servlet/TestTldScanner.java
b/test/org/apache/jasper/servlet/TestTldScanner.java
index 152a94b37d..950a1ebdf1 100644
--- a/test/org/apache/jasper/servlet/TestTldScanner.java
+++ b/test/org/apache/jasper/servlet/TestTldScanner.java
@@ -29,6 +29,8 @@ import java.util.Map;
import java.util.logging.Level;
import jakarta.servlet.ServletContext;
+import jakarta.servlet.descriptor.JspConfigDescriptor;
+import jakarta.servlet.descriptor.TaglibDescriptor;
import org.junit.Assert;
import org.junit.Test;
@@ -180,6 +182,74 @@ public class TestTldScanner extends TomcatBaseTest {
}
+ @Test
+ public void testListenersNotDuplicatedForDifferentTaglibUris() throws
Exception {
+ // Two TLDs with different URIs that declare the same listener class
+ // must not cause that class to be registered, and therefore
+ // instantiated, twice.
+ ServletContext mockContext = EasyMock.createMock(ServletContext.class);
+ EasyMock.replay(mockContext);
+
+ TldScanner scanner = new TldScanner(mockContext, true, true, true);
+
+ File appDir = new File(getTemporaryDirectory(),
"different-uri-listeners");
+ TldResourcePath first = createTld(appDir, "one",
+ "<uri>http://tomcat.apache.org/first</uri>\n" +
+ " <listener>\n" +
+ "
<listener-class>com.example.SharedListener</listener-class>\n" +
+ " </listener>");
+ TldResourcePath second = createTld(appDir, "two",
+ "<uri>http://tomcat.apache.org/second</uri>\n" +
+ " <listener>\n" +
+ "
<listener-class>com.example.SharedListener</listener-class>\n" +
+ " </listener>");
+
+ scanner.parseTld(first);
+ scanner.parseTld(second);
+
+ EasyMock.verify(mockContext);
+ Assert.assertEquals(2, scanner.getUriTldResourcePathMap().size());
+ Assert.assertEquals(1, scanner.getListeners().size());
+ Assert.assertEquals("com.example.SharedListener",
scanner.getListeners().get(0));
+ }
+
+
+ @Test
+ public void testListenersNotDuplicatedForWebXmlTaglibUriMismatch() throws
Exception {
+ // The taglib-uri in web.xml differs from the URI declared in the TLD
+ // itself. The same TLD found again by the scan has a URI that is not
+ // yet mapped, so the duplicate can only be detected by listener class.
+ File appDir = new File(getTemporaryDirectory(),
"webxml-uri-mismatch-listeners");
+ TldResourcePath declared = createTld(appDir, "one",
+ "<uri>http://tomcat.apache.org/mismatch</uri>\n" +
+ " <listener>\n" +
+ "
<listener-class>com.example.MismatchListener</listener-class>\n" +
+ " </listener>");
+ TldResourcePath found = createTld(appDir, "two",
+ "<uri>http://tomcat.apache.org/mismatch</uri>\n" +
+ " <listener>\n" +
+ "
<listener-class>com.example.MismatchListener</listener-class>\n" +
+ " </listener>");
+
+ TaglibDescriptor taglib = EasyMock.createMock(TaglibDescriptor.class);
+
EasyMock.expect(taglib.getTaglibURI()).andReturn("urn:mismatch").anyTimes();
+
EasyMock.expect(taglib.getTaglibLocation()).andReturn("/one/example.tld").anyTimes();
+ JspConfigDescriptor jspConfig =
EasyMock.createMock(JspConfigDescriptor.class);
+
EasyMock.expect(jspConfig.getTaglibs()).andReturn(Collections.singleton(taglib)).anyTimes();
+ ServletContext mockContext = EasyMock.createMock(ServletContext.class);
+
EasyMock.expect(mockContext.getJspConfigDescriptor()).andReturn(jspConfig).anyTimes();
+
EasyMock.expect(mockContext.getResource("/one/example.tld")).andReturn(declared.getUrl()).anyTimes();
+ EasyMock.replay(taglib, jspConfig, mockContext);
+
+ TldScanner scanner = new TldScanner(mockContext, true, true, true);
+ scanner.scanJspConfig();
+ scanner.parseTld(found);
+
+ Assert.assertEquals(1, scanner.getListeners().size());
+ Assert.assertEquals("com.example.MismatchListener",
scanner.getListeners().get(0));
+ }
+
+
private static TldResourcePath createTld(File appDir, String name,
String extraElements) throws Exception {
File tld = new File(appDir, name + "/example.tld");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]