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