1 /* 2 * Copyright (c) 2014, 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 test.auctionportal; 24 25 import static com.sun.org.apache.xerces.internal.impl.Constants.SP_ENTITY_EXPANSION_LIMIT; 26 import static com.sun.org.apache.xerces.internal.impl.Constants.SP_MAX_OCCUR_LIMIT; 27 import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE; 28 import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_SOURCE; 29 import static org.testng.Assert.assertTrue; 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileOutputStream; 33 import java.io.FilePermission; 34 import java.io.IOException; 35 import java.io.InputStream; 36 import java.io.UnsupportedEncodingException; 37 import static javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING; 38 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; 39 import javax.xml.parsers.DocumentBuilder; 40 import javax.xml.parsers.DocumentBuilderFactory; 41 import javax.xml.parsers.ParserConfigurationException; 42 import javax.xml.parsers.SAXParser; 43 import javax.xml.parsers.SAXParserFactory; 44 import javax.xml.transform.TransformerException; 45 import javax.xml.transform.TransformerFactory; 46 import javax.xml.transform.dom.DOMSource; 47 import javax.xml.transform.stream.StreamResult; 48 import jaxp.library.JAXPFileBaseTest; 49 import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold; 50 import static org.testng.Assert.assertFalse; 51 import org.testng.annotations.AfterGroups; 52 import org.testng.annotations.BeforeGroups; 53 import org.testng.annotations.Test; 54 import org.w3c.dom.Document; 55 import org.xml.sax.SAXException; 56 import org.xml.sax.SAXParseException; 57 import static test.auctionportal.HiBidConstants.CLASS_DIR; 58 import static test.auctionportal.HiBidConstants.GOLDEN_DIR; 59 import static test.auctionportal.HiBidConstants.XML_DIR; 60 61 /** 62 * This is a test class for the Auction portal HiBid.com. 63 */ 64 public class AuctionItemRepository extends JAXPFileBaseTest { 65 /** 66 * XML file for parsing. 67 */ 68 private final static String ENTITY_XML = XML_DIR + "entity.xml"; 69 70 /** 71 * Feature name. 72 */ 73 private final static String FEATURE_NAME = "http://xml.org/sax/features/namespace-prefixes"; 74 75 /** 76 * Setting the EntityExpansion Limit to 128000 and checks if the XML 77 * document that has more than two levels of entity expansion is parsed or 78 * not. Previous system property was changed to jdk.xml.entityExpansionLimit 79 * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html. 80 * 81 * @throws ParserConfigurationException if a DocumentBuilder cannot be 82 * created which satisfies the configuration requested. 83 * @throws SAXException If any parse errors occur. 84 * @throws IOException if the file exists but is a directory rather than 85 * a regular file, does not exist but cannot be created, or cannot 86 * be opened for any other reason. 87 */ 88 @Test 89 public void testEntityExpansionSAXPos() throws ParserConfigurationException, 90 SAXException, IOException { 91 SAXParserFactory factory = SAXParserFactory.newInstance(); 92 // Secure processing will limit XML processing to conform to 93 // implementation limits. 94 factory.setFeature(FEATURE_SECURE_PROCESSING, true); 95 // Set entityExpansionLimit as 2 should expect fatalError 96 setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(128000)); 97 SAXParser parser = factory.newSAXParser(); 98 99 MyErrorHandler fatalHandler = new MyErrorHandler(); 100 setPermissions(new FilePermission(ENTITY_XML, "read")); 101 parser.parse(new File(ENTITY_XML), fatalHandler); 102 assertFalse(fatalHandler.isAnyError()); 103 } 104 /** 105 * Setting the EntityExpansion Limit to 2 and checks if the XML 106 * document that has more than two levels of entity expansion is parsed or 107 * not. Previous system property was changed to jdk.xml.entityExpansionLimit 108 * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html. 109 * 110 * @throws ParserConfigurationException if a DocumentBuilder cannot be 111 * created which satisfies the configuration requested. 112 * @throws SAXException If any parse errors occur. 113 * @throws IOException if the file exists but is a directory rather than 114 * a regular file, does not exist but cannot be created, or cannot 115 * be opened for any other reason. 116 */ 117 @Test(expectedExceptions = SAXParseException.class) 118 public void testEntityExpansionSAXNeg() throws ParserConfigurationException, 119 SAXException, IOException { 120 SAXParserFactory factory = SAXParserFactory.newInstance(); 121 // Secure processing will limit XML processing to conform to 122 // implementation limits. 123 factory.setFeature(FEATURE_SECURE_PROCESSING, true); 124 // Set entityExpansionLimit as 2 should expect SAXParseException. 125 setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2)); 126 127 SAXParser parser = factory.newSAXParser(); 128 MyErrorHandler fatalHandler = new MyErrorHandler(); 129 setPermissions(new FilePermission(ENTITY_XML, "read")); 130 parser.parse(new File(ENTITY_XML), fatalHandler); 131 } 132 133 /** 134 * Testing set MaxOccursLimit to 10000 in the secure processing enabled for 135 * SAXParserFactory. 136 * 137 * @throws ParserConfigurationException if a DocumentBuilder cannot be 138 * created which satisfies the configuration requested. 139 * @throws SAXException If any parse errors occur. 140 * @throws IOException if the file exists but is a directory rather than 141 * a regular file, does not exist but cannot be created, or cannot 142 * be opened for any other reason. 143 */ 144 @Test 145 public void testMaxOccurLimitPos() throws ParserConfigurationException, 146 SAXException, IOException { 147 String schema_file = XML_DIR + "toys.xsd"; 148 String xml_file = XML_DIR + "toys.xml"; 149 SAXParserFactory factory = SAXParserFactory.newInstance(); 150 factory.setValidating(true); 151 factory.setFeature(FEATURE_SECURE_PROCESSING, true); 152 setSystemProperty(SP_MAX_OCCUR_LIMIT, String.valueOf(10000)); 153 SAXParser parser = factory.newSAXParser(); 154 parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI); 155 setPermissions(new FilePermission(XML_DIR + "-", "read")); 156 parser.setProperty(JAXP_SCHEMA_SOURCE, new File(schema_file)); 157 try (InputStream is = new FileInputStream(xml_file)) { 158 MyErrorHandler eh = new MyErrorHandler(); 159 parser.parse(is, eh); 160 assertFalse(eh.isAnyError()); 161 } 162 } 163 164 /** 165 * Use a DocumentBuilder to create a DOM object and see if Secure Processing 166 * feature affects the entity expansion. 167 * 168 * @throws ParserConfigurationException if a DocumentBuilder cannot be 169 * created which satisfies the configuration requested. 170 * @throws SAXException If any parse errors occur. 171 * @throws IOException if the file exists but is a directory rather than 172 * a regular file, does not exist but cannot be created, or cannot 173 * be opened for any other reason. 174 */ 175 @Test 176 public void testEntityExpansionDOMPos() throws ParserConfigurationException, 177 SAXException, IOException { 178 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 179 dfactory.setFeature(FEATURE_SECURE_PROCESSING, true); 180 setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(10000)); 181 DocumentBuilder dBuilder = dfactory.newDocumentBuilder(); 182 MyErrorHandler eh = new MyErrorHandler(); 183 dBuilder.setErrorHandler(eh); 184 setPermissions(new FilePermission(ENTITY_XML, "read")); 185 dBuilder.parse(ENTITY_XML); 186 assertFalse(eh.isAnyError()); 187 } 188 189 /** 190 * Use a DocumentBuilder to create a DOM object and see how does the Secure 191 * Processing feature and entityExpansionLimit value affects output. 192 * Negative test that when entityExpansionLimit is too small. 193 * 194 * @throws ParserConfigurationException if a DocumentBuilder cannot be 195 * created which satisfies the configuration requested. 196 * @throws SAXException If any parse errors occur. 197 * @throws IOException if the file exists but is a directory rather than 198 * a regular file, does not exist but cannot be created, or cannot 199 * be opened for any other reason. 200 */ 201 @Test(expectedExceptions = SAXParseException.class) 202 public void testEntityExpansionDOMNeg() throws ParserConfigurationException, 203 SAXException, IOException { 204 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 205 dfactory.setFeature(FEATURE_SECURE_PROCESSING, true); 206 setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2)); 207 DocumentBuilder dBuilder = dfactory.newDocumentBuilder(); 208 MyErrorHandler eh = new MyErrorHandler(); 209 dBuilder.setErrorHandler(eh); 210 setPermissions(new FilePermission(ENTITY_XML, "read")); 211 dBuilder.parse(ENTITY_XML); 212 } 213 214 215 /** 216 * Save system property for restoring. 217 */ 218 @BeforeGroups (groups = {"readWriteLocalFiles"}) 219 public void setFilePermissions() { 220 setPermissions(new FilePermission(XML_DIR + "/-", "read"), 221 new FilePermission(GOLDEN_DIR + "/-", "read"), 222 new FilePermission(CLASS_DIR + "/-", "read, write")); 223 } 224 225 /** 226 * Restore the system property. 227 */ 228 @AfterGroups (groups = {"readWriteLocalFiles"}) 229 public void restoreFilePermissions() { 230 setPermissions(); 231 } 232 /** 233 * Test xi:include with a SAXParserFactory. 234 * 235 * @throws UnsupportedEncodingException if given encoding is an invalid 236 * encoding name. 237 * @throws ParserConfigurationException if a DocumentBuilder cannot be 238 * created which satisfies the configuration requested. 239 * @throws SAXException If any parse errors occur. 240 * @throws IOException if the file exists but is a directory rather than 241 * a regular file, does not exist but cannot be created, or cannot 242 * be opened for any other reason. 243 */ 244 @Test(groups = {"readWriteLocalFiles"}) 245 public void testXIncludeSAXPos() throws UnsupportedEncodingException, 246 ParserConfigurationException, SAXException, IOException { 247 String resultFile = CLASS_DIR + "doc_xinclude.out"; 248 String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml"; 249 String xmlFile = XML_DIR + "doc_xinclude.xml"; 250 251 try(FileOutputStream fos = new FileOutputStream(resultFile)) { 252 XInclHandler xh = new XInclHandler(fos, null); 253 SAXParserFactory spf = SAXParserFactory.newInstance(); 254 spf.setNamespaceAware(true); 255 spf.setXIncludeAware(true); 256 spf.setFeature(FEATURE_NAME, true); 257 spf.newSAXParser().parse(new File(xmlFile), xh); 258 } 259 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 260 } 261 262 /** 263 * Test the simple case of including a document using xi:include using a 264 * DocumentBuilder. 265 * 266 * @throws ParserConfigurationException if a DocumentBuilder cannot be 267 * created which satisfies the configuration requested. 268 * @throws SAXException If any parse errors occur. 269 * @throws IOException if the file exists but is a directory rather than 270 * a regular file, does not exist but cannot be created, or cannot 271 * be opened for any other reason. 272 * @throws TransformerException If an unrecoverable error occurs 273 * during the course of the transformation. 274 */ 275 @Test(groups = {"readWriteLocalFiles"}) 276 public void testXIncludeDOMPos() throws ParserConfigurationException, 277 SAXException, IOException, TransformerException { 278 String resultFile = CLASS_DIR + "doc_xincludeDOM.out"; 279 String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml"; 280 String xmlFile = XML_DIR + "doc_xinclude.xml"; 281 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 282 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 283 dbf.setXIncludeAware(true); 284 dbf.setNamespaceAware(true); 285 Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); 286 doc.setXmlStandalone(true); 287 TransformerFactory.newInstance().newTransformer(). 288 transform(new DOMSource(doc), new StreamResult(fos)); 289 } 290 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 291 } 292 293 /** 294 * Test the simple case of including a document using xi:include within a 295 * xi:fallback using a DocumentBuilder. 296 * 297 * @throws ParserConfigurationException if a DocumentBuilder cannot be 298 * created which satisfies the configuration requested. 299 * @throws SAXException If any parse errors occur. 300 * @throws IOException if the file exists but is a directory rather than 301 * a regular file, does not exist but cannot be created, or cannot 302 * be opened for any other reason. 303 * @throws TransformerException If an unrecoverable error occurs 304 * during the course of the transformation. 305 */ 306 @Test(groups = {"readWriteLocalFiles"}) 307 public void testXIncludeFallbackDOMPos() throws ParserConfigurationException, 308 SAXException, IOException, TransformerException { 309 String resultFile = CLASS_DIR + "doc_fallbackDOM.out"; 310 String goldFile = GOLDEN_DIR + "doc_fallbackGold.xml"; 311 String xmlFile = XML_DIR + "doc_fallback.xml"; 312 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 313 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 314 dbf.setXIncludeAware(true); 315 dbf.setNamespaceAware(true); 316 317 Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); 318 doc.setXmlStandalone(true); 319 TransformerFactory.newInstance().newTransformer() 320 .transform(new DOMSource(doc), new StreamResult(fos)); 321 } 322 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 323 } 324 325 /** 326 * Test for xi:fallback where the fall back text is parsed as text. This 327 * test uses a nested xi:include for the fallback test. 328 * 329 * @throws ParserConfigurationException if a DocumentBuilder cannot be 330 * created which satisfies the configuration requested. 331 * @throws SAXException If any parse errors occur. 332 * @throws IOException if the file exists but is a directory rather than 333 * a regular file, does not exist but cannot be created, or cannot 334 * be opened for any other reason. 335 * @throws TransformerException If an unrecoverable error occurs 336 * during the course of the transformation. 337 */ 338 @Test(groups = {"readWriteLocalFiles"}) 339 public void testXIncludeFallbackTextPos() throws ParserConfigurationException, 340 SAXException, IOException, TransformerException { 341 String resultFile = CLASS_DIR + "doc_fallback_text.out"; 342 String goldFile = GOLDEN_DIR + "doc_fallback_textGold.xml"; 343 String xmlFile = XML_DIR + "doc_fallback_text.xml"; 344 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 345 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 346 dbf.setXIncludeAware(true); 347 dbf.setNamespaceAware(true); 348 349 Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); 350 doc.setXmlStandalone(true); 351 TransformerFactory.newInstance().newTransformer() 352 .transform(new DOMSource(doc), new StreamResult(fos)); 353 } 354 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 355 } 356 357 /** 358 * Test the XPointer element() framework with XInclude. 359 * 360 * @throws ParserConfigurationException if a DocumentBuilder cannot be 361 * created which satisfies the configuration requested. 362 * @throws SAXException If any parse errors occur. 363 * @throws IOException if the file exists but is a directory rather than 364 * a regular file, does not exist but cannot be created, or cannot 365 * be opened for any other reason. 366 * @throws TransformerException If an unrecoverable error occurs 367 * during the course of the transformation. 368 */ 369 @Test(groups = {"readWriteLocalFiles"}) 370 public void testXpointerElementPos() throws ParserConfigurationException, 371 TransformerException, SAXException, IOException { 372 String resultFile = CLASS_DIR + "doc_xpointer_element.out"; 373 String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml"; 374 String xmlFile = XML_DIR + "doc_xpointer_element.xml"; 375 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 376 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 377 dbf.setXIncludeAware(true); 378 dbf.setNamespaceAware(true); 379 380 DocumentBuilder db = dbf.newDocumentBuilder(); 381 382 TransformerFactory.newInstance().newTransformer() 383 .transform(new DOMSource(db.parse(new File(xmlFile))), 384 new StreamResult(fos)); 385 } 386 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 387 } 388 389 /** 390 * Test the XPointer framework with a SAX object. 391 * 392 * @throws ParserConfigurationException if a DocumentBuilder cannot be 393 * created which satisfies the configuration requested. 394 * @throws SAXException If any parse errors occur. 395 * @throws IOException if the file exists but is a directory rather than 396 * a regular file, does not exist but cannot be created, or cannot 397 * be opened for any other reason. 398 * @throws TransformerException If an unrecoverable error occurs 399 * during the course of the transformation. 400 */ 401 @Test(groups = {"readWriteLocalFiles"}) 402 public void testXPointerPos() throws ParserConfigurationException, 403 TransformerException, SAXException, IOException { 404 String resultFile = CLASS_DIR + "doc_xpointer.out"; 405 String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml"; 406 String xmlFile = XML_DIR + "doc_xpointer.xml"; 407 408 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 409 SAXParserFactory spf = SAXParserFactory.newInstance(); 410 spf.setNamespaceAware(true); 411 spf.setXIncludeAware(true); 412 spf.setFeature(FEATURE_NAME, true); 413 // parse the file 414 spf.newSAXParser().parse(new File(xmlFile), new XInclHandler(fos, null)); 415 } 416 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 417 } 418 419 /** 420 * Test if xi:include may reference the doc containing the include if the 421 * parse type is text. 422 * 423 * @throws ParserConfigurationException if a DocumentBuilder cannot be 424 * created which satisfies the configuration requested. 425 * @throws SAXException If any parse errors occur. 426 * @throws IOException if the file exists but is a directory rather than 427 * a regular file, does not exist but cannot be created, or cannot 428 * be opened for any other reason. 429 * @throws TransformerException If an unrecoverable error occurs 430 * during the course of the transformation. 431 */ 432 @Test(groups = {"readWriteLocalFiles"}) 433 public void testXIncludeLoopPos() throws ParserConfigurationException, 434 TransformerException, SAXException, IOException { 435 String resultFile = CLASS_DIR + "doc_xinc_loops.out"; 436 String goldFile = GOLDEN_DIR + "doc_xinc_loopGold.xml"; 437 String xmlFile = XML_DIR + "doc_xinc_loops.xml"; 438 439 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 440 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 441 dbf.setXIncludeAware(true); 442 dbf.setNamespaceAware(true); 443 DocumentBuilder db = dbf.newDocumentBuilder(); 444 Document doc = db.parse(new File(xmlFile)); 445 doc.normalizeDocument(); 446 doc.setXmlStandalone(true); 447 448 TransformerFactory.newInstance().newTransformer() 449 .transform(new DOMSource(doc), new StreamResult(fos)); 450 } 451 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 452 } 453 454 /** 455 * Test if two non nested xi:include elements can include the same document 456 * with an xi:include statement. 457 * 458 * @throws ParserConfigurationException if a DocumentBuilder cannot be 459 * created which satisfies the configuration requested. 460 * @throws SAXException If any parse errors occur. 461 * @throws IOException if the file exists but is a directory rather than 462 * a regular file, does not exist but cannot be created, or cannot 463 * be opened for any other reason. 464 * @throws TransformerException If an unrecoverable error occurs 465 * during the course of the transformation. 466 */ 467 @Test(groups = {"readWriteLocalFiles"}) 468 public void testXIncludeNestedPos() throws ParserConfigurationException, 469 TransformerException, SAXException, IOException { 470 String resultFile = CLASS_DIR + "schedule.out"; 471 String goldFile = GOLDEN_DIR + "scheduleGold.xml"; 472 String xmlFile = XML_DIR + "schedule.xml"; 473 474 try (FileOutputStream fos = new FileOutputStream(resultFile)) { 475 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 476 dbf.setXIncludeAware(true); 477 dbf.setNamespaceAware(true); 478 479 Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); 480 doc.setXmlStandalone(true); 481 TransformerFactory.newInstance().newTransformer() 482 .transform(new DOMSource(doc), new StreamResult(fos)); 483 } 484 assertTrue(compareDocumentWithGold(goldFile, resultFile)); 485 } 486 }