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