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 }