--- old/src/java.xml/share/classes/javax/xml/parsers/DocumentBuilderFactory.java 2019-05-20 17:22:17.130767973 -0700 +++ new/src/java.xml/share/classes/javax/xml/parsers/DocumentBuilderFactory.java 2019-05-20 17:22:16.844741290 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -39,7 +39,8 @@ */ public abstract class DocumentBuilderFactory { - + private static final String DEFAULT_IMPL = + "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"; private boolean validating = false; private boolean namespaceAware = false; private boolean whitespace = false; @@ -55,6 +56,76 @@ } /** + * Creates a new NamespaceAware instance of the {@code DocumentBuilderFactory} + * builtin system-default implementation. Parsers produced by the factory + * instance provides support for XML namespaces by default. + * + * @implSpec + * In addition to creating a factory instance using the same process as + * {@link #newDefaultInstance()}, this method must set NamespaceAware to true. + * + * @return a new instance of the {@code DocumentBuilderFactory} builtin + * system-default implementation. + * + * @since 13 + */ + public static DocumentBuilderFactory newDefaultNSInstance() { + return makeNSAware(new DocumentBuilderFactoryImpl()); + } + + /** + * Creates a new NamespaceAware instance of a {@code DocumentBuilderFactory}. + * Parsers produced by the factory instance provides support for XML namespaces + * by default. + * + * @implSpec + * In addition to creating a factory instance using the same process as + * {@link #newInstance()}, this method must set NamespaceAware to true. + * + * @return a new instance of a {@code DocumentBuilderFactory} + * + * @throws FactoryConfigurationError in case of {@linkplain + * java.util.ServiceConfigurationError service configuration error} + * or if the implementation is not available or cannot be instantiated. + * + * @since 13 + */ + public static DocumentBuilderFactory newNSInstance() { + return makeNSAware(FactoryFinder.find(DocumentBuilderFactory.class, DEFAULT_IMPL)); + } + + /** + * Creates a new NamespaceAware instance of a {@code DocumentBuilderFactory} + * from the class name. Parsers produced by the factory instance provides + * support for XML namespaces by default. + * + * @implSpec + * In addition to creating a factory instance using the same process as + * {@link #newInstance(java.lang.String, java.lang.ClassLoader)}, this method + * must set NamespaceAware to true. + * + * @param factoryClassName a fully qualified factory class name that provides + * implementation of + * {@code javax.xml.parsers.DocumentBuilderFactory}. + * + * @param classLoader the {@code ClassLoader} used to load the factory class. + * If it is {@code null}, the current {@code Thread}'s + * context classLoader is used to load the factory class. + * + * @return a new instance of a {@code DocumentBuilderFactory} + * + * @throws FactoryConfigurationError if {@code factoryClassName} is {@code null}, or + * the factory class cannot be loaded, instantiated. + * + * @since 13 + */ + public static DocumentBuilderFactory newNSInstance(String factoryClassName, + ClassLoader classLoader) { + return makeNSAware(FactoryFinder.newInstance( + DocumentBuilderFactory.class, factoryClassName, classLoader, false)); + } + + /** * Creates a new instance of the {@code DocumentBuilderFactory} builtin * system-default implementation. * @@ -141,7 +212,7 @@ /* The default property name according to the JAXP spec */ DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory" /* The fallback implementation class name */ - "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"); + DEFAULT_IMPL); } /** @@ -185,6 +256,11 @@ factoryClassName, classLoader, false); } + private static DocumentBuilderFactory makeNSAware(DocumentBuilderFactory dbf) { + dbf.setNamespaceAware(true); + return dbf; + } + /** * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder} * using the currently configured parameters. --- old/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java 2019-05-20 17:22:17.799830388 -0700 +++ new/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java 2019-05-20 17:22:17.517804078 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -41,6 +41,8 @@ * @since 1.4 */ public abstract class SAXParserFactory { + private static final String DEFAULT_IMPL = + "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"; /** * Should Parsers be validating? @@ -60,6 +62,76 @@ } /** + * Creates a new NamespaceAware instance of the {@code SAXParserFactory} + * builtin system-default implementation. Parsers produced by the factory + * instance provides support for XML namespaces by default. + * + * @implSpec + * In addition to creating a factory instance using the same process as + * {@link #newDefaultInstance()}, this method must set NamespaceAware to true. + * + * @return a new instance of the {@code SAXParserFactory} builtin + * system-default implementation. + * + * @since 13 + */ + public static SAXParserFactory newDefaultNSInstance() { + return makeNSAware(new SAXParserFactoryImpl()); + } + + /** + * Creates a new NamespaceAware instance of a {@code SAXParserFactory}. + * Parsers produced by the factory instance provides support for XML + * namespaces by default. + * + * @implSpec + * In addition to creating a factory instance using the same process as + * {@link #newInstance()}, this method must set NamespaceAware to true. + * + * @return a new instance of the {@code SAXParserFactory} + * + * @throws FactoryConfigurationError in case of {@linkplain + * java.util.ServiceConfigurationError service configuration error} + * or if the implementation is not available or cannot be instantiated. + * + * @since 13 + */ + public static SAXParserFactory newNSInstance() { + return makeNSAware(FactoryFinder.find(SAXParserFactory.class, DEFAULT_IMPL)); + } + + /** + * Creates a new NamespaceAware instance of a {@code SAXParserFactory} from + * the class name. Parsers produced by the factory instance provides + * support for XML namespaces by default. + * + * @implSpec + * In addition to creating a factory instance using the same process as + * {@link #newInstance(java.lang.String, java.lang.ClassLoader)}, this method + * must set NamespaceAware to true. + * + * @param factoryClassName a fully qualified factory class name that provides + * implementation of + * {@code javax.xml.parsers.SAXParserFactory}. + * + * @param classLoader the {@code ClassLoader} used to load the factory class. + * If it is {@code null}, the current {@code Thread}'s + * context classLoader is used to load the factory class. + * + * @return a new instance of the {@code SAXParserFactory} + * + * @throws FactoryConfigurationError if {@code factoryClassName} is {@code null}, or + * the factory class cannot be loaded, instantiated. + * + * @since 13 + */ + public static SAXParserFactory newNSInstance(String factoryClassName, + ClassLoader classLoader) { + return makeNSAware(FactoryFinder.newInstance( + SAXParserFactory.class, factoryClassName, classLoader, false)); + } + + /** * Creates a new instance of the {@code SAXParserFactory} builtin * system-default implementation. * @@ -148,7 +220,7 @@ /* The default property name according to the JAXP spec */ SAXParserFactory.class, /* The fallback implementation class name */ - "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"); + DEFAULT_IMPL); } /** @@ -192,6 +264,11 @@ factoryClassName, classLoader, false); } + private static SAXParserFactory makeNSAware(SAXParserFactory spf) { + spf.setNamespaceAware(true); + return spf; + } + /** * Creates a new instance of a SAXParser using the currently * configured factory parameters. --- old/test/jaxp/javax/xml/jaxp/unittest/parsers/BaseParsingTest.java 2019-05-20 17:22:18.473893270 -0700 +++ new/test/jaxp/javax/xml/jaxp/unittest/parsers/BaseParsingTest.java 2019-05-20 17:22:18.172865187 -0700 @@ -26,18 +26,27 @@ import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; +import org.testng.Assert; import static org.testng.Assert.assertEquals; import org.testng.annotations.DataProvider; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import org.w3c.dom.Document; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSSerializer; +import org.xml.sax.Attributes; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; /** * @test - * @bug 8169450 8222415 + * @bug 8169450 8222415 8219692 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true parsers.BaseParsingTest * @run testng/othervm parsers.BaseParsingTest @@ -45,6 +54,84 @@ */ @Listeners({jaxp.library.BasePolicy.class}) public class BaseParsingTest { + private static final String DOM_IMPL = + "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"; + private static final String SAX_IMPL = + "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"; + + String xml_8219692 = "" + + "in default namespace"; + + /** + * Creates NamespaceAware parsers using old and new factory methods. + * @return NamespaceAware parsers + * @throws ParserConfigurationException + */ + @DataProvider(name = "NSAwareDOMFactory") + public static Object[][] getNSDOMFactory() throws Exception { + boolean isNSAware = true; + + return new Object[][]{ + {getDOMParser(DocumentBuilderFactory.newDefaultInstance(), isNSAware)}, + {getDOMParser(DocumentBuilderFactory.newInstance(), isNSAware)}, + {getDOMParser(DocumentBuilderFactory.newInstance(DOM_IMPL, null), isNSAware)}, + // using the new methods + {DocumentBuilderFactory.newDefaultNSInstance().newDocumentBuilder()}, + {DocumentBuilderFactory.newNSInstance().newDocumentBuilder()}, + {DocumentBuilderFactory.newNSInstance(DOM_IMPL, null).newDocumentBuilder()} + }; + } + + /** + * Creates parsers using the old instance methods. By default, they are + * not Namespace Aware. + * @return non-NamespaceAware parsers + * @throws ParserConfigurationException + */ + @DataProvider(name = "DOMFactory") + public static Object[][] getDOMFactory() throws Exception { + boolean isNSAware = false; + + return new Object[][]{ + {getDOMParser(DocumentBuilderFactory.newDefaultInstance(), isNSAware)}, + {getDOMParser(DocumentBuilderFactory.newInstance(), isNSAware)}, + {getDOMParser(DocumentBuilderFactory.newInstance(DOM_IMPL, null), isNSAware)} + }; + } + + + /** + * Creates NamespaceAware parsers using old and new factory methods. + * @return NamespaceAware parsers + * @throws ParserConfigurationException + */ + @DataProvider(name = "NSAwareSAXFactory") + public static Object[][] getNSSAXFactory() throws Exception { + boolean isNSAware = true; + + return new Object[][]{ + {getSAXParser(SAXParserFactory.newDefaultInstance(), isNSAware)}, + {getSAXParser(SAXParserFactory.newInstance(), isNSAware)}, + {getSAXParser(SAXParserFactory.newInstance(SAX_IMPL, null), isNSAware)}, + // using the new methods + {SAXParserFactory.newDefaultNSInstance().newSAXParser()}, + {SAXParserFactory.newNSInstance().newSAXParser()}, + {SAXParserFactory.newNSInstance(SAX_IMPL, null).newSAXParser()}, + }; + } + + @DataProvider(name = "SAXFactory") + public static Object[][] getSAXFactory() throws Exception { + boolean isNSAware = false; + + return new Object[][]{ + {getSAXParser(SAXParserFactory.newDefaultInstance(), isNSAware)}, + {getSAXParser(SAXParserFactory.newInstance(), isNSAware)}, + {getSAXParser(SAXParserFactory.newInstance(SAX_IMPL, null), isNSAware)}, + }; + } @DataProvider(name = "xmlDeclarations") public static Object[][] xmlDeclarations() { @@ -174,4 +261,96 @@ Document doc = db.parse(is); assertEquals("UTF-16LE", doc.getInputEncoding()); } + + /** + * @bug 8219692 + * Verifies that the default namespace declaration is preserved when + * NamespaceAware is set on the parser. + * @throws Exception + */ + @Test(dataProvider = "NSAwareDOMFactory") + public void testNSAwareDOMFactory(DocumentBuilder db) throws Exception { + LSSerializer ls = getSerializer(db); + String out = ls.writeToString(getDoc(db, xml_8219692)); + System.out.println(out); + Assert.assertTrue(out.contains("http://openjdk_java_net/xml/defaultNS")); + } + + /** + * @bug 8219692 + * Verifies that the default namespace declaration is missing when the + * old factory methods are used. + * @throws Exception + */ + @Test(dataProvider = "DOMFactory") + public void testDOMFactory(DocumentBuilder db) throws Exception { + LSSerializer ls = getSerializer(db); + String out = ls.writeToString(getDoc(db, xml_8219692)); + System.out.println(out); + Assert.assertFalse(out.contains("http://openjdk_java_net/xml/defaultNS")); + } + + /** + * @bug 8219692 + * Verifies that the default namespace declaration is preserved when + * NamespaceAware is set on the parser. + * @throws Exception + */ + @Test(dataProvider = "NSAwareSAXFactory") + public void testNSAwareSAXFactory(SAXParser sp) throws Exception { + MyHandler h = new MyHandler(); + sp.parse(new InputSource(new StringReader(xml_8219692)), h); + + Assert.assertTrue(h.isNSAware); + } + + /** + * @bug 8219692 + * Verifies that the default namespace declaration is missing when the + * old factory methods are used. + * @throws Exception + */ + @Test(dataProvider = "SAXFactory") + public void testSAXFactory(SAXParser sp) throws Exception { + MyHandler h = new MyHandler(); + sp.parse(new InputSource(new StringReader(xml_8219692)), h); + + Assert.assertFalse(h.isNSAware); + } + + private static DocumentBuilder getDOMParser(DocumentBuilderFactory dbf, boolean isNSAware) + throws Exception { + dbf.setNamespaceAware(isNSAware); + return dbf.newDocumentBuilder(); + } + + private static SAXParser getSAXParser(SAXParserFactory spf, boolean isNSAware) + throws Exception { + spf.setNamespaceAware(isNSAware); + return spf.newSAXParser(); + } + + private LSSerializer getSerializer(DocumentBuilder db) throws Exception { + DOMImplementationLS di = (DOMImplementationLS) db.getDOMImplementation(); + return di.createLSSerializer(); + } + + private Document getDoc(DocumentBuilder db, String xml) throws Exception { + InputSource is = new InputSource(new StringReader(xml)); + return db.parse(is); + } + + /** + * SAX Handler + */ + class MyHandler extends DefaultHandler { + boolean isNSAware = false; + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + isNSAware = "http://openjdk_java_net/xml/defaultNS".equals(uri) + && ("a".equals(localName) || "b".equals(localName)); + } + } }