1 /*
   2  * Copyright (c) 2000, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.xml.parsers;
  27 
  28 import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
  29 import javax.xml.validation.Schema;
  30 
  31 /**
  32  * Defines a factory API that enables applications to obtain a
  33  * parser that produces DOM object trees from XML documents.
  34  *
  35  * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
  36  * @author <a href="mailto:Neeraj.Bajaj@sun.com">Neeraj Bajaj</a>
  37  *
  38  * @since 1.4
  39  */
  40 
  41 public abstract class DocumentBuilderFactory {
  42 
  43     private boolean validating = false;
  44     private boolean namespaceAware = false;
  45     private boolean whitespace = false;
  46     private boolean expandEntityRef = true;
  47     private boolean ignoreComments = false;
  48     private boolean coalescing = false;
  49 
  50     /**
  51      * Protected constructor to prevent instantiation.
  52      * Use {@link #newInstance()}.
  53      */
  54     protected DocumentBuilderFactory () {
  55     }
  56 
  57     /**
  58      * Creates a new instance of the {@code DocumentBuilderFactory} builtin
  59      * system-default implementation.
  60      *
  61      * @return A new instance of the {@code DocumentBuilderFactory} builtin
  62      *         system-default implementation.
  63      *
  64      * @since 9
  65      */
  66     public static DocumentBuilderFactory newDefaultInstance() {
  67         return new DocumentBuilderFactoryImpl();
  68     }
  69 
  70     /**
  71      * Obtain a new instance of a
  72      * {@code DocumentBuilderFactory}. This static method creates
  73      * a new factory instance.
  74      * This method uses the following ordered lookup procedure to determine
  75      * the {@code DocumentBuilderFactory} implementation class to
  76      * load:
  77      * <ul>
  78      * <li>
  79      * Use the {@code javax.xml.parsers.DocumentBuilderFactory} system
  80      * property.
  81      * </li>
  82      * <li>
  83      * <p>
  84      * Use the configuration file "jaxp.properties". The file is in standard
  85      * {@link java.util.Properties} format and typically located in the
  86      * {@code conf} directory of the Java installation. It contains the fully qualified
  87      * name of the implementation class with the key being the system property
  88      * defined above.
  89      * <p>
  90      * The jaxp.properties file is read only once by the JAXP implementation
  91      * and its values are then cached for future use.  If the file does not exist
  92      * when the first attempt is made to read from it, no further attempts are
  93      * made to check for its existence.  It is not possible to change the value
  94      * of any property in jaxp.properties after it has been read for the first time.
  95      * </li>
  96      * <li>
  97      * <p>
  98      * Use the service-provider loading facility, defined by the
  99      * {@link java.util.ServiceLoader} class, to attempt to locate and load an
 100      * implementation of the service using the {@linkplain
 101      * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}:
 102      * the service-provider loading facility will use the {@linkplain
 103      * java.lang.Thread#getContextClassLoader() current thread's context class loader}
 104      * to attempt to load the service. If the context class
 105      * loader is null, the {@linkplain
 106      * ClassLoader#getSystemClassLoader() system class loader} will be used.
 107      * </li>
 108      * <li>
 109      * <p>
 110      * Otherwise, the {@linkplain #newDefaultInstance() system-default}
 111      * implementation is returned.
 112      * </li>
 113      * </ul>
 114      *
 115      * <p>
 116      * Once an application has obtained a reference to a
 117      * {@code DocumentBuilderFactory} it can use the factory to
 118      * configure and obtain parser instances.
 119      *
 120      *
 121      * <h2>Tip for Trouble-shooting</h2>
 122      * <p>
 123      * Setting the {@code jaxp.debug} system property will cause
 124      * this method to print a lot of debug messages
 125      * to {@code System.err} about what it is doing and where it is looking at.
 126      *
 127      * <p>
 128      * If you have problems loading {@link DocumentBuilder}s, try:
 129      * <pre>
 130      * java -Djaxp.debug=1 YourProgram ....
 131      * </pre>
 132      *
 133      * @return New instance of a {@code DocumentBuilderFactory}
 134      *
 135      * @throws FactoryConfigurationError in case of {@linkplain
 136      * java.util.ServiceConfigurationError service configuration error} or if
 137      * the implementation is not available or cannot be instantiated.
 138      */
 139     public static DocumentBuilderFactory newInstance() {
 140         return FactoryFinder.find(
 141                 /* The default property name according to the JAXP spec */
 142                 DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory"
 143                 /* The fallback implementation class name */
 144                 "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
 145     }
 146 
 147     /**
 148      * Obtain a new instance of a {@code DocumentBuilderFactory} from class name.
 149      * This function is useful when there are multiple providers in the classpath.
 150      * It gives more control to the application as it can specify which provider
 151      * should be loaded.
 152      *
 153      * <p>Once an application has obtained a reference to a {@code DocumentBuilderFactory}
 154      * it can use the factory to configure and obtain parser instances.
 155      *
 156      *
 157      * <h2>Tip for Trouble-shooting</h2>
 158      * <p>Setting the {@code jaxp.debug} system property will cause
 159      * this method to print a lot of debug messages
 160      * to {@code System.err} about what it is doing and where it is looking at.
 161      *
 162      * <p> If you have problems try:
 163      * <pre>
 164      * java -Djaxp.debug=1 YourProgram ....
 165      * </pre>
 166      *
 167      * @param factoryClassName fully qualified factory class name that provides
 168      *        implementation of {@code javax.xml.parsers.DocumentBuilderFactory}.
 169      *
 170      * @param classLoader {@code ClassLoader} used to load the factory class. If {@code null}
 171      *                     current {@code Thread}'s context classLoader is used to load the factory class.
 172      *
 173      * @return New instance of a {@code DocumentBuilderFactory}
 174      *
 175      * @throws FactoryConfigurationError if {@code factoryClassName} is {@code null}, or
 176      *                                   the factory class cannot be loaded, instantiated.
 177      *
 178      * @see #newInstance()
 179      *
 180      * @since 1.6
 181      */
 182     public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){
 183             //do not fallback if given classloader can't find the class, throw exception
 184             return FactoryFinder.newInstance(DocumentBuilderFactory.class,
 185                         factoryClassName, classLoader, false);
 186     }
 187 
 188     /**
 189      * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder}
 190      * using the currently configured parameters.
 191      *
 192      * @return A new instance of a DocumentBuilder.
 193      *
 194      * @throws ParserConfigurationException if a DocumentBuilder
 195      *   cannot be created which satisfies the configuration requested.
 196      */
 197 
 198     public abstract DocumentBuilder newDocumentBuilder()
 199         throws ParserConfigurationException;
 200 
 201 
 202     /**
 203      * Specifies that the parser produced by this code will
 204      * provide support for XML namespaces. By default the value of this is set
 205      * to {@code false}
 206      *
 207      * @param awareness true if the parser produced will provide support
 208      *                  for XML namespaces; false otherwise.
 209      */
 210 
 211     public void setNamespaceAware(boolean awareness) {
 212         this.namespaceAware = awareness;
 213     }
 214 
 215     /**
 216      * Specifies that the parser produced by this code will
 217      * validate documents as they are parsed. By default the value of this
 218      * is set to {@code false}.
 219      *
 220      * <p>
 221      * Note that "the validation" here means
 222      * <a href="http://www.w3.org/TR/REC-xml#proc-types">a validating
 223      * parser</a> as defined in the XML recommendation.
 224      * In other words, it essentially just controls the DTD validation.
 225      * (except the legacy two properties defined in JAXP 1.2.)
 226      *
 227      * <p>
 228      * To use modern schema languages such as W3C XML Schema or
 229      * RELAX NG instead of DTD, you can configure your parser to be
 230      * a non-validating parser by leaving the {@link #setValidating(boolean)}
 231      * method {@code false}, then use the {@link #setSchema(Schema)}
 232      * method to associate a schema to a parser.
 233      *
 234      * @param validating true if the parser produced will validate documents
 235      *                   as they are parsed; false otherwise.
 236      */
 237 
 238     public void setValidating(boolean validating) {
 239         this.validating = validating;
 240     }
 241 
 242     /**
 243      * Specifies that the parsers created by this  factory must eliminate
 244      * whitespace in element content (sometimes known loosely as
 245      * 'ignorable whitespace') when parsing XML documents (see XML Rec
 246      * 2.10). Note that only whitespace which is directly contained within
 247      * element content that has an element only content model (see XML
 248      * Rec 3.2.1) will be eliminated. Due to reliance on the content model
 249      * this setting requires the parser to be in validating mode. By default
 250      * the value of this is set to {@code false}.
 251      *
 252      * @param whitespace true if the parser created must eliminate whitespace
 253      *                   in the element content when parsing XML documents;
 254      *                   false otherwise.
 255      */
 256 
 257     public void setIgnoringElementContentWhitespace(boolean whitespace) {
 258         this.whitespace = whitespace;
 259     }
 260 
 261     /**
 262      * Specifies that the parser produced by this code will
 263      * expand entity reference nodes. By default the value of this is set to
 264      * {@code true}
 265      *
 266      * @param expandEntityRef true if the parser produced will expand entity
 267      *                        reference nodes; false otherwise.
 268      */
 269 
 270     public void setExpandEntityReferences(boolean expandEntityRef) {
 271         this.expandEntityRef = expandEntityRef;
 272     }
 273 
 274     /**
 275      * Specifies that the parser produced by this code will
 276      * ignore comments. By default the value of this is set to {@code false}.
 277      *
 278      * @param ignoreComments {@code boolean} value to ignore comments during processing
 279      */
 280 
 281     public void setIgnoringComments(boolean ignoreComments) {
 282         this.ignoreComments = ignoreComments;
 283     }
 284 
 285     /**
 286      * Specifies that the parser produced by this code will
 287      * convert CDATA nodes to Text nodes and append it to the
 288      * adjacent (if any) text node. By default the value of this is set to
 289      * {@code false}
 290      *
 291      * @param coalescing  true if the parser produced will convert CDATA nodes
 292      *                    to Text nodes and append it to the adjacent (if any)
 293      *                    text node; false otherwise.
 294      */
 295 
 296     public void setCoalescing(boolean coalescing) {
 297         this.coalescing = coalescing;
 298     }
 299 
 300     /**
 301      * Indicates whether or not the factory is configured to produce
 302      * parsers which are namespace aware.
 303      *
 304      * @return  true if the factory is configured to produce parsers which
 305      *          are namespace aware; false otherwise.
 306      */
 307 
 308     public boolean isNamespaceAware() {
 309         return namespaceAware;
 310     }
 311 
 312     /**
 313      * Indicates whether or not the factory is configured to produce
 314      * parsers which validate the XML content during parse.
 315      *
 316      * @return  true if the factory is configured to produce parsers
 317      *          which validate the XML content during parse; false otherwise.
 318      */
 319 
 320     public boolean isValidating() {
 321         return validating;
 322     }
 323 
 324     /**
 325      * Indicates whether or not the factory is configured to produce
 326      * parsers which ignore ignorable whitespace in element content.
 327      *
 328      * @return  true if the factory is configured to produce parsers
 329      *          which ignore ignorable whitespace in element content;
 330      *          false otherwise.
 331      */
 332 
 333     public boolean isIgnoringElementContentWhitespace() {
 334         return whitespace;
 335     }
 336 
 337     /**
 338      * Indicates whether or not the factory is configured to produce
 339      * parsers which expand entity reference nodes.
 340      *
 341      * @return  true if the factory is configured to produce parsers
 342      *          which expand entity reference nodes; false otherwise.
 343      */
 344 
 345     public boolean isExpandEntityReferences() {
 346         return expandEntityRef;
 347     }
 348 
 349     /**
 350      * Indicates whether or not the factory is configured to produce
 351      * parsers which ignores comments.
 352      *
 353      * @return  true if the factory is configured to produce parsers
 354      *          which ignores comments; false otherwise.
 355      */
 356 
 357     public boolean isIgnoringComments() {
 358         return ignoreComments;
 359     }
 360 
 361     /**
 362      * Indicates whether or not the factory is configured to produce
 363      * parsers which converts CDATA nodes to Text nodes and appends it to
 364      * the adjacent (if any) Text node.
 365      *
 366      * @return  true if the factory is configured to produce parsers
 367      *          which converts CDATA nodes to Text nodes and appends it to
 368      *          the adjacent (if any) Text node; false otherwise.
 369      */
 370 
 371     public boolean isCoalescing() {
 372         return coalescing;
 373     }
 374 
 375     /**
 376      * Allows the user to set specific attributes on the underlying
 377      * implementation.
 378      * <p>
 379      * All implementations that implement JAXP 1.5 or newer are required to
 380      * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and
 381      * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties.
 382      *
 383      * <ul>
 384      *   <li>
 385      *      Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property
 386      *      restricts the access to external DTDs, external Entity References to the
 387      *      protocols specified by the property.
 388      *      If access is denied during parsing due to the restriction of this property,
 389      *      {@link org.xml.sax.SAXException} will be thrown by the parse methods defined by
 390      *      {@link javax.xml.parsers.DocumentBuilder}.
 391      *   </li>
 392      *   <li>
 393      *      Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property
 394      *      restricts the access to external Schema set by the schemaLocation attribute to
 395      *      the protocols specified by the property.  If access is denied during parsing
 396      *      due to the restriction of this property, {@link org.xml.sax.SAXException}
 397      *      will be thrown by the parse methods defined by
 398      *      {@link javax.xml.parsers.DocumentBuilder}.
 399      *   </li>
 400      * </ul>
 401      *
 402      * @param name The name of the attribute.
 403      * @param value The value of the attribute.
 404      *
 405      * @throws IllegalArgumentException thrown if the underlying
 406      *   implementation doesn't recognize the attribute.
 407      */
 408     public abstract void setAttribute(String name, Object value)
 409                 throws IllegalArgumentException;
 410 
 411     /**
 412      * Allows the user to retrieve specific attributes on the underlying
 413      * implementation.
 414      *
 415      * @param name The name of the attribute.
 416      *
 417      * @return value The value of the attribute.
 418      *
 419      * @throws IllegalArgumentException thrown if the underlying
 420      *   implementation doesn't recognize the attribute.
 421      */
 422     public abstract Object getAttribute(String name)
 423                 throws IllegalArgumentException;
 424 
 425     /**
 426      * Set a feature for this {@code DocumentBuilderFactory}
 427      * and {@code DocumentBuilder}s created by this factory.
 428      *
 429      * <p>
 430      * Feature names are fully qualified {@link java.net.URI}s.
 431      * Implementations may define their own features.
 432      * A {@link ParserConfigurationException} is thrown if this {@code DocumentBuilderFactory} or the
 433      * {@code DocumentBuilder}s it creates cannot support the feature.
 434      * It is possible for a {@code DocumentBuilderFactory} to expose a feature value but be unable to change its state.
 435      *
 436      *
 437      * <p>
 438      * All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
 439      * When the feature is:
 440      * <ul>
 441      *   <li>
 442      *     {@code true}: the implementation will limit XML processing to conform to implementation limits.
 443      *     Examples include entity expansion limits and XML Schema constructs that would consume large amounts of resources.
 444      *     If XML processing is limited for security reasons, it will be reported via a call to the registered
 445      *    {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
 446      *     See {@link  DocumentBuilder#setErrorHandler(org.xml.sax.ErrorHandler errorHandler)}.
 447      *   </li>
 448      *   <li>
 449      *     {@code false}: the implementation will processing XML according to the XML specifications without
 450      *     regard to possible implementation limits.
 451      *   </li>
 452      * </ul>
 453      *
 454      * @param name Feature name.
 455      * @param value Is feature state {@code true} or {@code false}.
 456      *
 457      * @throws ParserConfigurationException if this {@code DocumentBuilderFactory} or the {@code DocumentBuilder}s
 458      *   it creates cannot support this feature.
 459      * @throws NullPointerException If the {@code name} parameter is null.
 460      * @since 1.5
 461      */
 462     public abstract void setFeature(String name, boolean value)
 463             throws ParserConfigurationException;
 464 
 465     /**
 466      * Get the state of the named feature.
 467      *
 468      * <p>
 469      * Feature names are fully qualified {@link java.net.URI}s.
 470      * Implementations may define their own features.
 471      * An {@link ParserConfigurationException} is thrown if this {@code DocumentBuilderFactory} or the
 472      * {@code DocumentBuilder}s it creates cannot support the feature.
 473      * It is possible for an {@code DocumentBuilderFactory} to expose a feature value but be unable to change its state.
 474      *
 475      * @param name Feature name.
 476      *
 477      * @return State of the named feature.
 478      *
 479      * @throws ParserConfigurationException if this {@code DocumentBuilderFactory}
 480      *   or the {@code DocumentBuilder}s it creates cannot support this feature.
 481      * @since 1.5
 482      */
 483     public abstract boolean getFeature(String name)
 484             throws ParserConfigurationException;
 485 
 486 
 487     /**
 488      * Gets the {@link Schema} object specified through
 489      * the {@link #setSchema(Schema schema)} method.
 490      *
 491      * @return
 492      *      the {@link Schema} object that was last set through
 493      *      the {@link #setSchema(Schema)} method, or null
 494      *      if the method was not invoked since a {@link DocumentBuilderFactory}
 495      *      is created.
 496      *
 497      * @throws UnsupportedOperationException When implementation does not
 498      *   override this method.
 499      *
 500      * @since 1.5
 501      */
 502     public Schema getSchema() {
 503         throw new UnsupportedOperationException(
 504             "This parser does not support specification \""
 505             + this.getClass().getPackage().getSpecificationTitle()
 506             + "\" version \""
 507             + this.getClass().getPackage().getSpecificationVersion()
 508             + "\""
 509             );
 510 
 511     }
 512 
 513     /**
 514      * Set the {@link Schema} to be used by parsers created
 515      * from this factory.
 516      *
 517      * <p>
 518      * When a {@link Schema} is non-null, a parser will use a validator
 519      * created from it to validate documents before it passes information
 520      * down to the application.
 521      *
 522      * <p>When errors are found by the validator, the parser is responsible
 523      * to report them to the user-specified {@link org.xml.sax.ErrorHandler}
 524      * (or if the error handler is not set, ignore them or throw them), just
 525      * like any other errors found by the parser itself.
 526      * In other words, if the user-specified {@link org.xml.sax.ErrorHandler}
 527      * is set, it must receive those errors, and if not, they must be
 528      * treated according to the implementation specific
 529      * default error handling rules.
 530      *
 531      * <p>
 532      * A validator may modify the outcome of a parse (for example by
 533      * adding default values that were missing in documents), and a parser
 534      * is responsible to make sure that the application will receive
 535      * modified DOM trees.
 536      *
 537      * <p>
 538      * Initially, null is set as the {@link Schema}.
 539      *
 540      * <p>
 541      * This processing will take effect even if
 542      * the {@link #isValidating()} method returns {@code false}.
 543      *
 544      * <p>It is an error to use
 545      * the {@code http://java.sun.com/xml/jaxp/properties/schemaSource}
 546      * property and/or the {@code http://java.sun.com/xml/jaxp/properties/schemaLanguage}
 547      * property in conjunction with a {@link Schema} object.
 548      * Such configuration will cause a {@link ParserConfigurationException}
 549      * exception when the {@link #newDocumentBuilder()} is invoked.
 550      *
 551      *
 552      * <h3>Note for implementors</h3>
 553      *
 554      * <p>
 555      * A parser must be able to work with any {@link Schema}
 556      * implementation. However, parsers and schemas are allowed
 557      * to use implementation-specific custom mechanisms
 558      * as long as they yield the result described in the specification.
 559      *
 560      *
 561      * @param schema {@code Schema} to use or {@code null}
 562      *   to remove a schema.
 563      *
 564      * @throws UnsupportedOperationException When implementation does not
 565      *   override this method.
 566      *
 567      * @since 1.5
 568      */
 569     public void setSchema(Schema schema) {
 570         throw new UnsupportedOperationException(
 571             "This parser does not support specification \""
 572             + this.getClass().getPackage().getSpecificationTitle()
 573             + "\" version \""
 574             + this.getClass().getPackage().getSpecificationVersion()
 575             + "\""
 576             );
 577     }
 578 
 579 
 580 
 581     /**
 582      * Set state of XInclude processing.
 583      *
 584      * <p>If XInclude markup is found in the document instance, should it be
 585      * processed as specified in <a href="http://www.w3.org/TR/xinclude/">
 586      * XML Inclusions (XInclude) Version 1.0</a>.
 587      *
 588      * <p>XInclude processing defaults to {@code false}.
 589      *
 590      * @param state Set XInclude processing to {@code true} or
 591      *   {@code false}
 592      *
 593      * @throws UnsupportedOperationException When implementation does not
 594      *   override this method.
 595      *
 596      * @since 1.5
 597      */
 598     public void setXIncludeAware(final boolean state) {
 599         if (state) {
 600             throw new UnsupportedOperationException(" setXIncludeAware " +
 601                 "is not supported on this JAXP" +
 602                 " implementation or earlier: " + this.getClass());
 603         }
 604     }
 605 
 606     /**
 607      * Get state of XInclude processing.
 608      *
 609      * @return current state of XInclude processing
 610      *
 611      * @throws UnsupportedOperationException When implementation does not
 612      *   override this method.
 613      *
 614      * @since 1.5
 615      */
 616     public boolean isXIncludeAware() {
 617         throw new UnsupportedOperationException(
 618             "This parser does not support specification \""
 619             + this.getClass().getPackage().getSpecificationTitle()
 620             + "\" version \""
 621             + this.getClass().getPackage().getSpecificationVersion()
 622             + "\""
 623             );
 624     }
 625 }