1 /*
   2  * Copyright (c) 2003, 2016, 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 javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING;
  26 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
  27 import static jaxp.library.JAXPTestUtilities.USER_DIR;
  28 import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold;
  29 import static org.testng.Assert.assertFalse;
  30 import static org.testng.Assert.assertTrue;
  31 import static test.auctionportal.HiBidConstants.GOLDEN_DIR;
  32 import static test.auctionportal.HiBidConstants.JAXP_SCHEMA_LANGUAGE;
  33 import static test.auctionportal.HiBidConstants.JAXP_SCHEMA_SOURCE;
  34 import static test.auctionportal.HiBidConstants.SP_ENTITY_EXPANSION_LIMIT;
  35 import static test.auctionportal.HiBidConstants.SP_MAX_OCCUR_LIMIT;
  36 import static test.auctionportal.HiBidConstants.XML_DIR;
  37 
  38 import java.io.File;
  39 import java.io.FileInputStream;
  40 import java.io.FileOutputStream;
  41 import java.io.InputStream;
  42 
  43 import javax.xml.parsers.DocumentBuilder;
  44 import javax.xml.parsers.DocumentBuilderFactory;
  45 import javax.xml.parsers.SAXParser;
  46 import javax.xml.parsers.SAXParserFactory;
  47 import javax.xml.transform.TransformerFactory;
  48 import javax.xml.transform.dom.DOMSource;
  49 import javax.xml.transform.stream.StreamResult;
  50 
  51 import org.testng.annotations.Listeners;
  52 import org.testng.annotations.Test;
  53 import org.w3c.dom.Document;
  54 import org.xml.sax.SAXParseException;
  55 
  56 /**
  57  * This is a test class for the Auction portal HiBid.com.
  58  */
  59 @Listeners({jaxp.library.FilePolicy.class})
  60 public class AuctionItemRepository {
  61     /**
  62      * XML file for parsing.
  63      */
  64     private final static String ENTITY_XML = XML_DIR + "entity.xml";
  65 
  66     /**
  67      * Feature name.
  68      */
  69     private final static String FEATURE_NAME = "http://xml.org/sax/features/namespace-prefixes";
  70 
  71     /**
  72      * Setting the EntityExpansion Limit to 128000 and checks if the XML
  73      * document that has more than two levels of entity expansion is parsed or
  74      * not. Previous system property was changed to jdk.xml.entityExpansionLimit
  75      * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html.
  76      *
  77      * @throws Exception If any errors occur.
  78      */
  79     @Test
  80     public void testEntityExpansionSAXPos() throws Exception {
  81         SAXParserFactory factory = SAXParserFactory.newInstance();
  82         // Secure processing will limit XML processing to conform to
  83         // implementation limits.
  84         factory.setFeature(FEATURE_SECURE_PROCESSING, true);
  85         // Set entityExpansionLimit as 2 should expect fatalError
  86         System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(128000));
  87         SAXParser parser = factory.newSAXParser();
  88 
  89         MyErrorHandler fatalHandler = new MyErrorHandler();
  90         parser.parse(new File(ENTITY_XML), fatalHandler);
  91         assertFalse(fatalHandler.isAnyError());
  92     }
  93     /**
  94      * Setting the EntityExpansion Limit to 2 and checks if the XML
  95      * document that has more than two levels of entity expansion is parsed or
  96      * not. Previous system property was changed to jdk.xml.entityExpansionLimit
  97      * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html.
  98      *
  99      * @throws Exception If any errors occur.
 100      */
 101     @Test(expectedExceptions = SAXParseException.class)
 102     public void testEntityExpansionSAXNeg() throws Exception {
 103         SAXParserFactory factory = SAXParserFactory.newInstance();
 104         // Secure processing will limit XML processing to conform to
 105         // implementation limits.
 106         factory.setFeature(FEATURE_SECURE_PROCESSING, true);
 107         // Set entityExpansionLimit as 2 should expect SAXParseException.
 108         System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2));
 109 
 110         SAXParser parser = factory.newSAXParser();
 111         MyErrorHandler fatalHandler = new MyErrorHandler();
 112         parser.parse(new File(ENTITY_XML), fatalHandler);
 113     }
 114 
 115     /**
 116      * Testing set MaxOccursLimit to 10000 in the secure processing enabled for
 117      * SAXParserFactory.
 118      *
 119      * @throws Exception If any errors occur.
 120      */
 121     @Test
 122     public void testMaxOccurLimitPos() throws Exception {
 123         String schema_file = XML_DIR + "toys.xsd";
 124         String xml_file = XML_DIR + "toys.xml";
 125         SAXParserFactory factory = SAXParserFactory.newInstance();
 126         factory.setValidating(true);
 127         factory.setFeature(FEATURE_SECURE_PROCESSING, true);
 128         System.setProperty(SP_MAX_OCCUR_LIMIT, String.valueOf(10000));
 129         SAXParser parser = factory.newSAXParser();
 130         parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
 131         parser.setProperty(JAXP_SCHEMA_SOURCE, new File(schema_file));
 132         try (InputStream is = new FileInputStream(xml_file)) {
 133             MyErrorHandler eh = new MyErrorHandler();
 134             parser.parse(is, eh);
 135             assertFalse(eh.isAnyError());
 136         }
 137     }
 138 
 139     /**
 140      * Use a DocumentBuilder to create a DOM object and see if Secure Processing
 141      * feature affects the entity expansion.
 142      *
 143      * @throws Exception If any errors occur.
 144      */
 145     @Test
 146     public void testEntityExpansionDOMPos() throws Exception  {
 147         DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 148         dfactory.setFeature(FEATURE_SECURE_PROCESSING, true);
 149         System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(10000));
 150         DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
 151         MyErrorHandler eh = new MyErrorHandler();
 152         dBuilder.setErrorHandler(eh);
 153         dBuilder.parse(ENTITY_XML);
 154         assertFalse(eh.isAnyError());
 155     }
 156 
 157     /**
 158      * Use a DocumentBuilder to create a DOM object and see how does the Secure
 159      * Processing feature and entityExpansionLimit value affects output.
 160      * Negative test that when entityExpansionLimit is too small.
 161      *
 162      * @throws Exception If any errors occur.
 163      */
 164     @Test(expectedExceptions = SAXParseException.class)
 165     public void testEntityExpansionDOMNeg() throws Exception {
 166         DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 167         dfactory.setFeature(FEATURE_SECURE_PROCESSING, true);
 168         System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2));
 169         DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
 170         MyErrorHandler eh = new MyErrorHandler();
 171         dBuilder.setErrorHandler(eh);
 172         dBuilder.parse(ENTITY_XML);
 173     }
 174 
 175     /**
 176      * Test xi:include with a SAXParserFactory.
 177      *
 178      * @throws Exception If any errors occur.
 179      */
 180     @Test(groups = {"readWriteLocalFiles"})
 181     public void testXIncludeSAXPos() throws Exception {
 182         String resultFile = USER_DIR + "doc_xinclude.out";
 183         String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml";
 184         String xmlFile = XML_DIR + "doc_xinclude.xml";
 185 
 186         try(FileOutputStream fos = new FileOutputStream(resultFile)) {
 187             XInclHandler xh = new XInclHandler(fos, null);
 188             SAXParserFactory spf = SAXParserFactory.newInstance();
 189             spf.setNamespaceAware(true);
 190             spf.setXIncludeAware(true);
 191             spf.setFeature(FEATURE_NAME, true);
 192             spf.newSAXParser().parse(new File(xmlFile), xh);
 193         }
 194         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 195     }
 196 
 197     /**
 198      * Test the simple case of including a document using xi:include using a
 199      * DocumentBuilder.
 200      *
 201      * @throws Exception If any errors occur.
 202      */
 203     @Test(groups = {"readWriteLocalFiles"})
 204     public void testXIncludeDOMPos() throws Exception {
 205         String resultFile = USER_DIR + "doc_xincludeDOM.out";
 206         String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml";
 207         String xmlFile = XML_DIR + "doc_xinclude.xml";
 208         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 209             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 210             dbf.setXIncludeAware(true);
 211             dbf.setNamespaceAware(true);
 212             Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
 213             doc.setXmlStandalone(true);
 214             TransformerFactory.newInstance().newTransformer().
 215                     transform(new DOMSource(doc), new StreamResult(fos));
 216         }
 217         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 218     }
 219 
 220     /**
 221      * Test the simple case of including a document using xi:include within a
 222      * xi:fallback using a DocumentBuilder.
 223      *
 224      * @throws Exception If any errors occur.
 225      */
 226     @Test(groups = {"readWriteLocalFiles"})
 227     public void testXIncludeFallbackDOMPos() throws Exception {
 228         String resultFile = USER_DIR + "doc_fallbackDOM.out";
 229         String goldFile = GOLDEN_DIR + "doc_fallbackGold.xml";
 230         String xmlFile = XML_DIR + "doc_fallback.xml";
 231         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 232             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 233             dbf.setXIncludeAware(true);
 234             dbf.setNamespaceAware(true);
 235 
 236             Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
 237             doc.setXmlStandalone(true);
 238             TransformerFactory.newInstance().newTransformer()
 239                     .transform(new DOMSource(doc), new StreamResult(fos));
 240         }
 241         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 242     }
 243 
 244     /**
 245      * Test for xi:fallback where the fall back text is parsed as text. This
 246      * test uses a nested xi:include for the fallback test.
 247      *
 248      * @throws Exception If any errors occur.
 249      */
 250     @Test(groups = {"readWriteLocalFiles"})
 251     public void testXIncludeFallbackTextPos() throws Exception {
 252         String resultFile = USER_DIR + "doc_fallback_text.out";
 253         String goldFile = GOLDEN_DIR + "doc_fallback_textGold.xml";
 254         String xmlFile = XML_DIR + "doc_fallback_text.xml";
 255         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 256             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 257             dbf.setXIncludeAware(true);
 258             dbf.setNamespaceAware(true);
 259 
 260             Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
 261             doc.setXmlStandalone(true);
 262             TransformerFactory.newInstance().newTransformer()
 263                     .transform(new DOMSource(doc), new StreamResult(fos));
 264         }
 265         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 266     }
 267 
 268     /**
 269      * Test the XPointer element() framework with XInclude.
 270      *
 271      * @throws Exception If any errors occur.
 272      */
 273     @Test(groups = {"readWriteLocalFiles"})
 274     public void testXpointerElementPos() throws Exception {
 275         String resultFile = USER_DIR + "doc_xpointer_element.out";
 276         String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml";
 277         String xmlFile = XML_DIR + "doc_xpointer_element.xml";
 278         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 279             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 280             dbf.setXIncludeAware(true);
 281             dbf.setNamespaceAware(true);
 282 
 283             DocumentBuilder db = dbf.newDocumentBuilder();
 284 
 285             TransformerFactory.newInstance().newTransformer()
 286                     .transform(new DOMSource(db.parse(new File(xmlFile))),
 287                             new StreamResult(fos));
 288         }
 289         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 290     }
 291 
 292     /**
 293      * Test the XPointer framework with a SAX object.
 294      *
 295      * @throws Exception If any errors occur.
 296      */
 297     @Test(groups = {"readWriteLocalFiles"})
 298     public void testXPointerPos() throws Exception {
 299         String resultFile = USER_DIR + "doc_xpointer.out";
 300         String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml";
 301         String xmlFile = XML_DIR + "doc_xpointer.xml";
 302 
 303         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 304             SAXParserFactory spf = SAXParserFactory.newInstance();
 305             spf.setNamespaceAware(true);
 306             spf.setXIncludeAware(true);
 307             spf.setFeature(FEATURE_NAME, true);
 308             // parse the file
 309             spf.newSAXParser().parse(new File(xmlFile), new XInclHandler(fos, null));
 310         }
 311         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 312     }
 313 
 314     /**
 315      * Test if xi:include may reference the doc containing the include if the
 316      * parse type is text.
 317      *
 318      * @throws Exception If any errors occur.
 319      */
 320     @Test(groups = {"readWriteLocalFiles"})
 321     public void testXIncludeLoopPos() throws Exception {
 322         String resultFile = USER_DIR + "doc_xinc_loops.out";
 323         String goldFile = GOLDEN_DIR + "doc_xinc_loopGold.xml";
 324         String xmlFile = XML_DIR + "doc_xinc_loops.xml";
 325 
 326         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 327             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 328             dbf.setXIncludeAware(true);
 329             dbf.setNamespaceAware(true);
 330             DocumentBuilder db = dbf.newDocumentBuilder();
 331             Document doc = db.parse(new File(xmlFile));
 332             doc.normalizeDocument();
 333             doc.setXmlStandalone(true);
 334 
 335             TransformerFactory.newInstance().newTransformer()
 336                     .transform(new DOMSource(doc), new StreamResult(fos));
 337         }
 338         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 339     }
 340 
 341     /**
 342      * Test if two non nested xi:include elements can include the same document
 343      * with an xi:include statement.
 344      *
 345      * @throws Exception If any errors occur.
 346      */
 347     @Test(groups = {"readWriteLocalFiles"})
 348     public void testXIncludeNestedPos() throws Exception {
 349         String resultFile = USER_DIR + "schedule.out";
 350         String goldFile = GOLDEN_DIR + "scheduleGold.xml";
 351         String xmlFile = XML_DIR + "schedule.xml";
 352 
 353         try (FileOutputStream fos = new FileOutputStream(resultFile)) {
 354             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 355             dbf.setXIncludeAware(true);
 356             dbf.setNamespaceAware(true);
 357 
 358             Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
 359             doc.setXmlStandalone(true);
 360             TransformerFactory.newInstance().newTransformer()
 361                     .transform(new DOMSource(doc), new StreamResult(fos));
 362         }
 363         assertTrue(compareDocumentWithGold(goldFile, resultFile));
 364     }
 365 }