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