From 2eb234409170a72cc72c05b97b35785df6721ceb Mon Sep 17 00:00:00 2001 From: JoeWang-Java Date: Thu, 11 Jan 2024 18:23:55 +0000 Subject: [PATCH 1/2] 8323571: Regression in source resolution process --- .../internal/impl/XMLEntityManager.java | 38 ++-- .../unittest/common/catalog/NullIdTest.java | 201 ++++++++++++++++++ .../xml/jaxp/unittest/common/catalog/core.xsd | 97 +++++++++ .../jaxp/unittest/common/catalog/events.xsd | 35 +++ 4 files changed, 355 insertions(+), 16 deletions(-) create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index 6e5663bfa2c68..4b876994dd7c8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -1038,8 +1038,9 @@ public StaxXMLInputSource resolveEntityAsPerStax(XMLResourceIdentifier resourceI } // Step 2: custom catalog if specified - if ((publicId != null || literalSystemId != null) && - staxInputSource == null && (fUseCatalog && fCatalogFile != null)) { + if (staxInputSource == null + && (publicId != null || literalSystemId != null) + && (fUseCatalog && fCatalogFile != null)) { if (fCatalogResolver == null) { fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve); fCatalogResolver = CatalogManager.catalogResolver(fCatalogFeatures); @@ -1049,8 +1050,9 @@ public StaxXMLInputSource resolveEntityAsPerStax(XMLResourceIdentifier resourceI } // Step 3: use the default JDK Catalog Resolver if Step 2's resolve is continue - if ((publicId != null || literalSystemId != null) && - staxInputSource == null && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) { + if (staxInputSource == null + && (publicId != null || literalSystemId != null) + && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) { initJdkCatalogResolver(); staxInputSource = resolveWithCatalogStAX(fDefCR, JdkCatalog.JDKCATALOG, publicId, literalSystemId); @@ -1061,9 +1063,9 @@ public StaxXMLInputSource resolveEntityAsPerStax(XMLResourceIdentifier resourceI // Note if both publicId and systemId are null, the resolution process continues as usual if (staxInputSource != null) { fISCreatedByResolver = true; - } else if ((publicId == null && literalSystemId == null) || - (JdkXmlUtils.isResolveContinue(fCatalogFeatures) && - fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) { + } else if ((publicId == null && literalSystemId == null) + || (JdkXmlUtils.isResolveContinue(fCatalogFeatures) + && fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) { staxInputSource = new StaxXMLInputSource( new XMLInputSource(publicId, literalSystemId, baseSystemId, true), false); } @@ -1206,8 +1208,9 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th } // Step 2: custom catalog if specified - if ((publicId != null || literalSystemId != null || resourceIdentifier.getNamespace() !=null) - && xmlInputSource == null && (fUseCatalog && fCatalogFile != null)) { + if (xmlInputSource == null + && (publicId != null || literalSystemId != null || resourceIdentifier.getNamespace() !=null) + && (fUseCatalog && fCatalogFile != null)) { if (fCatalogResolver == null) { fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve); fCatalogResolver = CatalogManager.catalogResolver(fCatalogFeatures); @@ -1217,8 +1220,9 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th } // Step 3: use the default JDK Catalog Resolver if Step 2's resolve is continue - if ((publicId != null || literalSystemId != null) - && xmlInputSource == null && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) { + if (xmlInputSource == null + && (publicId != null || literalSystemId != null) + && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) { initJdkCatalogResolver(); // unlike a custom catalog, the JDK Catalog only contains entity references xmlInputSource = resolveEntity(fDefCR, publicId, literalSystemId, baseSystemId); @@ -1226,11 +1230,13 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th // Step 4: default resolution if not resolved by a resolver and the RESOLVE // feature is set to 'continue' - // Note if both publicId and systemId are null, the resolution process continues as usual - if ((publicId == null && literalSystemId == null) || - ((xmlInputSource == null) && JdkXmlUtils.isResolveContinue(fCatalogFeatures) && - fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) { - xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId, false); + if (xmlInputSource == null) { + // Note if both publicId and systemId are null, the resolution process continues as usual + if ((publicId == null && literalSystemId == null) || + (JdkXmlUtils.isResolveContinue(fCatalogFeatures) && + fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) { + xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId, false); + } } return xmlInputSource; diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java new file mode 100644 index 0000000000000..442f13f49273d --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package common.catalog; + +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.SAXException; + +import javax.xml.catalog.CatalogFeatures; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.SchemaFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Objects.requireNonNull; +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; +import static javax.xml.catalog.CatalogManager.catalogResolver; +import javax.xml.catalog.CatalogResolver; +import javax.xml.validation.Validator; +import org.testng.annotations.Test; + +/* + * @test + * @bug 8323571 + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest + * @run testng common.catalog.NullIdTest + * @summary Verifies null values are handled properly in the source resolution + * process. + */ +public class NullIdTest { + private static final Map SCHEMAS; + // Source Level JDK 8 + static { + Map map = new HashMap<>(); + map.put("https://schemas.opentest4j.org/reporting/events/0.1.0", "events.xsd"); + map.put("https://schemas.opentest4j.org/reporting/core/0.1.0", "core.xsd"); + SCHEMAS = Collections.unmodifiableMap(map); + } + + /* + * Verifies that the source resolution process recognizes the custom InputSource + * correctly even though the public and system IDs are null. + */ + @Test + public void test() throws Exception { + String xml = ""; + validate(new StreamSource(new StringReader(xml))); + System.out.println("Successfully validated"); + } + + private static void validate(Source source) throws SAXException, IOException { + SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI); + Validator validator = schemaFactory.newSchema().newValidator(); + validator.setResourceResolver(createResourceResolver()); + validator.validate(source); + } + + private static LSResourceResolver createResourceResolver() { + return (type, namespaceURI, publicId, systemId, baseURI) -> { + if (namespaceURI != null) { + if (SCHEMAS.containsKey(namespaceURI)) { + CustomLSInputImpl input = new CustomLSInputImpl(); + input.setPublicId(publicId); + String schema = SCHEMAS.get(namespaceURI); + input.setSystemId(requireNonNull(NullIdTest.class.getResource(schema)).toExternalForm()); + input.setBaseURI(baseURI); + InputStream stream = NullIdTest.class.getResourceAsStream(schema); + input.setCharacterStream(new InputStreamReader(requireNonNull(stream))); + return input; + } + } + if (systemId != null) { + CatalogFeatures features = CatalogFeatures.builder() + .with(CatalogFeatures.Feature.RESOLVE, "continue") + .build(); + CatalogResolver catalogResolver = catalogResolver(features); + return catalogResolver.resolveResource(type, namespaceURI, publicId, systemId, baseURI); + } + return null; + }; + } + + static class CustomLSInputImpl implements LSInput { + + private Reader characterStream; + private InputStream byteStream; + private String stringData; + private String systemId; + private String publicId; + private String baseURI; + private String encoding; + private boolean certifiedText; + + @Override + public Reader getCharacterStream() { + return characterStream; + } + + @Override + public void setCharacterStream(Reader characterStream) { + this.characterStream = characterStream; + } + + @Override + public InputStream getByteStream() { + return byteStream; + } + + @Override + public void setByteStream(InputStream byteStream) { + this.byteStream = byteStream; + } + + @Override + public String getStringData() { + return stringData; + } + + @Override + public void setStringData(String stringData) { + this.stringData = stringData; + } + + @Override + public String getSystemId() { + return systemId; + } + + @Override + public void setSystemId(String systemId) { + this.systemId = systemId; + } + + @Override + public String getPublicId() { + return publicId; + } + + @Override + public void setPublicId(String publicId) { + this.publicId = publicId; + } + + @Override + public String getBaseURI() { + return baseURI; + } + + @Override + public void setBaseURI(String baseURI) { + this.baseURI = baseURI; + } + + @Override + public String getEncoding() { + return encoding; + } + + @Override + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + @Override + public boolean getCertifiedText() { + return certifiedText; + } + + @Override + public void setCertifiedText(boolean certifiedText) { + this.certifiedText = certifiedText; + } + } +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd new file mode 100644 index 0000000000000..41b0de3425be5 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd new file mode 100644 index 0000000000000..56d5a43121193 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 010c5db833d397e6ca4baee1945629ffd8c03634 Mon Sep 17 00:00:00 2001 From: JoeWang-Java Date: Thu, 11 Jan 2024 20:57:17 +0000 Subject: [PATCH 2/2] Fix copyright year --- .../sun/org/apache/xerces/internal/impl/XMLEntityManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index 4b876994dd7c8..f922849d5fab2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -94,7 +94,7 @@ * @author K.Venugopal SUN Microsystems * @author Neeraj Bajaj SUN Microsystems * @author Sunitha Reddy SUN Microsystems - * @LastModified: Nov 2023 + * @LastModified: Jan 2024 */ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {