This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/commons-secure-xml.git


The following commit(s) were added to refs/heads/main by this push:
     new a06bb68  Forward getExternalSubset to a caller EntityResolver2 (#68)
a06bb68 is described below

commit a06bb687673c218053c5075ce6fb3a06948e3770
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Tue Sep 1 13:23:41 2026 +0200

    Forward getExternalSubset to a caller EntityResolver2 (#68)
    
    The entity-resolver floor inherited DefaultHandler2's always-null
    getExternalSubset, so a caller resolver installed through
    setEntityResolver never had its synthetic external subset consulted and
    DOCTYPE-less documents parsed without the declarations the caller
    supplied. Forward the call to an EntityResolver2 delegate; without one
    the "no synthetic subset" default stands. A null return means the parse
    continues without a subset, not that a resource went unresolved, so the
    ignore fallback stays out of this path.
    
    Assisted-By: Claude Fable 5 <[email protected]>
    Claude-Session: https://claude.ai/code/session_01CLnTBsvmYtxzNTWVGNyz33
---
 .../xml/secure/FallbackIgnoreEntityResolver2.java      | 11 ++++++-----
 .../xml/secure/FallbackIgnoreEntityResolver2Test.java  | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2.java
 
b/src/main/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2.java
index aa840a6..5fc2575 100644
--- 
a/src/main/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2.java
+++ 
b/src/main/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2.java
@@ -47,11 +47,6 @@
  * resolver; anything they leave unresolved (a {@code null} return, or no 
caller resolver at all) goes to {@link #onUnresolved}, which returns empty 
content by
  * default.
  * </p>
- * <p>
- * It extends {@link DefaultHandler2} so it is also usable as a {@link 
org.xml.sax.ext.LexicalHandler}; {@link #getExternalSubset} therefore inherits 
the
- * {@code DefaultHandler2} "no synthetic subset" default. Only {@link 
#resolveEntity(String, String, String, String) resolveEntity} (the actual 
external fetch)
- * reaches the ignore fallback.
- * </p>
  */
 class FallbackIgnoreEntityResolver2 extends DefaultHandler2 {
 
@@ -99,6 +94,12 @@ final EntityResolver getDelegate() {
         return delegate;
     }
 
+    @Override
+    public final InputSource getExternalSubset(final String name, final String 
baseURI) throws SAXException, IOException {
+        // A null return means "no synthetic subset", not "unresolved", 
nothing is fetched.
+        return delegate instanceof EntityResolver2 ? ((EntityResolver2) 
delegate).getExternalSubset(name, baseURI) : null;
+    }
+
     /**
      * Outcome when neither the caller delegate nor this resolver provides the 
entity. Resolves to empty content by default, so the external resource is 
neither
      * fetched nor leaked and the parse continues with no replacement text. 
The returned source echoes the requested identifiers (with {@code systemId}
diff --git 
a/src/test/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2Test.java
 
b/src/test/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2Test.java
index 2148ae4..18b71f3 100644
--- 
a/src/test/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2Test.java
+++ 
b/src/test/java/org/apache/commons/xml/secure/FallbackIgnoreEntityResolver2Test.java
@@ -19,6 +19,7 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
@@ -31,6 +32,23 @@
 
 class FallbackIgnoreEntityResolver2Test {
 
+    @Test
+    void forwardsGetExternalSubsetOnlyToExtendedDelegates() throws Exception {
+        final FallbackIgnoreEntityResolver2 floor = new 
FallbackIgnoreEntityResolver2(null);
+        assertNull(floor.getExternalSubset("name", 
"https://example.test/base/";));
+        floor.setDelegate((publicId, systemId) -> new InputSource());
+        assertNull(floor.getExternalSubset("name", 
"https://example.test/base/";));
+        final InputSource expected = new InputSource();
+        floor.setDelegate(new DefaultHandler2() {
+
+            @Override
+            public InputSource getExternalSubset(final String name, final 
String baseURI) {
+                return expected;
+            }
+        });
+        assertSame(expected, floor.getExternalSubset("name", 
"https://example.test/base/";));
+    }
+
     @Test
     void resolvesDelegatesAndAllFallbackPaths() throws Exception {
         final FallbackIgnoreEntityResolver2 floor = new 
FallbackIgnoreEntityResolver2(null);

Reply via email to