1 /* 2 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package parsers; 24 25 import java.io.ByteArrayInputStream; 26 import java.io.StringReader; 27 import javax.xml.parsers.DocumentBuilder; 28 import javax.xml.parsers.DocumentBuilderFactory; 29 import javax.xml.parsers.ParserConfigurationException; 30 import javax.xml.parsers.SAXParser; 31 import javax.xml.parsers.SAXParserFactory; 32 import javax.xml.stream.XMLInputFactory; 33 import javax.xml.stream.XMLStreamReader; 34 import org.testng.Assert; 35 import static org.testng.Assert.assertEquals; 36 import org.testng.annotations.DataProvider; 37 import org.testng.annotations.Listeners; 38 import org.testng.annotations.Test; 39 import org.w3c.dom.Document; 40 import org.w3c.dom.ls.DOMImplementationLS; 41 import org.w3c.dom.ls.LSSerializer; 42 import org.xml.sax.Attributes; 43 import org.xml.sax.InputSource; 44 import org.xml.sax.SAXException; 45 import org.xml.sax.helpers.DefaultHandler; 46 47 /** 48 * @test 49 * @bug 8169450 8222415 8219692 50 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest 51 * @run testng/othervm -DrunSecMngr=true parsers.BaseParsingTest 52 * @run testng/othervm parsers.BaseParsingTest 53 * @summary Tests that verify base parsing 54 */ 55 @Listeners({jaxp.library.BasePolicy.class}) 56 public class BaseParsingTest { 57 private static final String DOM_IMPL = 58 "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"; 59 private static final String SAX_IMPL = 60 "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"; 61 62 String xml_8219692 = "<a " 63 + "xmlns=\"http://openjdk_java_net/xml/defaultNS\" " 64 + "xmlns:p1=\"http://openjdk_java_net/xml/serializer/\">" 65 + "<b>in default namespace</b></a>"; 66 67 /** 68 * Creates NamespaceAware parsers using old and new factory methods. 69 * @return NamespaceAware parsers 70 * @throws ParserConfigurationException 71 */ 72 @DataProvider(name = "NSAwareDOMFactory") 73 public static Object[][] getNSDOMFactory() throws Exception { 74 boolean isNSAware = true; 75 76 return new Object[][]{ 77 {getDOMParser(DocumentBuilderFactory.newDefaultInstance(), isNSAware)}, 78 {getDOMParser(DocumentBuilderFactory.newInstance(), isNSAware)}, 79 {getDOMParser(DocumentBuilderFactory.newInstance(DOM_IMPL, null), isNSAware)}, 80 // using the new methods 81 {DocumentBuilderFactory.newDefaultNSInstance().newDocumentBuilder()}, 82 {DocumentBuilderFactory.newNSInstance().newDocumentBuilder()}, 83 {DocumentBuilderFactory.newNSInstance(DOM_IMPL, null).newDocumentBuilder()} 84 }; 85 } 86 87 /** 88 * Creates parsers using the old instance methods. By default, they are 89 * not Namespace Aware. 90 * @return non-NamespaceAware parsers 91 * @throws ParserConfigurationException 92 */ 93 @DataProvider(name = "DOMFactory") 94 public static Object[][] getDOMFactory() throws Exception { 95 boolean isNSAware = false; 96 97 return new Object[][]{ 98 {getDOMParser(DocumentBuilderFactory.newDefaultInstance(), isNSAware)}, 99 {getDOMParser(DocumentBuilderFactory.newInstance(), isNSAware)}, 100 {getDOMParser(DocumentBuilderFactory.newInstance(DOM_IMPL, null), isNSAware)} 101 }; 102 } 103 104 105 /** 106 * Creates NamespaceAware parsers using old and new factory methods. 107 * @return NamespaceAware parsers 108 * @throws ParserConfigurationException 109 */ 110 @DataProvider(name = "NSAwareSAXFactory") 111 public static Object[][] getNSSAXFactory() throws Exception { 112 boolean isNSAware = true; 113 114 return new Object[][]{ 115 {getSAXParser(SAXParserFactory.newDefaultInstance(), isNSAware)}, 116 {getSAXParser(SAXParserFactory.newInstance(), isNSAware)}, 117 {getSAXParser(SAXParserFactory.newInstance(SAX_IMPL, null), isNSAware)}, 118 // using the new methods 119 {SAXParserFactory.newDefaultNSInstance().newSAXParser()}, 120 {SAXParserFactory.newNSInstance().newSAXParser()}, 121 {SAXParserFactory.newNSInstance(SAX_IMPL, null).newSAXParser()}, 122 }; 123 } 124 125 @DataProvider(name = "SAXFactory") 126 public static Object[][] getSAXFactory() throws Exception { 127 boolean isNSAware = false; 128 129 return new Object[][]{ 130 {getSAXParser(SAXParserFactory.newDefaultInstance(), isNSAware)}, 131 {getSAXParser(SAXParserFactory.newInstance(), isNSAware)}, 132 {getSAXParser(SAXParserFactory.newInstance(SAX_IMPL, null), isNSAware)}, 133 }; 134 } 135 136 @DataProvider(name = "xmlDeclarations") 137 public static Object[][] xmlDeclarations() { 138 return new Object[][]{ 139 {"<?xml version=\"1.0\"?><root><test>t</test></root>"}, 140 {"<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><test>t</test></root>"}, 141 {"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone='yes'?><root><test>t</test></root>"}, 142 {"<?xml\n" 143 + " version=\"1.0\"?>\n" 144 + "<root>\n" 145 + " <test>t</test>\n" 146 + "</root>"}, 147 {"<?xml\n" 148 + " version=\"1.0\"\n" 149 + " encoding=\"UTF-8\"?>\n" 150 + "<root>\n" 151 + " <test>t</test>\n" 152 + "</root>"}, 153 {"<?xml\n" 154 + " version=\"1.0\"\n" 155 + " encoding=\"UTF-8\"\n" 156 + " standalone=\"yes\"?>\n" 157 + "<root>\n" 158 + " <test>t</test>\n" 159 + "</root>"}, 160 {"<?xml\n" 161 + " version\n" 162 + "=\n" 163 + "\"1.0\"\n" 164 + " encoding\n" 165 + "=\n" 166 + "\"UTF-8\"\n" 167 + " standalone\n" 168 + "=\n" 169 + "\"yes\"?>\n" 170 + "<root>\n" 171 + " <test>t</test>\n" 172 + "</root>"}, 173 {"<?xml version=\"1.1\"?><root><test>t</test></root>"}, 174 {"<?xml version=\"1.1\" encoding=\"UTF-8\"?><root><test>t</test></root>"}, 175 {"<?xml version=\"1.1\" encoding=\"UTF-8\" standalone='yes'?><root><test>t</test></root>"}, 176 {"<?xml\n" 177 + " version=\"1.1\"?>\n" 178 + "<root>\n" 179 + " <test>t</test>\n" 180 + "</root>"}, 181 {"<?xml\n" 182 + " version=\"1.1\"\n" 183 + " encoding=\"UTF-8\"?>\n" 184 + "<root>\n" 185 + " <test>t</test>\n" 186 + "</root>"}, 187 {"<?xml\n" 188 + " version=\"1.1\"\n" 189 + " encoding=\"UTF-8\"\n" 190 + " standalone=\"yes\"?>\n" 191 + "<root>\n" 192 + " <test>t</test>\n" 193 + "</root>"}, 194 {"<?xml\n" 195 + " version\n" 196 + "=\n" 197 + "\"1.1\"\n" 198 + " encoding\n" 199 + "=\n" 200 + "\"UTF-8\"\n" 201 + " standalone\n" 202 + "=\n" 203 + "\"yes\"?>\n" 204 + "<root>\n" 205 + " <test>t</test>\n" 206 + "</root>"} 207 }; 208 } 209 210 /** 211 * @bug 8169450 212 * Verifies that the parser successfully parses the declarations provided in 213 * xmlDeclarations. Exception would otherwise be thrown as reported in 8169450. 214 * 215 * XML Declaration according to https://www.w3.org/TR/REC-xml/#NT-XMLDecl 216 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' 217 * [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') 218 * [25] Eq ::= S? '=' S? [26] VersionNum ::= '1.' [0-9]+ 219 * 220 * @param xml the test xml 221 * @throws Exception if the parser fails to parse the xml 222 */ 223 @Test(dataProvider = "xmlDeclarations") 224 public void test(String xml) throws Exception { 225 XMLInputFactory xif = XMLInputFactory.newDefaultFactory(); 226 XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml)); 227 while (xsr.hasNext()) { 228 xsr.next(); 229 } 230 } 231 232 /** 233 * @bug 8169450 234 * This particular issue does not appear in DOM parsing since the spaces are 235 * normalized during version detection. This test case then serves as a guard 236 * against such an issue from occurring in the version detection. 237 * 238 * @param xml the test xml 239 * @throws Exception if the parser fails to parse the xml 240 */ 241 @Test(dataProvider = "xmlDeclarations") 242 public void testWithDOM(String xml) throws Exception { 243 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 244 DocumentBuilder db = dbf.newDocumentBuilder(); 245 db.parse(new InputSource(new StringReader(xml))); 246 } 247 248 /** 249 * @bug 8222415 250 * Verifies that the parser is configured properly for UTF-16BE or LE. 251 * @throws Exception 252 */ 253 @Test 254 public void testEncoding() throws Exception { 255 ByteArrayInputStream bis = new ByteArrayInputStream( 256 "<?xml version=\"1.0\" encoding=\"UTF-16\"?> <a/>".getBytes("UnicodeLittle")); 257 InputSource is = new InputSource(bis); 258 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 259 DocumentBuilder db = dbf.newDocumentBuilder(); 260 261 Document doc = db.parse(is); 262 assertEquals("UTF-16LE", doc.getInputEncoding()); 263 } 264 265 /** 266 * @bug 8219692 267 * Verifies that the default namespace declaration is preserved when 268 * NamespaceAware is set on the parser. 269 * @throws Exception 270 */ 271 @Test(dataProvider = "NSAwareDOMFactory") 272 public void testNSAwareDOMFactory(DocumentBuilder db) throws Exception { 273 LSSerializer ls = getSerializer(db); 274 String out = ls.writeToString(getDoc(db, xml_8219692)); 275 System.out.println(out); 276 Assert.assertTrue(out.contains("http://openjdk_java_net/xml/defaultNS")); 277 } 278 279 /** 280 * @bug 8219692 281 * Verifies that the default namespace declaration is missing when the 282 * old factory methods are used. 283 * @throws Exception 284 */ 285 @Test(dataProvider = "DOMFactory") 286 public void testDOMFactory(DocumentBuilder db) throws Exception { 287 LSSerializer ls = getSerializer(db); 288 String out = ls.writeToString(getDoc(db, xml_8219692)); 289 System.out.println(out); 290 Assert.assertFalse(out.contains("http://openjdk_java_net/xml/defaultNS")); 291 } 292 293 /** 294 * @bug 8219692 295 * Verifies that the default namespace declaration is preserved when 296 * NamespaceAware is set on the parser. 297 * @throws Exception 298 */ 299 @Test(dataProvider = "NSAwareSAXFactory") 300 public void testNSAwareSAXFactory(SAXParser sp) throws Exception { 301 MyHandler h = new MyHandler(); 302 sp.parse(new InputSource(new StringReader(xml_8219692)), h); 303 304 Assert.assertTrue(h.isNSAware); 305 } 306 307 /** 308 * @bug 8219692 309 * Verifies that the default namespace declaration is missing when the 310 * old factory methods are used. 311 * @throws Exception 312 */ 313 @Test(dataProvider = "SAXFactory") 314 public void testSAXFactory(SAXParser sp) throws Exception { 315 MyHandler h = new MyHandler(); 316 sp.parse(new InputSource(new StringReader(xml_8219692)), h); 317 318 Assert.assertFalse(h.isNSAware); 319 } 320 321 private static DocumentBuilder getDOMParser(DocumentBuilderFactory dbf, boolean isNSAware) 322 throws Exception { 323 dbf.setNamespaceAware(isNSAware); 324 return dbf.newDocumentBuilder(); 325 } 326 327 private static SAXParser getSAXParser(SAXParserFactory spf, boolean isNSAware) 328 throws Exception { 329 spf.setNamespaceAware(isNSAware); 330 return spf.newSAXParser(); 331 } 332 333 private LSSerializer getSerializer(DocumentBuilder db) throws Exception { 334 DOMImplementationLS di = (DOMImplementationLS) db.getDOMImplementation(); 335 return di.createLSSerializer(); 336 } 337 338 private Document getDoc(DocumentBuilder db, String xml) throws Exception { 339 InputSource is = new InputSource(new StringReader(xml)); 340 return db.parse(is); 341 } 342 343 /** 344 * SAX Handler 345 */ 346 class MyHandler extends DefaultHandler { 347 boolean isNSAware = false; 348 349 @Override 350 public void startElement(String uri, String localName, String qName, 351 Attributes attributes) throws SAXException { 352 isNSAware = "http://openjdk_java_net/xml/defaultNS".equals(uri) 353 && ("a".equals(localName) || "b".equals(localName)); 354 } 355 } 356 }