View Javadoc

    1   /*
    2    * Copyright 2001-2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License")
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16
    17  package org.apache.commons.configuration;
    18
    19  import java.io.IOException;
    20
    21  import org.xml.sax.Attributes;
    22  import org.xml.sax.ContentHandler;
    23  import org.xml.sax.DTDHandler;
    24  import org.xml.sax.EntityResolver;
    25  import org.xml.sax.ErrorHandler;
    26  import org.xml.sax.InputSource;
    27  import org.xml.sax.SAXException;
    28  import org.xml.sax.XMLReader;
    29  import org.xml.sax.helpers.AttributesImpl;
    30
    31  /***
    32   * <p>A base class for &quot;faked&quot; <code>XMLReader</code> classes
    33   * that transform a configuration object in a set of SAX parsing events.</p>
    34   * <p>This class provides dummy implementations for most of the methods
    35   * defined in the <code>XMLReader</code> interface that are not used for this
    36   * special purpose. There will be concrete sub classes that process specific
    37   * configuration classes.</p>
    38   *
    39   * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
    40   * @version $Id: ConfigurationXMLReader.java,v 1.3 2004/06/24 12:35:15 ebourg Exp $
    41   */
    42  public abstract class ConfigurationXMLReader implements XMLReader
    43  {
    44      /*** Constant for the namespace URI.*/
    45      protected static final String NS_URI = "";
    46
    47      /*** Constant for the default name of the root element.*/
    48      private static final String DEFAULT_ROOT_NAME = "config";
    49
    50      /*** An empty attributes object.*/
    51      private static final Attributes EMPTY_ATTRS = new AttributesImpl();
    52
    53      /*** Stores the content handler.*/
    54      private ContentHandler contentHandler;
    55
    56      /*** Stores an exception that occurred during parsing.*/
    57      private SAXException exception;
    58
    59      /*** Stores the name for the root element.*/
    60      private String rootName;
    61
    62      /***
    63       * Creates a new instance of <code>ConfigurationXMLReader</code>.
    64       */
    65      protected ConfigurationXMLReader()
    66      {
    67          super();
    68          setRootName(DEFAULT_ROOT_NAME);
    69      }
    70
    71      /***
    72       * Parses the acutal configuration object. The passed system ID will be
    73       * ignored.
    74       *
    75       * @param systemId the system ID (ignored)
    76       * @throws IOException if no configuration was specified
    77       * @throws SAXException if an error occurs during parsing
    78       */
    79      public void parse(String systemId) throws IOException, SAXException
    80      {
    81          parseConfiguration();
    82      }
    83
    84      /***
    85       * Parses the acutal configuration object. The passed input source will be
    86       * ignored.
    87       *
    88       * @param input the input source (ignored)
    89       * @throws IOException if no configuration was specified
    90       * @throws SAXException if an error occurs during parsing
    91       */
    92      public void parse(InputSource input) throws IOException, SAXException
    93      {
    94          parseConfiguration();
    95      }
    96
    97      /***
    98       * Dummy implementation of the interface method.
    99       *
    100      * @param name the name of the feature
    101      * @return always <b>false</b> (no features are supported)
    102      */
    103     public boolean getFeature(String name)
    104     {
    105         return false;
    106     }
    107
    108     /***
    109      * Dummy implementation of the interface method.
    110      *
    111      * @param name the name of the feature to be set
    112      * @param value the value of the feature
    113      */
    114     public void setFeature(String name, boolean value)
    115     {
    116     }
    117
    118     /***
    119      * Returns the actually set content handler.
    120      *
    121      * @return the content handler
    122      */
    123     public ContentHandler getContentHandler()
    124     {
    125         return contentHandler;
    126     }
    127
    128     /***
    129      * Sets the content handler. The object specified here will receive SAX
    130      * events during parsing.
    131      *
    132      * @param handler the content handler
    133      */
    134     public void setContentHandler(ContentHandler handler)
    135     {
    136         contentHandler = handler;
    137     }
    138
    139     /***
    140      * Returns the DTD handler. This class does not support DTD handlers,
    141      * so this method always returns <b>null</b>.
    142      *
    143      * @return the DTD handler
    144      */
    145     public DTDHandler getDTDHandler()
    146     {
    147         return null;
    148     }
    149
    150     /***
    151      * Sets the DTD handler. The passed value is ignored.
    152      *
    153      * @param handler the handler to be set
    154      */
    155     public void setDTDHandler(DTDHandler handler)
    156     {
    157     }
    158
    159     /***
    160      * Returns the entity resolver. This class does not support an entity
    161      * resolver, so this method always returns <b>null</b>.
    162      *
    163      * @return the entity resolver
    164      */
    165     public EntityResolver getEntityResolver()
    166     {
    167         return null;
    168     }
    169
    170     /***
    171      * Sets the entity resolver. The passed value is ignored.
    172      *
    173      * @param resolver the entity resolver
    174      */
    175     public void setEntityResolver(EntityResolver resolver)
    176     {
    177     }
    178
    179     /***
    180      * Returns the error handler. This class does not support an error handler,
    181      * so this method always returns <b>null</b>.
    182      *
    183      * @return the error handler
    184      */
    185     public ErrorHandler getErrorHandler()
    186     {
    187         return null;
    188     }
    189
    190     /***
    191      * Sets the error handler. The passed value is ignored.
    192      *
    193      * @param handler the error handler
    194      */
    195     public void setErrorHandler(ErrorHandler handler)
    196     {
    197     }
    198
    199     /***
    200      * Dummy implementation of the interface method. No properties are
    201      * supported, so this method always returns <b>null</b>.
    202      *
    203      * @param name the name of the requested property
    204      * @return the property value
    205      */
    206     public Object getProperty(String name)
    207     {
    208         return null;
    209     }
    210
    211     /***
    212      * Dummy implementation of the interface method. No properties are
    213      * supported, so a call of this method just has no effect.
    214      *
    215      * @param name the property name
    216      * @param value the property value
    217      */
    218     public void setProperty(String name, Object value)
    219     {
    220     }
    221
    222     /***
    223      * Returns the name to be used for the root element.
    224      *
    225      * @return the name for the root element
    226      */
    227     public String getRootName()
    228     {
    229         return rootName;
    230     }
    231
    232     /***
    233      * Sets the name for the root element.
    234      *
    235      * @param string the name for the root element.
    236      */
    237     public void setRootName(String string)
    238     {
    239         rootName = string;
    240     }
    241
    242     /***
    243      * Fires a SAX element start event.
    244      *
    245      * @param name the name of the actual element
    246      * @param attribs the attributes of this element (can be <b>null</b>)
    247      */
    248     protected void fireElementStart(String name, Attributes attribs)
    249     {
    250         if (getException() == null)
    251         {
    252             try
    253             {
    254                 Attributes at = (attribs == null) ? EMPTY_ATTRS : attribs;
    255                 getContentHandler().startElement(NS_URI, name, name, at);
    256             }
    257             catch (SAXException ex)
    258             {
    259                 exception = ex;
    260             }
    261         }
    262     }
    263
    264     /***
    265      * Fires a SAX element end event.
    266      *
    267      * @param name the name of the affected element
    268      */
    269     protected void fireElementEnd(String name)
    270     {
    271         if (getException() == null)
    272         {
    273             try
    274             {
    275                 getContentHandler().endElement(NS_URI, name, name);
    276             }
    277             catch (SAXException ex)
    278             {
    279                 exception = ex;
    280             }
    281         }
    282     }
    283
    284     /***
    285      * Fires a SAX characters event.
    286      *
    287      * @param text the text
    288      */
    289     protected void fireCharacters(String text)
    290     {
    291         if (getException() == null)
    292         {
    293             try
    294             {
    295                 char[] ch = text.toCharArray();
    296                 getContentHandler().characters(ch, 0, ch.length);
    297             }
    298             catch (SAXException ex)
    299             {
    300                 exception = ex;
    301             }
    302         }
    303     }
    304
    305     /***
    306      * Returns a reference to an exception that occurred during parsing.
    307      *
    308      * @return a SAXExcpetion or <b>null</b> if none occurred
    309      */
    310     public SAXException getException()
    311     {
    312         return exception;
    313     }
    314
    315     /***
    316      * Parses the configuration object and generates SAX events. This is the
    317      * main processing method.
    318      *
    319      * @throws IOException if no configuration has been specified
    320      * @throws SAXException if an error occurs during parsing
    321      */
    322     protected void parseConfiguration() throws IOException, SAXException
    323     {
    324         if (getParsedConfiguration() == null)
    325         {
    326             throw new IOException("No configuration specified!");
    327         }
    328
    329         if (getContentHandler() != null)
    330         {
    331             exception = null;
    332             getContentHandler().startDocument();
    333             processKeys();
    334             if (getException() != null)
    335             {
    336                 throw getException();
    337             }
    338             getContentHandler().endDocument();
    339         }
    340     }
    341
    342     /***
    343      * Returns a reference to the configuration that is parsed by this object.
    344      *
    345      * @return the parsed configuration
    346      */
    347     public abstract Configuration getParsedConfiguration();
    348
    349     /***
    350      * Processes all keys stored in the actual configuration. This method is
    351      * called by <code>parseConfiguration()</code> to start the main parsing
    352      * process. <code>parseConfiguration()</code> calls the content handler's
    353      * <code>startDocument()</code> and <code>endElement()</code> methods
    354      * and cares for exception handling. The remaining actions are left to this
    355      * method that must be implemented in a concrete sub class.
    356      *
    357      * @throws IOException if an IO error occurs
    358      * @throws SAXException if a SAX error occurs
    359      */
    360     protected abstract void processKeys() throws IOException, SAXException;
    361 }