1 /*
   2  * Copyright (c) 1999, 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 
  24 package javax.xml.parsers.ptests;
  25 
  26 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
  27 import static javax.xml.parsers.ptests.ParserTestConst.GOLDEN_DIR;
  28 import static javax.xml.parsers.ptests.ParserTestConst.XML_DIR;
  29 import static jaxp.library.JAXPTestUtilities.USER_DIR;
  30 import static jaxp.library.JAXPTestUtilities.compareWithGold;
  31 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  32 import static org.testng.Assert.assertEquals;
  33 import static org.testng.Assert.assertFalse;
  34 import static org.testng.Assert.assertNotNull;
  35 import static org.testng.Assert.assertNull;
  36 import static org.testng.Assert.assertTrue;
  37 
  38 import java.io.BufferedReader;
  39 import java.io.Closeable;
  40 import java.io.File;
  41 import java.io.FileInputStream;
  42 import java.io.FileNotFoundException;
  43 import java.io.FileReader;
  44 
  45 import javax.xml.parsers.DocumentBuilder;
  46 import javax.xml.parsers.DocumentBuilderFactory;
  47 import javax.xml.parsers.FactoryConfigurationError;
  48 import javax.xml.parsers.ParserConfigurationException;
  49 import javax.xml.parsers.SAXParser;
  50 import javax.xml.parsers.SAXParserFactory;
  51 import javax.xml.transform.Transformer;
  52 import javax.xml.transform.TransformerFactory;
  53 import javax.xml.transform.dom.DOMSource;
  54 import javax.xml.transform.sax.SAXResult;
  55 
  56 import jaxp.library.JAXPDataProvider;
  57 
  58 import org.testng.annotations.DataProvider;
  59 import org.testng.annotations.Listeners;
  60 import org.testng.annotations.Test;
  61 import org.w3c.dom.Document;
  62 import org.w3c.dom.Element;
  63 import org.w3c.dom.NodeList;
  64 import org.xml.sax.InputSource;
  65 import org.xml.sax.SAXException;
  66 import org.xml.sax.helpers.DefaultHandler;
  67 
  68 /**
  69  * @bug 8080907
  70  * This checks the methods of DocumentBuilderFactoryImpl.
  71  */
  72 @Listeners({jaxp.library.FilePolicy.class})
  73 public class DocumentBuilderFactoryTest {
  74     /**
  75      * DocumentBuilderFactory implementation class name.
  76      */
  77     private static final String DOCUMENT_BUILDER_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl";
  78 
  79     /**
  80      * Provide valid DocumentBuilderFactory instantiation parameters.
  81      *
  82      * @return a data provider contains DocumentBuilderFactory instantiation parameters.
  83      */
  84     @DataProvider(name = "parameters")
  85     public Object[][] getValidateParameters() {
  86         return new Object[][] { { DOCUMENT_BUILDER_FACTORY_CLASSNAME, null }, { DOCUMENT_BUILDER_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
  87     }
  88 
  89     /**
  90      * Test for DocumentBuilderFactory.newInstance(java.lang.String
  91      * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
  92      * points to correct implementation of
  93      * javax.xml.parsers.DocumentBuilderFactory , should return newInstance of
  94      * DocumentBuilderFactory
  95      *
  96      * @param factoryClassName
  97      * @param classLoader
  98      * @throws ParserConfigurationException
  99      */
 100     @Test(dataProvider = "parameters")
 101     public void testNewInstance(String factoryClassName, ClassLoader classLoader) throws ParserConfigurationException {
 102         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(factoryClassName, classLoader);
 103         DocumentBuilder builder = dbf.newDocumentBuilder();
 104         assertNotNull(builder);
 105     }
 106 
 107     /**
 108      * test for DocumentBuilderFactory.newInstance(java.lang.String
 109      * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName is
 110      * null , should throw FactoryConfigurationError
 111      *
 112      * @param factoryClassName
 113      * @param classLoader
 114      */
 115     @Test(expectedExceptions = FactoryConfigurationError.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
 116     public void testNewInstanceNeg(String factoryClassName, ClassLoader classLoader) {
 117         DocumentBuilderFactory.newInstance(factoryClassName, classLoader);
 118     }
 119 
 120     /**
 121      * Test the default functionality of schema support method.
 122      * @throws Exception If any errors occur.
 123      */
 124     @Test
 125     public void testCheckSchemaSupport1() throws Exception {
 126         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 127         dbf.setValidating(true);
 128         dbf.setNamespaceAware(true);
 129         dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
 130                 W3C_XML_SCHEMA_NS_URI);
 131         MyErrorHandler eh = MyErrorHandler.newInstance();
 132         DocumentBuilder db = dbf.newDocumentBuilder();
 133         db.setErrorHandler(eh);
 134         db.parse(new File(XML_DIR, "test.xml"));
 135         assertFalse(eh.isErrorOccured());
 136     }
 137 
 138     @DataProvider(name = "schema-source")
 139     public Object[][] getSchemaSource() throws FileNotFoundException {
 140         return new Object[][] {
 141                 { new FileInputStream(new File(XML_DIR, "test.xsd")) },
 142                 { new InputSource(filenameToURL(XML_DIR + "test.xsd")) } };
 143     }
 144 
 145     /**
 146      * Test the default functionality of schema support method. In
 147      * this case the schema source property is set.
 148      * @throws Exception If any errors occur.
 149      */
 150     @Test(dataProvider = "schema-source")
 151     public void testCheckSchemaSupport2(Object schemaSource) throws Exception {
 152         try {
 153             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 154             dbf.setValidating(true);
 155             dbf.setNamespaceAware(true);
 156             dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
 157                     W3C_XML_SCHEMA_NS_URI);
 158             dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaSource);
 159             MyErrorHandler eh = MyErrorHandler.newInstance();
 160             DocumentBuilder db = dbf.newDocumentBuilder();
 161             db.setErrorHandler(eh);
 162             db.parse(new File(XML_DIR, "test1.xml"));
 163             assertFalse(eh.isErrorOccured());
 164         } finally {
 165             if (schemaSource instanceof Closeable) {
 166                 ((Closeable) schemaSource).close();
 167             }
 168         }
 169 
 170     }
 171 
 172     /**
 173      * Test the default functionality of schema support method. In
 174      * this case the schema source property is set.
 175      * @throws Exception If any errors occur.
 176      */
 177     @Test(dataProvider = "schema-source")
 178     public void testCheckSchemaSupport3(Object schemaSource) throws Exception {
 179         try {
 180             SAXParserFactory spf = SAXParserFactory.newInstance();
 181             spf.setValidating(true);
 182             spf.setNamespaceAware(true);
 183             SAXParser sp = spf.newSAXParser();
 184             sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
 185                     W3C_XML_SCHEMA_NS_URI);
 186             sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaSource);
 187             DefaultHandler dh = new DefaultHandler();
 188             // Not expect any unrecoverable error here.
 189             sp.parse(new File(XML_DIR, "test1.xml"), dh);
 190         } finally {
 191             if (schemaSource instanceof Closeable) {
 192                 ((Closeable) schemaSource).close();
 193             }
 194         }
 195     }
 196 
 197     /**
 198      * Test the default functionality of newInstance method. To test
 199      * the isCoalescing method and setCoalescing This checks to see if the CDATA
 200      * and text nodes got combined In that case it will print "<xml>This
 201      * is not parsed</xml> yet".
 202      * @throws Exception If any errors occur.
 203      */
 204     @Test
 205     public void testCheckDocumentBuilderFactory02() throws Exception {
 206         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 207         dbf.setCoalescing(true);
 208         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 209         Document doc = docBuilder.parse(new File(XML_DIR, "DocumentBuilderFactory01.xml"));
 210         Element e = (Element) doc.getElementsByTagName("html").item(0);
 211         NodeList nl = e.getChildNodes();
 212         assertEquals(nl.getLength(), 1);
 213     }
 214 
 215     /**
 216      * Test the isIgnoringComments. By default it is false.
 217      */
 218     @Test
 219     public void testCheckDocumentBuilderFactory03() {
 220         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 221         assertFalse(dbf.isIgnoringComments());
 222     }
 223 
 224     /**
 225      * Test the isValidating. By default it is false, set it to true and then
 226      * use a document which is not valid. It should throw a warning or
 227      * an error at least. The test passes in case retval 0 is set in the error
 228      * method .
 229      * @throws Exception If any errors occur.
 230      */
 231     @Test
 232     public void testCheckDocumentBuilderFactory04() throws Exception {
 233         MyErrorHandler eh = MyErrorHandler.newInstance();
 234         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 235         dbf.setValidating(true);
 236         DocumentBuilder db = dbf.newDocumentBuilder();
 237         db.setErrorHandler(eh);
 238         db.parse(new File(XML_DIR, "DocumentBuilderFactory05.xml"));
 239         assertTrue(eh.isErrorOccured());
 240     }
 241 
 242     /**
 243      * Test the setValidating. By default it is false, use a
 244      * document which is not valid. It should not throw a warning or an error.
 245      * The test passes in case the return value equals 1.
 246      * @throws Exception If any errors occur.
 247      */
 248     @Test
 249     public void testCheckDocumentBuilderFactory16() throws Exception {
 250         MyErrorHandler eh = MyErrorHandler.newInstance();
 251         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 252         DocumentBuilder db = dbf.newDocumentBuilder();
 253         db.setErrorHandler(eh);
 254         db.parse(new File(XML_DIR, "DocumentBuilderFactory05.xml"));
 255         assertFalse(eh.isErrorOccured());
 256     }
 257 
 258     /**
 259      * Test the setValidating. By default it is false, use a
 260      * document which is valid. It should not throw a warning or an error. The
 261      * test passes in case the return value equals 1.
 262      * @throws Exception If any errors occur.
 263      */
 264     @Test
 265     public void testCheckDocumentBuilderFactory17() throws Exception {
 266         MyErrorHandler eh = MyErrorHandler.newInstance();
 267         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 268         DocumentBuilder db = dbf.newDocumentBuilder();
 269         db.setErrorHandler(eh);
 270         db.parse(new File(XML_DIR, "DocumentBuilderFactory04.xml"));
 271         assertFalse(eh.isErrorOccured());
 272     }
 273 
 274     /**
 275      * Test the isExpandEntityReferences. By default it is true.
 276      * @throws Exception If any errors occur.
 277      */
 278     @Test
 279     public void testCheckDocumentBuilderFactory05() throws Exception {
 280         try(FileInputStream fis = new FileInputStream(new File(
 281                 XML_DIR, "DocumentBuilderFactory02.xml"))) {
 282             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 283             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 284             Document doc = docBuilder.parse(fis);
 285             Element e = (Element) doc.getElementsByTagName("title").item(0);
 286             NodeList nl = e.getChildNodes();
 287             assertTrue(dbf.isExpandEntityReferences());
 288             assertEquals(nl.item(0).getNodeValue().trim().charAt(0), 'W');
 289         }
 290     }
 291 
 292     /**
 293      * Test the default functionality of setValidating method. The
 294      * XML file has a DTD which has namespaces defined. The parser takes care to
 295      * check if the namespaces using elements and defined attributes are there
 296      * or not.
 297      * @throws Exception If any errors occur.
 298      */
 299     @Test
 300     public void testCheckDocumentBuilderFactory06() throws Exception {
 301         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 302         dbf.setValidating(true);
 303         DocumentBuilder db = dbf.newDocumentBuilder();
 304         MyErrorHandler eh = MyErrorHandler.newInstance();
 305         db.setErrorHandler(eh);
 306         Document doc = db.parse(new File(XML_DIR, "DocumentBuilderFactory04.xml"));
 307         assertTrue(doc instanceof Document);
 308         assertFalse(eh.isErrorOccured());
 309     }
 310 
 311     /**
 312      * Test the setExpandEntityReferences.
 313      * @throws Exception If any errors occur.
 314      */
 315     @Test
 316     public void testCheckDocumentBuilderFactory07() throws Exception {
 317         try (FileInputStream fis = new FileInputStream(new File(
 318                 XML_DIR, "DocumentBuilderFactory02.xml"))) {
 319             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 320             dbf.setExpandEntityReferences(true);
 321             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 322             Document doc = docBuilder.parse(fis);
 323             Element e = (Element) doc.getElementsByTagName("title").item(0);
 324             NodeList nl = e.getChildNodes();
 325             assertTrue(dbf.isExpandEntityReferences());
 326             assertEquals(nl.item(0).getNodeValue().trim().charAt(0), 'W');
 327         }
 328     }
 329 
 330     /**
 331      * Test the setExpandEntityReferences.
 332      * @throws Exception If any errors occur.
 333      */
 334     @Test
 335     public void testCheckDocumentBuilderFactory08() throws Exception {
 336         try (FileInputStream fis = new FileInputStream(new File(
 337                 XML_DIR, "DocumentBuilderFactory02.xml"))) {
 338             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 339             dbf.setExpandEntityReferences(false);
 340             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 341             Document doc = docBuilder.parse(fis);
 342             Element e = (Element) doc.getElementsByTagName("title").item(0);
 343             NodeList nl = e.getChildNodes();
 344             assertNull(nl.item(0).getNodeValue());
 345         }
 346     }
 347 
 348     /**
 349      * Test the setIgnoringComments. By default it is set to false.
 350      * explicitly setting it to false, it recognizes the comment which is in
 351      * Element Node Hence the Element's child node is not null.
 352      * @throws Exception If any errors occur.
 353      */
 354     @Test
 355     public void testCheckDocumentBuilderFactory09() throws Exception {
 356         try (FileInputStream fis = new FileInputStream(new File(
 357                 XML_DIR, "DocumentBuilderFactory07.xml"))) {
 358             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 359             dbf.setIgnoringComments(false);
 360             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 361             Document doc = docBuilder.parse(fis);
 362             Element e = (Element) doc.getElementsByTagName("body").item(0);
 363             NodeList nl = e.getChildNodes();
 364             assertNotNull(nl.item(0).getNodeValue());
 365         }
 366     }
 367 
 368     /**
 369      * This tests for the parse(InputSource).
 370      * @throws Exception If any errors occur.
 371      */
 372     @Test
 373     public void testCheckDocumentBuilderFactory10() throws Exception {
 374         try (BufferedReader br = new BufferedReader(new FileReader(new File(
 375                 XML_DIR, "DocumentBuilderFactory07.xml")))) {
 376             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 377             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 378             Document doc = docBuilder.parse(new InputSource(br));
 379             assertNotNull(doc);
 380         }
 381     }
 382 
 383     /**
 384      * This tests for the parse InputStream with SystemID as a second parameter.
 385      * @throws Exception If any errors occur.
 386      */
 387     @Test
 388     public void testCheckDocumentBuilderFactory11() throws Exception {
 389         try (FileInputStream fis = new FileInputStream(new File(
 390                 XML_DIR, "dbf10import.xsl"))) {
 391             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 392             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 393             Document doc = docBuilder.parse(fis, new File(XML_DIR).toURI()
 394                     .toASCIIString());
 395             assertNotNull(doc);
 396         }
 397     }
 398 
 399     /**
 400      * This tests for the parse InputStream with empty SystemID as a second
 401      * parameter.
 402      * @throws Exception If any errors occur.
 403      */
 404     @Test
 405     public void testCheckDocumentBuilderFactory12() throws Exception {
 406         try (FileInputStream fis = new FileInputStream(new File(
 407                 XML_DIR, "dbf10import.xsl"))) {
 408             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 409             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 410             Document doc = docBuilder.parse(fis, " ");
 411             assertNotNull(doc);
 412         }
 413     }
 414 
 415     /**
 416      * This tests for the parse(uri).
 417      * @throws Exception If any errors occur.
 418      */
 419     @Test
 420     public void testCheckDocumentBuilderFactory13() throws Exception {
 421         // Accesing default working directory.
 422         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 423         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 424         Document doc = docBuilder.parse(new File(XML_DIR + "dbf10import.xsl")
 425                 .toURI().toASCIIString());
 426         assertNotNull(doc);
 427     }
 428 
 429     /**
 430      * This tests for the parse(uri) with empty string as parameter should
 431      * throw Sax Exception.
 432      * @throws Exception If any errors occur.
 433      */
 434     @Test(expectedExceptions = SAXException.class)
 435     public void testCheckDocumentBuilderFactory14() throws Exception {
 436         // Accesing default working directory.
 437         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 438         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 439         docBuilder.parse("");
 440     }
 441 
 442     /**
 443      * This tests for the parse (uri) with null uri as parameter should throw
 444      * IllegalArgumentException.
 445      * @throws Exception If any errors occur.
 446      *
 447      */
 448     @Test(expectedExceptions = IllegalArgumentException.class)
 449     public void testCheckDocumentBuilderFactory15() throws Exception {
 450         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 451         DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 452         String uri = null;
 453         docBuilder.parse(uri);
 454     }
 455 
 456     /**
 457      * Test the setIgnoringComments. By default it is set to false,
 458      * setting this to true, It does not recognize the comment, Here the
 459      * nodelist has a length 0 because the ignoring comments is true.
 460      * @throws Exception If any errors occur.
 461      */
 462     @Test
 463     public void testCheckIgnoringComments() throws Exception {
 464         try (FileInputStream fis = new FileInputStream(new File(
 465                 XML_DIR, "DocumentBuilderFactory08.xml"))) {
 466             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 467             dbf.setIgnoringComments(true);
 468             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 469             Document doc = docBuilder.parse(fis);
 470             Element e = (Element) doc.getElementsByTagName("body").item(0);
 471             NodeList nl = e.getChildNodes();
 472             assertEquals(nl.getLength(), 0);
 473         }
 474     }
 475 
 476     /**
 477      * Test the default behaviour of setIgnoringComments. By default
 478      * it is set to false, this is similar to case 9 but not setIgnoringComments
 479      * explicitly, it does not recognize the comment.
 480      * @throws Exception If any errors occur.
 481      */
 482     @Test
 483     public void testCheckIgnoringComments1() throws Exception {
 484         try (FileInputStream fis = new FileInputStream(new File(
 485                 XML_DIR, "DocumentBuilderFactory07.xml"))) {
 486             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 487             DocumentBuilder docBuilder = dbf.newDocumentBuilder();
 488             Document doc = docBuilder.parse(fis);
 489             Element e = (Element) doc.getElementsByTagName("body").item(0);
 490             NodeList nl = e.getChildNodes();
 491             assertFalse(dbf.isIgnoringComments());
 492             assertNotNull(nl.item(0).getNodeValue());
 493         }
 494     }
 495 
 496     /**
 497      * Test for the isIgnoringElementContentWhitespace and the
 498      * setIgnoringElementContentWhitespace. The xml file has all kinds of
 499      * whitespace,tab and newline characters, it uses the MyNSContentHandler
 500      * which does not invoke the characters callback when this
 501      * setIgnoringElementContentWhitespace is set to true.
 502      * @throws Exception If any errors occur.
 503      */
 504     @Test
 505     public void testCheckElementContentWhitespace() throws Exception {
 506         String goldFile = GOLDEN_DIR + "dbfactory02GF.out";
 507         String outputFile = USER_DIR + "dbfactory02.out";
 508         MyErrorHandler eh = MyErrorHandler.newInstance();
 509         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 510         dbf.setValidating(true);
 511         assertFalse(dbf.isIgnoringElementContentWhitespace());
 512         dbf.setIgnoringElementContentWhitespace(true);
 513         DocumentBuilder db = dbf.newDocumentBuilder();
 514         db.setErrorHandler(eh);
 515         Document doc = db.parse(new File(XML_DIR, "DocumentBuilderFactory06.xml"));
 516         assertFalse(eh.isErrorOccured());
 517         DOMSource domSource = new DOMSource(doc);
 518         TransformerFactory tfactory = TransformerFactory.newInstance();
 519         Transformer transformer = tfactory.newTransformer();
 520         SAXResult saxResult = new SAXResult();
 521         try(MyCHandler handler = MyCHandler.newInstance(new File(outputFile))) {
 522             saxResult.setHandler(handler);
 523             transformer.transform(domSource, saxResult);
 524         }
 525         assertTrue(compareWithGold(goldFile, outputFile));
 526     }
 527 }