1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 "faked" <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 }