8219692: DOM and SAX parsers ignore namespace
Reviewed-by: lancea
This commit is contained in:
parent
8f1d837e99
commit
2e09b8459b
@ -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 @@ import javax.xml.validation.Schema;
|
||||
*/
|
||||
|
||||
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;
|
||||
@ -54,6 +55,76 @@ public abstract class DocumentBuilderFactory {
|
||||
protected DocumentBuilderFactory () {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public abstract class DocumentBuilderFactory {
|
||||
/* 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 @@ public abstract class DocumentBuilderFactory {
|
||||
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.
|
||||
|
@ -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 @@ import org.xml.sax.SAXNotSupportedException;
|
||||
* @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?
|
||||
@ -59,6 +61,76 @@ public abstract class SAXParserFactory {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public abstract class SAXParserFactory {
|
||||
/* 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 @@ public abstract class SAXParserFactory {
|
||||
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.
|
||||
|
@ -26,18 +26,27 @@ import java.io.ByteArrayInputStream;
|
||||
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 @@ import org.xml.sax.InputSource;
|
||||
*/
|
||||
@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 = "<a "
|
||||
+ "xmlns=\"http://openjdk_java_net/xml/defaultNS\" "
|
||||
+ "xmlns:p1=\"http://openjdk_java_net/xml/serializer/\">"
|
||||
+ "<b>in default namespace</b></a>";
|
||||
|
||||
/**
|
||||
* 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 @@ public class BaseParsingTest {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user