# HG changeset patch
# User joehw
# Date 1549389455 28800
# Node ID 5d95a8dbb6e4fc5983f9f358717b464ce4ac2575
# Parent 1126811a5124f7408951734d834f6226514fd69e
8206132: DOM parser does not honor DocumentBuilderFactory.setExpandEntityReferences(false)
Reviewed-by: rriggs, lancea
diff -r 1126811a5124 -r 5d95a8dbb6e4 src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Tue Feb 05 09:56:19 2019 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Tue Feb 05 09:57:35 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -73,7 +73,7 @@
* @author Eric Ye, IBM
* @author Sunitha Reddy, SUN Microsystems
*
- * @LastModified: Sep 2017
+ * @LastModified: Jan 2019
*/
public class XMLDocumentFragmentScannerImpl
extends XMLScanner
@@ -163,6 +163,10 @@
protected static final String STANDARD_URI_CONFORMANT =
Constants.XERCES_FEATURE_PREFIX +Constants.STANDARD_URI_CONFORMANT_FEATURE;
+ /** Feature id: create entity ref nodes. */
+ protected static final String CREATE_ENTITY_REF_NODES =
+ Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
+
/** Property identifier: Security property manager. */
private static final String XML_SECURITY_PROPERTY_MANAGER =
Constants.XML_SECURITY_PROPERTY_MANAGER;
@@ -322,6 +326,9 @@
/** Xerces Feature: Disallow doctype declaration. */
protected boolean fDisallowDoctype = false;
+ /** Create entity reference nodes. */
+ protected boolean fCreateEntityRefNodes = false;
+
/**
* CDATA chunk size limit
*/
@@ -596,6 +603,8 @@
fSecurityManager = (XMLSecurityManager)componentManager.getProperty(Constants.SECURITY_MANAGER, null);
fNotifyBuiltInRefs = componentManager.getFeature(NOTIFY_BUILTIN_REFS, false);
+ fCreateEntityRefNodes = componentManager.getFeature(CREATE_ENTITY_REF_NODES, fCreateEntityRefNodes);
+
Object resolver = componentManager.getProperty(ENTITY_RESOLVER, null);
fExternalSubsetResolver = (resolver instanceof ExternalSubsetResolver) ?
(ExternalSubsetResolver) resolver : null;
@@ -1837,14 +1846,20 @@
} else
reportFatalError("EntityNotDeclared", new Object[]{name});
}
- //we are starting the entity even if the entity was not declared
- //if that was the case it its taken care in XMLEntityManager.startEntity()
- //we immediately call the endEntity. Application gets to know if there was
- //any entity that was not declared.
- fEntityManager.startEntity(true, name, false);
- //set the scaner state to content.. parser will automatically revive itself at any point of time.
- //setScannerState(SCANNER_STATE_CONTENT);
- //return true ;
+
+ // create EntityReference only
+ if (fCreateEntityRefNodes) {
+ fDocumentHandler.startGeneralEntity(name, null, null, null);
+ } else {
+ //we are starting the entity even if the entity was not declared
+ //if that was the case it its taken care in XMLEntityManager.startEntity()
+ //we immediately call the endEntity. Application gets to know if there was
+ //any entity that was not declared.
+ fEntityManager.startEntity(true, name, false);
+ //set the scaner state to content.. parser will automatically revive itself at any point of time.
+ //setScannerState(SCANNER_STATE_CONTENT);
+ //return true ;
+ }
} // scanEntityReference()
// utility methods
diff -r 1126811a5124 -r 5d95a8dbb6e4 src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java Tue Feb 05 09:56:19 2019 -0800
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java Tue Feb 05 09:57:35 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -84,7 +84,7 @@
* @author Andy Clark, IBM
* @author Elena Litani, IBM
*
- * @LastModified: Nov 2017
+ * @LastModified: Jan 2019
*/
public class AbstractDOMParser extends AbstractXMLDocumentParser {
@@ -491,8 +491,10 @@
if (DEBUG_EVENTS) {
System.out.println ("==>startGeneralEntity ("+name+")");
if (DEBUG_BASEURI) {
- System.out.println (" expandedSystemId( **baseURI): "+identifier.getExpandedSystemId ());
- System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
+ System.out.println (" expandedSystemId( **baseURI): " +
+ identifier == null ? null : identifier.getExpandedSystemId());
+ System.out.println (" baseURI:" +
+ identifier == null ? null : identifier.getBaseSystemId());
}
}
@@ -512,7 +514,7 @@
EntityReferenceImpl erImpl =(EntityReferenceImpl)er;
// set base uri
- erImpl.setBaseURI (identifier.getExpandedSystemId ());
+ erImpl.setBaseURI (identifier == null ? null : identifier.getExpandedSystemId());
if (fDocumentType != null) {
// set actual encoding
NamedNodeMap entities = fDocumentType.getEntities ();
@@ -528,12 +530,17 @@
}
fInEntityRef = true;
fCurrentNode.appendChild (er);
- fCurrentNode = er;
+
+ if (!fCreateEntityRefNodes) {
+ fCurrentNode = er;
+ } else {
+ ((NodeImpl)er).setReadOnly (true, true);
+ }
}
else {
- int er =
- fDeferredDocumentImpl.createDeferredEntityReference (name, identifier.getExpandedSystemId ());
+ int er = fDeferredDocumentImpl.createDeferredEntityReference (name,
+ identifier == null ? null : identifier.getExpandedSystemId ());
if (fDocumentTypeIndex != -1) {
// find corresponding Entity decl
int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
@@ -552,7 +559,10 @@
}
}
fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, er);
- fCurrentNodeIndex = er;
+
+ if (!fCreateEntityRefNodes) {
+ fCurrentNodeIndex = er;
+ }
}
} // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
diff -r 1126811a5124 -r 5d95a8dbb6e4 test/jaxp/javax/xml/jaxp/unittest/dom/DOMFeatureTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/dom/DOMFeatureTest.java Tue Feb 05 09:57:35 2019 -0800
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2019, 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 dom;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+/*
+ * @test
+ * @bug 8206132
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng dom.DOMFeatureTest
+ * @summary Tests DOM features.
+ */
+@Listeners({jaxp.library.BasePolicy.class})
+public class DOMFeatureTest {
+
+ private static final String XML1 = "\n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + "]>\n"
+ + "\n"
+ + " &author;\n"
+ + "";
+
+ private static final String XML2 = "\n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "]>\n"
+ + "\n"
+ + " &author; HamletChapter 1\n"
+ + "";
+
+ private static final String XML3 = "\n"
+ + ""
+ + " \n"
+ + " \n"
+ + " \n"
+ + "]>\n"
+ + "\n"
+ + " &author; HamletChapter 1\n"
+ + "";
+
+ /*
+ * DataProvider: for testing the EntityExpansion feature
+ * Data columns: case number, feature setting (true/false), xml file,
+ * number of nodes expected, text content expected, element if any
+ */
+ @DataProvider(name = "EntityExpansion")
+ Object[][] getData() throws Exception {
+ return new Object[][]{
+ {1, true, XML1, 1, "William Shakespeare", null},
+ {2, true, XML2, 2, "William Shakespeare Hamlet", "chapter"},
+ {3, false, XML1, 1, null, null},
+ {4, false, XML2, 3, " Hamlet", "chapter"},
+ {4, false, XML3, 3, " Hamlet", "chapter"},
+ };
+ }
+
+ /*
+ * DataProvider: for testing the EntityExpansion feature
+ * Data columns: feature setting (true/false), xml file
+ */
+ @DataProvider(name = "EntityExpansion1")
+ Object[][] getData1() throws Exception {
+ return new Object[][]{
+ {true, XML3},
+ };
+ }
+ /**
+ * Verifies the EntityExpansion feature.
+ * @param caseNo the case number
+ * @param feature flag indicating the setting of the feature
+ * @param xml the XML string
+ * @param n the number of nodes expected
+ * @param expectedText expected Text string
+ * @param expectedElement expected Element
+ * @throws Exception
+ */
+ @Test(dataProvider = "EntityExpansion")
+ public void testEntityExpansion(int caseNo, boolean feature, String xml,
+ int n, String expectedText, String expectedElement) throws Exception {
+ final Document doc = getDocument(feature, xml);
+ final Element e = (Element) doc.getElementsByTagName("title").item(0);
+ final NodeList nl = e.getChildNodes();
+
+ switch (caseNo) {
+ case 1:
+ // The DOM tree should contain just the Text node
+ Assert.assertTrue(nl.item(0) instanceof Text);
+ Assert.assertEquals(nl.item(0).getNodeValue(), expectedText);
+ Assert.assertEquals(nl.getLength(), n);
+ break;
+ case 2:
+ // The DOM tree contains the Text node and an Element (chapter)
+ Assert.assertTrue(nl.item(0) instanceof Text);
+ Assert.assertEquals(nl.item(0).getNodeValue(), expectedText);
+ Assert.assertTrue(nl.item(1) instanceof Element);
+ Assert.assertEquals(nl.item(1).getNodeName(), expectedElement);
+ Assert.assertEquals(nl.getLength(), n);
+ break;
+ case 3:
+ // The DOM tree contains just the EntityReference node
+ Assert.assertTrue(nl.item(0) instanceof EntityReference);
+ Assert.assertEquals(nl.item(0).getNodeValue(), null);
+ Assert.assertEquals(nl.getLength(), n);
+ break;
+ case 4:
+ // The DOM tree contains a EntityReference, Text and an Element
+ Assert.assertTrue(nl.item(0) instanceof EntityReference);
+ Assert.assertEquals(nl.item(0).getNodeValue(), null);
+ Assert.assertTrue(nl.item(1) instanceof Text);
+ Assert.assertEquals(nl.item(1).getNodeValue(), expectedText);
+ Assert.assertTrue(nl.item(2) instanceof Element);
+ Assert.assertEquals(nl.item(2).getNodeName(), expectedElement);
+ Assert.assertEquals(nl.getLength(), n);
+ break;
+ }
+ }
+
+ /**
+ * Verifies the EntityExpansion feature. When the feature is set to true, the
+ * parser will attempt to resolve the external reference, that in turn will
+ * result in an Exception.
+ * @param feature flag indicating the setting of the feature
+ * @param xml the XML string
+ * @throws Exception: when a non-existent external reference is encountered
+ */
+ @Test(dataProvider = "EntityExpansion1", expectedExceptions = java.net.UnknownHostException.class)
+ public void testEntityExpansion1(boolean feature, String xml)
+ throws Exception {
+ final Document doc = getDocument(feature, xml);
+ final Element e = (Element) doc.getElementsByTagName("title").item(0);
+ final NodeList nl = e.getChildNodes();
+ }
+
+ private static Document getDocument(boolean expand, String xml)
+ throws SAXException, IOException, ParserConfigurationException {
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setExpandEntityReferences(expand);
+
+ final DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+
+ InputStream a = new ByteArrayInputStream(xml.getBytes());
+ Document out = docBuilder.parse(a);
+ return out;
+ }
+}
diff -r 1126811a5124 -r 5d95a8dbb6e4 test/jaxp/javax/xml/jaxp/unittest/dom/ElementTraversal.java
--- a/test/jaxp/javax/xml/jaxp/unittest/dom/ElementTraversal.java Tue Feb 05 09:56:19 2019 -0800
+++ b/test/jaxp/javax/xml/jaxp/unittest/dom/ElementTraversal.java Tue Feb 05 09:57:35 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -125,7 +125,6 @@
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(xmlFile);
} catch (ParserConfigurationException | SAXException | IOException e) {
diff -r 1126811a5124 -r 5d95a8dbb6e4 test/jaxp/javax/xml/jaxp/unittest/dom/ls/LSSerializerTest.java
--- a/test/jaxp/javax/xml/jaxp/unittest/dom/ls/LSSerializerTest.java Tue Feb 05 09:56:19 2019 -0800
+++ b/test/jaxp/javax/xml/jaxp/unittest/dom/ls/LSSerializerTest.java Tue Feb 05 09:57:35 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -35,6 +35,7 @@
import javax.xml.parsers.ParserConfigurationException;
import org.testng.Assert;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import org.w3c.dom.DOMError;
@@ -52,7 +53,7 @@
/*
* @test
- * @bug 8080906 8114834
+ * @bug 8080906 8114834 8206132
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true dom.ls.LSSerializerTest
* @run testng/othervm dom.ls.LSSerializerTest
@@ -225,31 +226,111 @@
Assert.assertEquals(XML11_DOCUMENT_OUTPUT, defaultSerialization, "Invalid serialization of XML 1.1 document: ");
}
+ // XML source
+ private static final String XML =
+ "\n" +
+ "" +
+ " " +
+ " " +
+ "text\">" +
+ " " +
+ " " +
+ " ]>" +
+ " &name1;" +
+ "b &name2; &name1; b" +
+ " &name; " +
+ "&ele1;d" +
+ " &ele2;eee " +
+ "<att>" +
+ " &ele; g" +
+ "&ele2;" ;
+
+ // result when "entities" = true, equvalent to setting ExpandEntityReference to false
+ private static final String RESULT_TRUE =
+ "\n" +
+ "\n" +
+ "\n" +
+ "text'>\n" +
+ "\n" +
+ "\n" +
+ "]>\n" +
+ "\n" +
+ " &name1;\n" +
+ " b &name2;&name1; b\n" +
+ " &name;\n" +
+ " &ele1;d\n" +
+ " &ele2;eee \n" +
+ " <att>\n" +
+ " &ele; g\n" +
+ " &ele2;\n" +
+ "\n";
+
+ // result when "entities" = false, equvalent to setting ExpandEntityReference to true
+ private static final String RESULT_FALSE =
+ "\n" +
+ "\n" +
+ "\n" +
+ "text'>\n" +
+ "\n" +
+ "\n" +
+ "]>\n" +
+ "\n" +
+ " Jo Smith\n" +
+ " b Jo Smith Jo Smith b\n" +
+ " Jo Smith \n" +
+ " \n" +
+ " \n" +
+ " text\n" +
+ " \n" +
+ " d\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " text\n" +
+ " \n" +
+ " eee \n" +
+ " \n" +
+ " <att>\n" +
+ " \n" +
+ " \n" +
+ " text\n" +
+ " \n" +
+ " g\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " text\n" +
+ " \n" +
+ " \n" +
+ "\n";
+
/*
- * @bug 8114834 test entity reference, nested entity reference when entities
- * is true and false
+ * DataProvider: for testing the entities parameter
+ * Data columns: xml source, entities setting, expected result
*/
- @Test
- public void testEntityReference() throws Exception {
- final String XML_DOCUMENT = "\n" +
- "" +
- " " +
- " " +
- "text\">" +
- " " +
- " " +
- " ]>" +
- " &name1;" +
- "b &name2; &name1; b" +
- " &name; " +
- "&ele1;d" +
- " &ele2;eee " +
- "<att>" +
- " &ele; g" +
- "&ele2;" ;
+ @DataProvider(name = "entities")
+ Object[][] getData() throws Exception {
+ return new Object[][]{
+ {XML, Boolean.TRUE, RESULT_TRUE},
+ {XML, Boolean.FALSE, RESULT_FALSE},
+ };
+ }
-
+ /**
+ * Tests serializing DOM Document with DOMConfiguration's "entities" parameter.
+ *
+ * @param source the XML source
+ * @param entities the entities parameter setting
+ * @param expected expected string result
+ * @throws Exception
+ * @bug 8114834 8206132
+ */
+ @Test(dataProvider = "entities")
+ public void testEntityReference(String source, Boolean entities, String expected)
+ throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
@@ -257,76 +338,18 @@
DOMImplementationLS domImplementationLS = (DOMImplementationLS) domImplementation;
LSParser domParser = domImplementationLS.createLSParser(MODE_SYNCHRONOUS, null);
- domParser.getDomConfig().setParameter("entities", Boolean.TRUE);
+ domParser.getDomConfig().setParameter("entities", entities);
LSInput src = domImplementationLS.createLSInput();
- src.setStringData(XML_DOCUMENT);
+ src.setStringData(source);
Document document = domParser.parse(src);
LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
-
lsSerializer.getDomConfig().setParameter("format-pretty-print", true);
- System.out.println("test with default entities is " + lsSerializer.getDomConfig().getParameter("entities"));
- Assert.assertEquals(lsSerializer.writeToString(document),
- "\n" +
- "\n" +
- "\n" +
- "text'>\n" +
- "\n" +
- "\n" +
- "]>\n" +
- "\n" +
- " &name1;Jo Smith\n" +
- " b &name2;Jo Smith &name1;Jo Smith b\n" +
- " &name;Jo Smith \n" +
- " &ele1;d\n" +
- " &ele2;eee \n" +
- " <att>\n" +
- " &ele; g\n" +
- " &ele2;\n" +
- "\n");
+ System.out.println("test with default entities is " +
+ lsSerializer.getDomConfig().getParameter("entities"));
- lsSerializer.getDomConfig().setParameter("entities", Boolean.FALSE);
- System.out.println("test with entities is false");
- Assert.assertEquals(lsSerializer.writeToString(document),
- "\n" +
- "\n" +
- "\n" +
- "text'>\n" +
- "\n" +
- "\n" +
- "]>\n" +
- "\n" +
- " &name;Jo Smith\n" +
- " b &name;Jo Smith &name;Jo Smith b\n" +
- " &name;Jo Smith \n" +
- " \n" +
- " \n" +
- " text\n" +
- " \n" +
- " d\n" +
- " \n" +
- " \n" +
- " \n" +
- " text\n" +
- " \n" +
- " eee \n" +
- " \n" +
- " <att>\n" +
- " \n" +
- " \n" +
- " text\n" +
- " \n" +
- " g\n" +
- " \n" +
- " \n" +
- " \n" +
- " text\n" +
- " \n" +
- " \n" +
- "\n");
-
+ String result = lsSerializer.writeToString(document);
+ Assert.assertEquals(result, expected);
}
}