1 /*
   2  * Copyright (c) 2009, 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.  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.stream;
  27 
  28 import com.sun.xml.internal.stream.XMLInputFactoryImpl;
  29 import javax.xml.stream.util.XMLEventAllocator;
  30 import javax.xml.transform.Source;
  31 
  32 /**
  33  * Defines an abstract implementation of a factory for getting streams.
  34  *
  35  * The following table defines the standard properties of this specification.
  36  * Each property varies in the level of support required by each implementation.
  37  * The level of support required is described in the 'Required' column.
  38  *
  39  *   <table border="2" rules="all" cellpadding="4">
  40  *    <thead>
  41  *      <tr>
  42  *        <th align="center" colspan="5">
  43  *          Configuration parameters
  44  *        </th>
  45  *      </tr>
  46  *    </thead>
  47  *    <tbody>
  48  *      <tr>
  49  *        <th>Property Name</th>
  50  *        <th>Behavior</th>
  51  *        <th>Return type</th>
  52  *        <th>Default Value</th>
  53  *        <th>Required</th>
  54  *      </tr>
  55  * <tr><td>javax.xml.stream.isValidating</td><td>Turns on/off implementation specific DTD validation</td><td>Boolean</td><td>False</td><td>No</td></tr>
  56  * <tr><td>javax.xml.stream.isNamespaceAware</td><td>Turns on/off namespace processing for XML 1.0 support</td><td>Boolean</td><td>True</td><td>True (required) / False (optional)</td></tr>
  57  * <tr><td>javax.xml.stream.isCoalescing</td><td>Requires the processor to coalesce adjacent character data</td><td>Boolean</td><td>False</td><td>Yes</td></tr>
  58  * <tr><td>javax.xml.stream.isReplacingEntityReferences</td><td>replace internal entity references with their replacement text and report them as characters</td><td>Boolean</td><td>True</td><td>Yes</td></tr>
  59  *<tr><td>javax.xml.stream.isSupportingExternalEntities</td><td>Resolve external parsed entities</td><td>Boolean</td><td>Unspecified</td><td>Yes</td></tr>
  60  *<tr><td>javax.xml.stream.supportDTD</td><td>Use this property to request processors that do not support DTDs</td><td>Boolean</td><td>True</td><td>Yes</td></tr>
  61  *<tr><td>javax.xml.stream.reporter</td><td>sets/gets the impl of the XMLReporter </td><td>javax.xml.stream.XMLReporter</td><td>Null</td><td>Yes</td></tr>
  62  *<tr><td>javax.xml.stream.resolver</td><td>sets/gets the impl of the XMLResolver interface</td><td>javax.xml.stream.XMLResolver</td><td>Null</td><td>Yes</td></tr>
  63  *<tr><td>javax.xml.stream.allocator</td><td>sets/gets the impl of the XMLEventAllocator interface</td><td>javax.xml.stream.util.XMLEventAllocator</td><td>Null</td><td>Yes</td></tr>
  64  *    </tbody>
  65  *  </table>
  66  *
  67  *
  68  * @version 1.2
  69  * @author Copyright (c) 2009, 2015 by Oracle Corporation. All Rights Reserved.
  70  * @see XMLOutputFactory
  71  * @see XMLEventReader
  72  * @see XMLStreamReader
  73  * @see EventFilter
  74  * @see XMLReporter
  75  * @see XMLResolver
  76  * @see javax.xml.stream.util.XMLEventAllocator
  77  * @since 1.6
  78  */
  79 
  80 public abstract class XMLInputFactory {
  81   /**
  82    * The property used to turn on/off namespace support,
  83    * this is to support XML 1.0 documents,
  84    * only the true setting must be supported
  85    */
  86   public static final String IS_NAMESPACE_AWARE=
  87     "javax.xml.stream.isNamespaceAware";
  88 
  89   /**
  90    * The property used to turn on/off implementation specific validation
  91    */
  92   public static final String IS_VALIDATING=
  93     "javax.xml.stream.isValidating";
  94 
  95   /**
  96    * The property that requires the parser to coalesce adjacent character data sections
  97    */
  98   public static final String IS_COALESCING=
  99     "javax.xml.stream.isCoalescing";
 100 
 101   /**
 102    * Requires the parser to replace internal
 103    * entity references with their replacement
 104    * text and report them as characters
 105    */
 106   public static final String IS_REPLACING_ENTITY_REFERENCES=
 107     "javax.xml.stream.isReplacingEntityReferences";
 108 
 109   /**
 110    *  The property that requires the parser to resolve external parsed entities
 111    */
 112   public static final String IS_SUPPORTING_EXTERNAL_ENTITIES=
 113     "javax.xml.stream.isSupportingExternalEntities";
 114 
 115   /**
 116    *  The property that requires the parser to support DTDs
 117    */
 118   public static final String SUPPORT_DTD=
 119     "javax.xml.stream.supportDTD";
 120 
 121   /**
 122    * The property used to
 123    * set/get the implementation of the XMLReporter interface
 124    */
 125   public static final String REPORTER=
 126     "javax.xml.stream.reporter";
 127 
 128   /**
 129    * The property used to set/get the implementation of the XMLResolver
 130    */
 131   public static final String RESOLVER=
 132     "javax.xml.stream.resolver";
 133 
 134   /**
 135    * The property used to set/get the implementation of the allocator
 136    */
 137   public static final String ALLOCATOR=
 138     "javax.xml.stream.allocator";
 139 
 140   static final String DEFAULIMPL = "com.sun.xml.internal.stream.XMLInputFactoryImpl";
 141 
 142   protected XMLInputFactory(){}
 143 
 144   /**
 145    * Creates a new instance of the {@code XMLInputFactory} builtin
 146    * system-default implementation.
 147    *
 148    * @return A new instance of the {@code XMLInputFactory} builtin
 149    *         system-default implementation.
 150    *
 151    * @since 9
 152    */
 153   public static XMLInputFactory newDefaultFactory() {
 154       return new XMLInputFactoryImpl();
 155   }
 156 
 157   /**
 158    * Creates a new instance of the factory in exactly the same manner as the
 159    * {@link #newFactory()} method.
 160    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
 161    */
 162   public static XMLInputFactory newInstance()
 163     throws FactoryConfigurationError
 164   {
 165     return FactoryFinder.find(XMLInputFactory.class, DEFAULIMPL);
 166   }
 167 
 168   /**
 169    * Create a new instance of the factory.
 170    * <p>
 171    * This static method creates a new factory instance.
 172    * This method uses the following ordered lookup procedure to determine
 173    * the XMLInputFactory implementation class to load:
 174    *
 175    * <ul>
 176    * <li>
 177    *   <p>Use the javax.xml.stream.XMLInputFactory system property.
 178    * </li>
 179    * <li>
 180    *   <p>Use the configuration file "stax.properties". The file is in standard
 181    *   {@link java.util.Properties} format and typically located in the
 182    *   {@code conf} directory of the Java installation. It contains the fully qualified
 183    *   name of the implementation class with the key being the system property
 184    *   defined above.
 185    *
 186    *   <p>The stax.properties file is read only once by the implementation
 187    *   and its values are then cached for future use.  If the file does not exist
 188    *   when the first attempt is made to read from it, no further attempts are
 189    *   made to check for its existence.  It is not possible to change the value
 190    *   of any property in stax.properties after it has been read for the first time.
 191    *
 192    *   <p>
 193    *   Use the jaxp configuration file "jaxp.properties". The file is in the same
 194    *   format as stax.properties and will only be read if stax.properties does
 195    *   not exist.
 196    * </li>
 197    * <li>
 198    *   <p>Use the service-provider loading facility, defined by the
 199    *   {@link java.util.ServiceLoader} class, to attempt to locate and load an
 200    *   implementation of the service using the {@linkplain
 201    *   java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}:
 202    *   the service-provider loading facility will use the {@linkplain
 203    *   java.lang.Thread#getContextClassLoader() current thread's context class loader}
 204    *   to attempt to load the service. If the context class
 205    *   loader is null, the {@linkplain
 206    *   ClassLoader#getSystemClassLoader() system class loader} will be used.
 207    * </li>
 208    * <li>
 209    * <p>Otherwise, the {@linkplain #newDefaultFactory() system-default}
 210    *    implementation is returned.
 211    * </li>
 212    * </ul>
 213    * <p>
 214    *   Once an application has obtained a reference to a XMLInputFactory it
 215    *   can use the factory to configure and obtain stream instances.
 216    * <p>
 217    *   Note that this is a new method that replaces the deprecated newInstance() method.
 218    *     No changes in behavior are defined by this replacement method relative to
 219    *     the deprecated method.
 220    *
 221    * @throws FactoryConfigurationError in case of {@linkplain
 222    *   java.util.ServiceConfigurationError service configuration error} or if
 223    *   the implementation is not available or cannot be instantiated.
 224    */
 225   @Deprecated(since="1.7")
 226   public static XMLInputFactory newFactory()
 227     throws FactoryConfigurationError
 228   {
 229     return FactoryFinder.find(XMLInputFactory.class, DEFAULIMPL);
 230   }
 231 
 232   /**
 233    * Create a new instance of the factory
 234    *
 235    * @param factoryId             Name of the factory to find, same as
 236    *                              a property name
 237    * @param classLoader           classLoader to use
 238    * @return the factory implementation
 239    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
 240    *
 241    * @deprecated  This method has been deprecated to maintain API consistency.
 242    *              All newInstance methods have been replaced with corresponding
 243    *              newFactory methods. The replacement {@link
 244    *              #newFactory(java.lang.String, java.lang.ClassLoader)} method
 245    *              defines no changes in behavior.
 246    */
 247   @Deprecated(since="1.7")
 248   public static XMLInputFactory newInstance(String factoryId,
 249           ClassLoader classLoader)
 250           throws FactoryConfigurationError {
 251       //do not fallback if given classloader can't find the class, throw exception
 252       return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
 253   }
 254 
 255   /**
 256    * Create a new instance of the factory.
 257    * If the classLoader argument is null, then the ContextClassLoader is used.
 258    * <p>
 259    * This method uses the following ordered lookup procedure to determine
 260    * the XMLInputFactory implementation class to load:
 261    * <ul>
 262    * <li>
 263    *   <p>
 264    *   Use the value of the system property identified by {@code factoryId}.
 265    * </li>
 266    * <li>
 267    *   <p>
 268    *   Use the configuration file "stax.properties". The file is in standard
 269    *   {@link java.util.Properties} format and typically located in the
 270    *   {@code conf} directory of the Java installation. It contains the fully qualified
 271    *   name of the implementation class with the key being the system property
 272    *   defined above.
 273    *
 274    *   <p>
 275    *   The stax.properties file is read only once by the implementation
 276    *   and its values are then cached for future use.  If the file does not exist
 277    *   when the first attempt is made to read from it, no further attempts are
 278    *   made to check for its existence.  It is not possible to change the value
 279    *   of any property in stax.properties after it has been read for the first time.
 280    *
 281    *   <p>
 282    *   Use the jaxp configuration file "jaxp.properties". The file is in the same
 283    *   format as stax.properties and will only be read if stax.properties does
 284    *   not exist.
 285    * </li>
 286    * <li>
 287    *   <p>
 288    *   If {@code factoryId} is "javax.xml.stream.XMLInputFactory",
 289    *   use the service-provider loading facility, defined by the
 290    *   {@link java.util.ServiceLoader} class, to attempt to {@linkplain
 291    *   java.util.ServiceLoader#load(java.lang.Class, java.lang.ClassLoader) locate and load}
 292    *   an implementation of the service using the specified {@code ClassLoader}.
 293    *   If {@code classLoader} is null, the {@linkplain
 294    *   java.util.ServiceLoader#load(java.lang.Class) default loading mechanism} will apply:
 295    *   That is, the service-provider loading facility will use the {@linkplain
 296    *   java.lang.Thread#getContextClassLoader() current thread's context class loader}
 297    *   to attempt to load the service. If the context class
 298    *   loader is null, the {@linkplain
 299    *   ClassLoader#getSystemClassLoader() system class loader} will be used.
 300    * </li>
 301    * <li>
 302    *   <p>
 303    *   Otherwise, throws a {@link FactoryConfigurationError}.
 304    * </li>
 305    * </ul>
 306    *
 307    * <p>
 308    * Note that this is a new method that replaces the deprecated
 309    *   {@link #newInstance(java.lang.String, java.lang.ClassLoader)
 310    *   newInstance(String factoryId, ClassLoader classLoader)} method.
 311    * No changes in behavior are defined by this replacement method relative
 312    * to the deprecated method.
 313    *
 314    *
 315    * @apiNote The parameter factoryId defined here is inconsistent with that
 316    * of other JAXP factories where the first parameter is fully qualified
 317    * factory class name that provides implementation of the factory.
 318    *
 319    * @param factoryId             Name of the factory to find, same as
 320    *                              a property name
 321    * @param classLoader           classLoader to use
 322    * @return the factory implementation
 323    * @throws FactoryConfigurationError in case of {@linkplain
 324    *   java.util.ServiceConfigurationError service configuration error} or if
 325    *   the implementation is not available or cannot be instantiated.
 326    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
 327    */
 328   public static XMLInputFactory newFactory(String factoryId,
 329           ClassLoader classLoader)
 330           throws FactoryConfigurationError {
 331       //do not fallback if given classloader can't find the class, throw exception
 332       return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
 333   }
 334 
 335   /**
 336    * Create a new XMLStreamReader from a reader
 337    * @param reader the XML data to read from
 338    * @throws XMLStreamException
 339    */
 340   public abstract XMLStreamReader createXMLStreamReader(java.io.Reader reader)
 341     throws XMLStreamException;
 342 
 343   /**
 344    * Create a new XMLStreamReader from a JAXP source.  This method is optional.
 345    * @param source the source to read from
 346    * @throws UnsupportedOperationException if this method is not
 347    * supported by this XMLInputFactory
 348    * @throws XMLStreamException
 349    */
 350   public abstract XMLStreamReader createXMLStreamReader(Source source)
 351     throws XMLStreamException;
 352 
 353   /**
 354    * Create a new XMLStreamReader from a java.io.InputStream
 355    * @param stream the InputStream to read from
 356    * @throws XMLStreamException
 357    */
 358   public abstract XMLStreamReader createXMLStreamReader(java.io.InputStream stream)
 359     throws XMLStreamException;
 360 
 361   /**
 362    * Create a new XMLStreamReader from a java.io.InputStream
 363    * @param stream the InputStream to read from
 364    * @param encoding the character encoding of the stream
 365    * @throws XMLStreamException
 366    */
 367   public abstract XMLStreamReader createXMLStreamReader(java.io.InputStream stream, String encoding)
 368     throws XMLStreamException;
 369 
 370   /**
 371    * Create a new XMLStreamReader from a java.io.InputStream
 372    * @param systemId the system ID of the stream
 373    * @param stream the InputStream to read from
 374    */
 375   public abstract XMLStreamReader createXMLStreamReader(String systemId, java.io.InputStream stream)
 376     throws XMLStreamException;
 377 
 378   /**
 379    * Create a new XMLStreamReader from a java.io.InputStream
 380    * @param systemId the system ID of the stream
 381    * @param reader the InputStream to read from
 382    */
 383   public abstract XMLStreamReader createXMLStreamReader(String systemId, java.io.Reader reader)
 384     throws XMLStreamException;
 385 
 386   /**
 387    * Create a new XMLEventReader from a reader
 388    * @param reader the XML data to read from
 389    * @throws XMLStreamException
 390    */
 391   public abstract XMLEventReader createXMLEventReader(java.io.Reader reader)
 392     throws XMLStreamException;
 393 
 394   /**
 395    * Create a new XMLEventReader from a reader
 396    * @param systemId the system ID of the input
 397    * @param reader the XML data to read from
 398    * @throws XMLStreamException
 399    */
 400   public abstract XMLEventReader createXMLEventReader(String systemId, java.io.Reader reader)
 401     throws XMLStreamException;
 402 
 403   /**
 404    * Create a new XMLEventReader from an XMLStreamReader.  After being used
 405    * to construct the XMLEventReader instance returned from this method
 406    * the XMLStreamReader must not be used.
 407    * @param reader the XMLStreamReader to read from (may not be modified)
 408    * @return a new XMLEventReader
 409    * @throws XMLStreamException
 410    */
 411   public abstract XMLEventReader createXMLEventReader(XMLStreamReader reader)
 412     throws XMLStreamException;
 413 
 414   /**
 415    * Create a new XMLEventReader from a JAXP source.
 416    * Support of this method is optional.
 417    * @param source the source to read from
 418    * @throws UnsupportedOperationException if this method is not
 419    * supported by this XMLInputFactory
 420    */
 421   public abstract XMLEventReader createXMLEventReader(Source source)
 422     throws XMLStreamException;
 423 
 424   /**
 425    * Create a new XMLEventReader from a java.io.InputStream
 426    * @param stream the InputStream to read from
 427    * @throws XMLStreamException
 428    */
 429   public abstract XMLEventReader createXMLEventReader(java.io.InputStream stream)
 430     throws XMLStreamException;
 431 
 432   /**
 433    * Create a new XMLEventReader from a java.io.InputStream
 434    * @param stream the InputStream to read from
 435    * @param encoding the character encoding of the stream
 436    * @throws XMLStreamException
 437    */
 438   public abstract XMLEventReader createXMLEventReader(java.io.InputStream stream, String encoding)
 439     throws XMLStreamException;
 440 
 441   /**
 442    * Create a new XMLEventReader from a java.io.InputStream
 443    * @param systemId the system ID of the stream
 444    * @param stream the InputStream to read from
 445    * @throws XMLStreamException
 446    */
 447   public abstract XMLEventReader createXMLEventReader(String systemId, java.io.InputStream stream)
 448     throws XMLStreamException;
 449 
 450   /**
 451    * Create a filtered reader that wraps the filter around the reader
 452    * @param reader the reader to filter
 453    * @param filter the filter to apply to the reader
 454    * @throws XMLStreamException
 455    */
 456   public abstract XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter)
 457     throws XMLStreamException;
 458 
 459   /**
 460    * Create a filtered event reader that wraps the filter around the event reader
 461    * @param reader the event reader to wrap
 462    * @param filter the filter to apply to the event reader
 463    * @throws XMLStreamException
 464    */
 465   public abstract XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter)
 466     throws XMLStreamException;
 467 
 468   /**
 469    * The resolver that will be set on any XMLStreamReader or XMLEventReader created
 470    * by this factory instance.
 471    */
 472   public abstract XMLResolver getXMLResolver();
 473 
 474   /**
 475    * The resolver that will be set on any XMLStreamReader or XMLEventReader created
 476    * by this factory instance.
 477    * @param resolver the resolver to use to resolve references
 478    */
 479   public abstract void  setXMLResolver(XMLResolver resolver);
 480 
 481   /**
 482    * The reporter that will be set on any XMLStreamReader or XMLEventReader created
 483    * by this factory instance.
 484    */
 485   public abstract XMLReporter getXMLReporter();
 486 
 487   /**
 488    * The reporter that will be set on any XMLStreamReader or XMLEventReader created
 489    * by this factory instance.
 490    * @param reporter the resolver to use to report non fatal errors
 491    */
 492   public abstract void setXMLReporter(XMLReporter reporter);
 493 
 494   /**
 495    * Allows the user to set specific feature/property on the underlying
 496    * implementation. The underlying implementation is not required to support
 497    * every setting of every property in the specification and may use
 498    * IllegalArgumentException to signal that an unsupported property may not be
 499    * set with the specified value.
 500    * <p>
 501    * All implementations that implement JAXP 1.5 or newer are required to
 502    * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property.
 503    * <ul>
 504    *   <li>
 505    *        <p>
 506    *        Access to external DTDs, external Entity References is restricted to the
 507    *        protocols specified by the property. If access is denied during parsing
 508    *        due to the restriction of this property, {@link javax.xml.stream.XMLStreamException}
 509    *        will be thrown by the {@link javax.xml.stream.XMLStreamReader#next()} or
 510    *        {@link javax.xml.stream.XMLEventReader#nextEvent()} method.
 511    *
 512    *   </li>
 513    * </ul>
 514    * @param name The name of the property (may not be null)
 515    * @param value The value of the property
 516    * @throws java.lang.IllegalArgumentException if the property is not supported
 517    */
 518   public abstract void setProperty(java.lang.String name, Object value)
 519     throws java.lang.IllegalArgumentException;
 520 
 521   /**
 522    * Get the value of a feature/property from the underlying implementation
 523    * @param name The name of the property (may not be null)
 524    * @return The value of the property
 525    * @throws IllegalArgumentException if the property is not supported
 526    */
 527   public abstract Object getProperty(java.lang.String name)
 528     throws java.lang.IllegalArgumentException;
 529 
 530 
 531   /**
 532    * Query the set of properties that this factory supports.
 533    *
 534    * @param name The name of the property (may not be null)
 535    * @return true if the property is supported and false otherwise
 536    */
 537   public abstract boolean isPropertySupported(String name);
 538 
 539   /**
 540    * Set a user defined event allocator for events
 541    * @param allocator the user defined allocator
 542    */
 543   public abstract void setEventAllocator(XMLEventAllocator allocator);
 544 
 545   /**
 546    * Gets the allocator used by streams created with this factory
 547    */
 548   public abstract XMLEventAllocator getEventAllocator();
 549 
 550 }