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