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