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 155408 2005-02-26 12:56:39Z dirkv $
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 }