View Javadoc

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