/* * Copyright (c) 2014, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package test.auctionportal; import static com.sun.org.apache.xerces.internal.impl.Constants.SP_ENTITY_EXPANSION_LIMIT; import static com.sun.org.apache.xerces.internal.impl.Constants.SP_MAX_OCCUR_LIMIT; import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE; import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_SOURCE; import static org.testng.Assert.assertTrue; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import static javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING; import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; 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.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import jaxp.library.JAXPFileBaseTest; import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold; import static org.testng.Assert.assertFalse; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import org.w3c.dom.Document; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import static test.auctionportal.HiBidConstants.CLASS_DIR; import static test.auctionportal.HiBidConstants.GOLDEN_DIR; import static test.auctionportal.HiBidConstants.XML_DIR; /** * This is a test class for the Auction portal HiBid.com. */ public class AuctionItemRepository extends JAXPFileBaseTest { /** * XML file for parsing. */ private final static String ENTITY_XML = XML_DIR + "entity.xml"; /** * Feature name. */ private final static String FEATURE_NAME = "http://xml.org/sax/features/namespace-prefixes"; /** * Setting the EntityExpansion Limit to 128000 and checks if the XML * document that has more than two levels of entity expansion is parsed or * not. Previous system property was changed to jdk.xml.entityExpansionLimit * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. */ @Test public void testEntityExpansionSAXPos() throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); // Secure processing will limit XML processing to conform to // implementation limits. factory.setFeature(FEATURE_SECURE_PROCESSING, true); // Set entityExpansionLimit as 2 should expect fatalError setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(128000)); SAXParser parser = factory.newSAXParser(); MyErrorHandler fatalHandler = new MyErrorHandler(); setPermissions(new FilePermission(ENTITY_XML, "read")); parser.parse(new File(ENTITY_XML), fatalHandler); assertFalse(fatalHandler.isAnyError()); } /** * Setting the EntityExpansion Limit to 2 and checks if the XML * document that has more than two levels of entity expansion is parsed or * not. Previous system property was changed to jdk.xml.entityExpansionLimit * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. */ @Test(expectedExceptions = SAXParseException.class) public void testEntityExpansionSAXNeg() throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); // Secure processing will limit XML processing to conform to // implementation limits. factory.setFeature(FEATURE_SECURE_PROCESSING, true); // Set entityExpansionLimit as 2 should expect SAXParseException. setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2)); SAXParser parser = factory.newSAXParser(); MyErrorHandler fatalHandler = new MyErrorHandler(); setPermissions(new FilePermission(ENTITY_XML, "read")); parser.parse(new File(ENTITY_XML), fatalHandler); } /** * Testing set MaxOccursLimit to 10000 in the secure processing enabled for * SAXParserFactory. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. */ @Test public void testMaxOccurLimitPos() throws ParserConfigurationException, SAXException, IOException { String schema_file = XML_DIR + "toys.xsd"; String xml_file = XML_DIR + "toys.xml"; SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); factory.setFeature(FEATURE_SECURE_PROCESSING, true); setSystemProperty(SP_MAX_OCCUR_LIMIT, String.valueOf(10000)); SAXParser parser = factory.newSAXParser(); parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI); setPermissions(new FilePermission(XML_DIR + "-", "read")); parser.setProperty(JAXP_SCHEMA_SOURCE, new File(schema_file)); try (InputStream is = new FileInputStream(xml_file)) { MyErrorHandler eh = new MyErrorHandler(); parser.parse(is, eh); assertFalse(eh.isAnyError()); } } /** * Use a DocumentBuilder to create a DOM object and see if Secure Processing * feature affects the entity expansion. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. */ @Test public void testEntityExpansionDOMPos() throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); dfactory.setFeature(FEATURE_SECURE_PROCESSING, true); setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(10000)); DocumentBuilder dBuilder = dfactory.newDocumentBuilder(); MyErrorHandler eh = new MyErrorHandler(); dBuilder.setErrorHandler(eh); setPermissions(new FilePermission(ENTITY_XML, "read")); dBuilder.parse(ENTITY_XML); assertFalse(eh.isAnyError()); } /** * Use a DocumentBuilder to create a DOM object and see how does the Secure * Processing feature and entityExpansionLimit value affects output. * Negative test that when entityExpansionLimit is too small. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. */ @Test(expectedExceptions = SAXParseException.class) public void testEntityExpansionDOMNeg() throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); dfactory.setFeature(FEATURE_SECURE_PROCESSING, true); setSystemProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2)); DocumentBuilder dBuilder = dfactory.newDocumentBuilder(); MyErrorHandler eh = new MyErrorHandler(); dBuilder.setErrorHandler(eh); setPermissions(new FilePermission(ENTITY_XML, "read")); dBuilder.parse(ENTITY_XML); } /** * Save system property for restoring. */ @BeforeGroups (groups = {"readWriteLocalFiles"}) public void setFilePermissions() { setPermissions(new FilePermission(XML_DIR + "/-", "read"), new FilePermission(GOLDEN_DIR + "/-", "read"), new FilePermission(CLASS_DIR + "/-", "read, write")); } /** * Restore the system property. */ @AfterGroups (groups = {"readWriteLocalFiles"}) public void restoreFilePermissions() { setPermissions(); } /** * Test xi:include with a SAXParserFactory. * * @throws UnsupportedEncodingException if given encoding is an invalid * encoding name. * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. */ @Test(groups = {"readWriteLocalFiles"}) public void testXIncludeSAXPos() throws UnsupportedEncodingException, ParserConfigurationException, SAXException, IOException { String resultFile = CLASS_DIR + "doc_xinclude.out"; String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml"; String xmlFile = XML_DIR + "doc_xinclude.xml"; try(FileOutputStream fos = new FileOutputStream(resultFile)) { XInclHandler xh = new XInclHandler(fos, null); SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setXIncludeAware(true); spf.setFeature(FEATURE_NAME, true); spf.newSAXParser().parse(new File(xmlFile), xh); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test the simple case of including a document using xi:include using a * DocumentBuilder. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXIncludeDOMPos() throws ParserConfigurationException, SAXException, IOException, TransformerException { String resultFile = CLASS_DIR + "doc_xincludeDOM.out"; String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml"; String xmlFile = XML_DIR + "doc_xinclude.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); doc.setXmlStandalone(true); TransformerFactory.newInstance().newTransformer(). transform(new DOMSource(doc), new StreamResult(fos)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test the simple case of including a document using xi:include within a * xi:fallback using a DocumentBuilder. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXIncludeFallbackDOMPos() throws ParserConfigurationException, SAXException, IOException, TransformerException { String resultFile = CLASS_DIR + "doc_fallbackDOM.out"; String goldFile = GOLDEN_DIR + "doc_fallbackGold.xml"; String xmlFile = XML_DIR + "doc_fallback.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); doc.setXmlStandalone(true); TransformerFactory.newInstance().newTransformer() .transform(new DOMSource(doc), new StreamResult(fos)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test for xi:fallback where the fall back text is parsed as text. This * test uses a nested xi:include for the fallback test. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXIncludeFallbackTextPos() throws ParserConfigurationException, SAXException, IOException, TransformerException { String resultFile = CLASS_DIR + "doc_fallback_text.out"; String goldFile = GOLDEN_DIR + "doc_fallback_textGold.xml"; String xmlFile = XML_DIR + "doc_fallback_text.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); doc.setXmlStandalone(true); TransformerFactory.newInstance().newTransformer() .transform(new DOMSource(doc), new StreamResult(fos)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test the XPointer element() framework with XInclude. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXpointerElementPos() throws ParserConfigurationException, TransformerException, SAXException, IOException { String resultFile = CLASS_DIR + "doc_xpointer_element.out"; String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml"; String xmlFile = XML_DIR + "doc_xpointer_element.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); TransformerFactory.newInstance().newTransformer() .transform(new DOMSource(db.parse(new File(xmlFile))), new StreamResult(fos)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test the XPointer framework with a SAX object. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXPointerPos() throws ParserConfigurationException, TransformerException, SAXException, IOException { String resultFile = CLASS_DIR + "doc_xpointer.out"; String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml"; String xmlFile = XML_DIR + "doc_xpointer.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setXIncludeAware(true); spf.setFeature(FEATURE_NAME, true); // parse the file spf.newSAXParser().parse(new File(xmlFile), new XInclHandler(fos, null)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test if xi:include may reference the doc containing the include if the * parse type is text. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXIncludeLoopPos() throws ParserConfigurationException, TransformerException, SAXException, IOException { String resultFile = CLASS_DIR + "doc_xinc_loops.out"; String goldFile = GOLDEN_DIR + "doc_xinc_loopGold.xml"; String xmlFile = XML_DIR + "doc_xinc_loops.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File(xmlFile)); doc.normalizeDocument(); doc.setXmlStandalone(true); TransformerFactory.newInstance().newTransformer() .transform(new DOMSource(doc), new StreamResult(fos)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } /** * Test if two non nested xi:include elements can include the same document * with an xi:include statement. * * @throws ParserConfigurationException if a DocumentBuilder cannot be * created which satisfies the configuration requested. * @throws SAXException If any parse errors occur. * @throws IOException if the file exists but is a directory rather than * a regular file, does not exist but cannot be created, or cannot * be opened for any other reason. * @throws TransformerException If an unrecoverable error occurs * during the course of the transformation. */ @Test(groups = {"readWriteLocalFiles"}) public void testXIncludeNestedPos() throws ParserConfigurationException, TransformerException, SAXException, IOException { String resultFile = CLASS_DIR + "schedule.out"; String goldFile = GOLDEN_DIR + "scheduleGold.xml"; String xmlFile = XML_DIR + "schedule.xml"; try (FileOutputStream fos = new FileOutputStream(resultFile)) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile)); doc.setXmlStandalone(true); TransformerFactory.newInstance().newTransformer() .transform(new DOMSource(doc), new StreamResult(fos)); } assertTrue(compareDocumentWithGold(goldFile, resultFile)); } }