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