1 /*
   2  * Copyright (c) 2000, 2017, 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 java.io.File;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 
  32 import javax.xml.validation.Schema;
  33 
  34 import org.xml.sax.HandlerBase;
  35 import org.xml.sax.InputSource;
  36 import org.xml.sax.Parser;
  37 import org.xml.sax.SAXException;
  38 import org.xml.sax.SAXNotRecognizedException;
  39 import org.xml.sax.SAXNotSupportedException;
  40 import org.xml.sax.XMLReader;
  41 import org.xml.sax.helpers.DefaultHandler;
  42 
  43 
  44 /**
  45  * Defines the API that wraps an {@link org.xml.sax.XMLReader}
  46  * implementation class. In JAXP 1.0, this class wrapped the
  47  * {@link org.xml.sax.Parser} interface, however this interface was
  48  * replaced by the {@link org.xml.sax.XMLReader}. For ease
  49  * of transition, this class continues to support the same name
  50  * and interface as well as supporting new methods.
  51  *
  52  * An instance of this class can be obtained from the
  53  * {@link javax.xml.parsers.SAXParserFactory#newSAXParser()} method.
  54  * Once an instance of this class is obtained, XML can be parsed from
  55  * a variety of input sources. These input sources are InputStreams,
  56  * Files, URLs, and SAX InputSources.<p>
  57  *
  58  * This static method creates a new factory instance based
  59  * on a system property setting or uses the platform default
  60  * if no property has been defined.<p>
  61  *
  62  * The system property that controls which Factory implementation
  63  * to create is named <code>&quot;javax.xml.parsers.SAXParserFactory&quot;</code>.
  64  * This property names a class that is a concrete subclass of this
  65  * abstract class. If no property is defined, a platform default
  66  * will be used.</p>
  67  *
  68  * As the content is parsed by the underlying parser, methods of the
  69  * given {@link org.xml.sax.HandlerBase} or the
  70  * {@link org.xml.sax.helpers.DefaultHandler} are called.<p>
  71  *
  72  * Implementors of this class which wrap an underlying implementation
  73  * can consider using the {@link org.xml.sax.helpers.ParserAdapter}
  74  * class to initially adapt their SAX1 implementation to work under
  75  * this revised class.
  76  *
  77  * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
  78  * @since 1.4
  79  */
  80 @SuppressWarnings("deprecation")
  81 public abstract class SAXParser {
  82 
  83     /**
  84      * <p>Protected constructor to prevent instantiation.
  85      * Use {@link javax.xml.parsers.SAXParserFactory#newSAXParser()}.</p>
  86      */
  87     protected SAXParser () {
  88 
  89     }
  90 
  91         /**
  92          * <p>Reset this <code>SAXParser</code> to its original configuration.</p>
  93          *
  94          * <p><code>SAXParser</code> is reset to the same state as when it was created with
  95          * {@link SAXParserFactory#newSAXParser()}.
  96          * <code>reset()</code> is designed to allow the reuse of existing <code>SAXParser</code>s
  97          * thus saving resources associated with the creation of new <code>SAXParser</code>s.</p>
  98          *
  99          * <p>The reset <code>SAXParser</code> is not guaranteed to have the same {@link Schema}
 100          * <code>Object</code>, e.g. {@link Object#equals(Object obj)}.  It is guaranteed to have a functionally equal
 101          * <code>Schema</code>.</p>
 102      *
 103      * @throws UnsupportedOperationException When Implementations do not
 104      *   override this method
 105          *
 106          * @since 1.5
 107          */
 108         public void reset() {
 109 
 110                 // implementors should override this method
 111                 throw new UnsupportedOperationException(
 112                         "This SAXParser, \"" + this.getClass().getName() + "\", does not support the reset functionality."
 113                         + "  Specification \"" + this.getClass().getPackage().getSpecificationTitle() + "\""
 114                         + " version \"" + this.getClass().getPackage().getSpecificationVersion() + "\""
 115                         );
 116         }
 117 
 118     /**
 119      * <p>Parse the content of the given {@link java.io.InputStream}
 120      * instance as XML using the specified {@link org.xml.sax.HandlerBase}.
 121      * <i> Use of the DefaultHandler version of this method is recommended as
 122      * the HandlerBase class has been deprecated in SAX 2.0</i>.</p>
 123      *
 124      * @param is InputStream containing the content to be parsed.
 125      * @param hb The SAX HandlerBase to use.
 126      *
 127      * @throws IllegalArgumentException If the given InputStream is null.
 128      * @throws SAXException If parse produces a SAX error.
 129      * @throws IOException If an IO error occurs interacting with the
 130      *   <code>InputStream</code>.
 131      *
 132      * @see org.xml.sax.DocumentHandler
 133      */
 134     public void parse(InputStream is, HandlerBase hb)
 135         throws SAXException, IOException {
 136         if (is == null) {
 137             throw new IllegalArgumentException("InputStream cannot be null");
 138         }
 139 
 140         InputSource input = new InputSource(is);
 141         this.parse(input, hb);
 142     }
 143 
 144     /**
 145      * <p>Parse the content of the given {@link java.io.InputStream}
 146      * instance as XML using the specified {@link org.xml.sax.HandlerBase}.
 147      * <i> Use of the DefaultHandler version of this method is recommended as
 148      * the HandlerBase class has been deprecated in SAX 2.0</i>.</p>
 149      *
 150      * @param is InputStream containing the content to be parsed.
 151      * @param hb The SAX HandlerBase to use.
 152      * @param systemId The systemId which is needed for resolving relative URIs.
 153      *
 154      * @throws IllegalArgumentException If the given <code>InputStream</code> is
 155      *   <code>null</code>.
 156      * @throws IOException If any IO error occurs interacting with the
 157      *   <code>InputStream</code>.
 158      * @throws SAXException If any SAX errors occur during processing.
 159      *
 160      * @see org.xml.sax.DocumentHandler version of this method instead.
 161      */
 162     public void parse(
 163         InputStream is,
 164         HandlerBase hb,
 165         String systemId)
 166         throws SAXException, IOException {
 167         if (is == null) {
 168             throw new IllegalArgumentException("InputStream cannot be null");
 169         }
 170 
 171         InputSource input = new InputSource(is);
 172         input.setSystemId(systemId);
 173         this.parse(input, hb);
 174     }
 175 
 176     /**
 177      * Parse the content of the given {@link java.io.InputStream}
 178      * instance as XML using the specified
 179      * {@link org.xml.sax.helpers.DefaultHandler}.
 180      *
 181      * @param is InputStream containing the content to be parsed.
 182      * @param dh The SAX DefaultHandler to use.
 183      *
 184      * @throws IllegalArgumentException If the given InputStream is null.
 185      * @throws IOException If any IO errors occur.
 186      * @throws SAXException If any SAX errors occur during processing.
 187      *
 188      * @see org.xml.sax.DocumentHandler
 189      */
 190     public void parse(InputStream is, DefaultHandler dh)
 191         throws SAXException, IOException {
 192         if (is == null) {
 193             throw new IllegalArgumentException("InputStream cannot be null");
 194         }
 195 
 196         InputSource input = new InputSource(is);
 197         this.parse(input, dh);
 198     }
 199 
 200     /**
 201      * Parse the content of the given {@link java.io.InputStream}
 202      * instance as XML using the specified
 203      * {@link org.xml.sax.helpers.DefaultHandler}.
 204      *
 205      * @param is InputStream containing the content to be parsed.
 206      * @param dh The SAX DefaultHandler to use.
 207      * @param systemId The systemId which is needed for resolving relative URIs.
 208      *
 209      * @throws IllegalArgumentException If the given InputStream is null.
 210      * @throws IOException If any IO errors occur.
 211      * @throws SAXException If any SAX errors occur during processing.
 212      *
 213      * @see org.xml.sax.DocumentHandler version of this method instead.
 214      */
 215     public void parse(
 216         InputStream is,
 217         DefaultHandler dh,
 218         String systemId)
 219         throws SAXException, IOException {
 220         if (is == null) {
 221             throw new IllegalArgumentException("InputStream cannot be null");
 222         }
 223 
 224         InputSource input = new InputSource(is);
 225         input.setSystemId(systemId);
 226         this.parse(input, dh);
 227     }
 228 
 229     /**
 230      * Parse the content described by the giving Uniform Resource
 231      * Identifier (URI) as XML using the specified
 232      * {@link org.xml.sax.HandlerBase}.
 233      * <i> Use of the DefaultHandler version of this method is recommended as
 234      * the <code>HandlerBase</code> class has been deprecated in SAX 2.0</i>
 235      *
 236      * @param uri The location of the content to be parsed.
 237      * @param hb The SAX HandlerBase to use.
 238      *
 239      * @throws IllegalArgumentException If the uri is null.
 240      * @throws IOException If any IO errors occur.
 241      * @throws SAXException If any SAX errors occur during processing.
 242      *
 243      * @see org.xml.sax.DocumentHandler
 244      */
 245     public void parse(String uri, HandlerBase hb)
 246         throws SAXException, IOException {
 247         if (uri == null) {
 248             throw new IllegalArgumentException("uri cannot be null");
 249         }
 250 
 251         InputSource input = new InputSource(uri);
 252         this.parse(input, hb);
 253     }
 254 
 255     /**
 256      * Parse the content described by the giving Uniform Resource
 257      * Identifier (URI) as XML using the specified
 258      * {@link org.xml.sax.helpers.DefaultHandler}.
 259      *
 260      * @param uri The location of the content to be parsed.
 261      * @param dh The SAX DefaultHandler to use.
 262      *
 263      * @throws IllegalArgumentException If the uri is null.
 264      * @throws IOException If any IO errors occur.
 265      * @throws SAXException If any SAX errors occur during processing.
 266      *
 267      * @see org.xml.sax.DocumentHandler
 268      */
 269     public void parse(String uri, DefaultHandler dh)
 270         throws SAXException, IOException {
 271         if (uri == null) {
 272             throw new IllegalArgumentException("uri cannot be null");
 273         }
 274 
 275         InputSource input = new InputSource(uri);
 276         this.parse(input, dh);
 277     }
 278 
 279     /**
 280      * Parse the content of the file specified as XML using the
 281      * specified {@link org.xml.sax.HandlerBase}.
 282      * <i> Use of the DefaultHandler version of this method is recommended as
 283      * the HandlerBase class has been deprecated in SAX 2.0</i>
 284      *
 285      * @param f The file containing the XML to parse
 286      * @param hb The SAX HandlerBase to use.
 287      *
 288      * @throws IllegalArgumentException If the File object is null.
 289      * @throws IOException If any IO errors occur.
 290      * @throws SAXException If any SAX errors occur during processing.
 291      *
 292      * @see org.xml.sax.DocumentHandler
 293      */
 294     public void parse(File f, HandlerBase hb)
 295         throws SAXException, IOException {
 296         if (f == null) {
 297             throw new IllegalArgumentException("File cannot be null");
 298         }
 299 
 300         //convert file to appropriate URI, f.toURI().toASCIIString()
 301         //converts the URI to string as per rule specified in
 302         //RFC 2396,
 303         InputSource input = new InputSource(f.toURI().toASCIIString());
 304         this.parse(input, hb);
 305     }
 306 
 307     /**
 308      * Parse the content of the file specified as XML using the
 309      * specified {@link org.xml.sax.helpers.DefaultHandler}.
 310      *
 311      * @param f The file containing the XML to parse
 312      * @param dh The SAX DefaultHandler to use.
 313      *
 314      * @throws IllegalArgumentException If the File object is null.
 315      * @throws IOException If any IO errors occur.
 316      * @throws SAXException If any SAX errors occur during processing.
 317      *
 318      * @see org.xml.sax.DocumentHandler
 319      */
 320     public void parse(File f, DefaultHandler dh)
 321         throws SAXException, IOException {
 322         if (f == null) {
 323             throw new IllegalArgumentException("File cannot be null");
 324         }
 325 
 326         //convert file to appropriate URI, f.toURI().toASCIIString()
 327         //converts the URI to string as per rule specified in
 328         //RFC 2396,
 329         InputSource input = new InputSource(f.toURI().toASCIIString());
 330         this.parse(input, dh);
 331     }
 332 
 333     /**
 334      * Parse the content given {@link org.xml.sax.InputSource}
 335      * as XML using the specified
 336      * {@link org.xml.sax.HandlerBase}.
 337      * <i> Use of the DefaultHandler version of this method is recommended as
 338      * the HandlerBase class has been deprecated in SAX 2.0</i>
 339      *
 340      * @param is The InputSource containing the content to be parsed.
 341      * @param hb The SAX HandlerBase to use.
 342      *
 343      * @throws IllegalArgumentException If the <code>InputSource</code> object
 344      *   is <code>null</code>.
 345      * @throws IOException If any IO errors occur.
 346      * @throws SAXException If any SAX errors occur during processing.
 347      *
 348      * @see org.xml.sax.DocumentHandler
 349      */
 350     public void parse(InputSource is, HandlerBase hb)
 351         throws SAXException, IOException {
 352         if (is == null) {
 353             throw new IllegalArgumentException("InputSource cannot be null");
 354         }
 355 
 356         Parser parser = this.getParser();
 357         if (hb != null) {
 358             parser.setDocumentHandler(hb);
 359             parser.setEntityResolver(hb);
 360             parser.setErrorHandler(hb);
 361             parser.setDTDHandler(hb);
 362         }
 363         parser.parse(is);
 364     }
 365 
 366     /**
 367      * Parse the content given {@link org.xml.sax.InputSource}
 368      * as XML using the specified
 369      * {@link org.xml.sax.helpers.DefaultHandler}.
 370      *
 371      * @param is The InputSource containing the content to be parsed.
 372      * @param dh The SAX DefaultHandler to use.
 373      *
 374      * @throws IllegalArgumentException If the <code>InputSource</code> object
 375      *   is <code>null</code>.
 376      * @throws IOException If any IO errors occur.
 377      * @throws SAXException If any SAX errors occur during processing.
 378      *
 379      * @see org.xml.sax.DocumentHandler
 380      */
 381     public void parse(InputSource is, DefaultHandler dh)
 382         throws SAXException, IOException {
 383         if (is == null) {
 384             throw new IllegalArgumentException("InputSource cannot be null");
 385         }
 386 
 387         XMLReader reader = this.getXMLReader();
 388         if (dh != null) {
 389             reader.setContentHandler(dh);
 390             reader.setEntityResolver(dh);
 391             reader.setErrorHandler(dh);
 392             reader.setDTDHandler(dh);
 393         }
 394         reader.parse(is);
 395     }
 396 
 397     /**
 398      * Returns the SAX parser that is encapsulated by the
 399      * implementation of this class.
 400      *
 401      * @return The SAX parser that is encapsulated by the
 402      *         implementation of this class.
 403      *
 404      * @throws SAXException If any SAX errors occur during processing.
 405      */
 406     public abstract org.xml.sax.Parser getParser() throws SAXException;
 407 
 408     /**
 409      * Returns the {@link org.xml.sax.XMLReader} that is encapsulated by the
 410      * implementation of this class.
 411      *
 412      * @return The XMLReader that is encapsulated by the
 413      *         implementation of this class.
 414      *
 415      * @throws SAXException If any SAX errors occur during processing.
 416      */
 417 
 418     public abstract org.xml.sax.XMLReader getXMLReader() throws SAXException;
 419 
 420     /**
 421      * Indicates whether or not this parser is configured to
 422      * understand namespaces.
 423      *
 424      * @return true if this parser is configured to
 425      *         understand namespaces; false otherwise.
 426      */
 427 
 428     public abstract boolean isNamespaceAware();
 429 
 430     /**
 431      * Indicates whether or not this parser is configured to
 432      * validate XML documents.
 433      *
 434      * @return true if this parser is configured to
 435      *         validate XML documents; false otherwise.
 436      */
 437 
 438     public abstract boolean isValidating();
 439 
 440     /**
 441      * <p>Sets the particular property in the underlying implementation of
 442      * {@link org.xml.sax.XMLReader}.
 443      * A list of the core features and properties can be found at
 444      * <a href="http://sax.sourceforge.net/?selected=get-set">
 445      * http://sax.sourceforge.net/?selected=get-set</a>.</p>
 446      * <p>
 447      * All implementations that implement JAXP 1.5 or newer are required to
 448      * support the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} and
 449      * {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} properties.
 450      * </p>
 451      * <ul>
 452      *   <li>
 453      *      <p>
 454      *      Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_DTD} property
 455      *      restricts the access to external DTDs, external Entity References to
 456      *      the protocols specified by the property.  If access is denied during parsing
 457      *      due to the restriction of this property, {@link org.xml.sax.SAXException}
 458      *      will be thrown by the parse methods defined by {@link javax.xml.parsers.SAXParser}.
 459      *      </p>
 460      *      <p>
 461      *      Setting the {@link javax.xml.XMLConstants#ACCESS_EXTERNAL_SCHEMA} property
 462      *      restricts the access to external Schema set by the schemaLocation attribute to
 463      *      the protocols specified by the property.  If access is denied during parsing
 464      *      due to the restriction of this property, {@link org.xml.sax.SAXException}
 465      *      will be thrown by the parse methods defined by the {@link javax.xml.parsers.SAXParser}.
 466      *      </p>
 467      *   </li>
 468      * </ul>
 469      *
 470      * @param name The name of the property to be set.
 471      * @param value The value of the property to be set.
 472      *
 473      * @throws SAXNotRecognizedException When the underlying XMLReader does
 474      *   not recognize the property name.
 475      * @throws SAXNotSupportedException When the underlying XMLReader
 476      *  recognizes the property name but doesn't support the property.
 477      *
 478      * @see org.xml.sax.XMLReader#setProperty
 479      */
 480     public abstract void setProperty(String name, Object value)
 481         throws SAXNotRecognizedException, SAXNotSupportedException;
 482 
 483     /**
 484      * <p>Returns the particular property requested for in the underlying
 485      * implementation of {@link org.xml.sax.XMLReader}.</p>
 486      *
 487      * @param name The name of the property to be retrieved.
 488      * @return Value of the requested property.
 489      *
 490      * @throws SAXNotRecognizedException When the underlying XMLReader does
 491      *    not recognize the property name.
 492      * @throws SAXNotSupportedException When the underlying XMLReader
 493      *  recognizes the property name but doesn't support the property.
 494      *
 495      * @see org.xml.sax.XMLReader#getProperty
 496      */
 497     public abstract Object getProperty(String name)
 498         throws SAXNotRecognizedException, SAXNotSupportedException;
 499 
 500     /** <p>Get current state of canonicalization.</p>
 501      *
 502      * @return current state canonicalization control
 503      */
 504     /*
 505     public boolean getCanonicalization() {
 506         return canonicalState;
 507     }
 508     */
 509 
 510     /** <p>Get a reference to the the {@link Schema} being used by
 511      * the XML processor.</p>
 512      *
 513      * <p>If no schema is being used, <code>null</code> is returned.</p>
 514      *
 515      * @return {@link Schema} being used or <code>null</code>
 516      *  if none in use
 517      *
 518      * @throws UnsupportedOperationException When implementation does not
 519      *   override this method
 520      *
 521      * @since 1.5
 522      */
 523     public Schema getSchema() {
 524         throw new UnsupportedOperationException(
 525             "This parser does not support specification \""
 526             + this.getClass().getPackage().getSpecificationTitle()
 527             + "\" version \""
 528             + this.getClass().getPackage().getSpecificationVersion()
 529             + "\""
 530             );
 531     }
 532 
 533     /**
 534      * <p>Get the XInclude processing mode for this parser.</p>
 535      *
 536      * @return
 537      *      the return value of
 538      *      the {@link SAXParserFactory#isXIncludeAware()}
 539      *      when this parser was created from factory.
 540      *
 541      * @throws UnsupportedOperationException When implementation does not
 542      *   override this method
 543      *
 544      * @since 1.5
 545      *
 546      * @see SAXParserFactory#setXIncludeAware(boolean)
 547      */
 548     public boolean isXIncludeAware() {
 549         throw new UnsupportedOperationException(
 550             "This parser does not support specification \""
 551             + this.getClass().getPackage().getSpecificationTitle()
 552             + "\" version \""
 553             + this.getClass().getPackage().getSpecificationVersion()
 554             + "\""
 555             );
 556     }
 557 }