Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ConfigurationXMLReader |
|
| 1.4583333333333333;1,458 |
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 "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 | 2 | 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 | 7 | super(); |
69 | 7 | setRootName(DEFAULT_ROOT_NAME); |
70 | 7 | } |
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 | 2 | parseConfiguration(); |
83 | 0 | } |
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 | 3 | parseConfiguration(); |
96 | 3 | } |
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 | 0 | 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 | 3 | } |
118 | ||
119 | /** | |
120 | * Returns the actually set content handler. | |
121 | * | |
122 | * @return the content handler | |
123 | */ | |
124 | public ContentHandler getContentHandler() | |
125 | { | |
126 | 228 | 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 | 4 | contentHandler = handler; |
138 | 4 | } |
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 | 0 | 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 | 3 | } |
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 | 0 | 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 | 0 | } |
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 | 0 | 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 | 0 | } |
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 | 0 | 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 | 12 | } |
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 | 8 | 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 | 8 | rootName = string; |
241 | 8 | } |
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 | 101 | if (getException() == null) |
252 | { | |
253 | try | |
254 | { | |
255 | 84 | Attributes at = (attribs == null) ? EMPTY_ATTRS : attribs; |
256 | 84 | getContentHandler().startElement(NS_URI, name, name, at); |
257 | 84 | } |
258 | catch (SAXException ex) | |
259 | { | |
260 | 0 | exception = ex; |
261 | } | |
262 | } | |
263 | 101 | } |
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 | 101 | if (getException() == null) |
273 | { | |
274 | try | |
275 | { | |
276 | 80 | getContentHandler().endElement(NS_URI, name, name); |
277 | 80 | } |
278 | catch (SAXException ex) | |
279 | { | |
280 | 0 | exception = ex; |
281 | } | |
282 | } | |
283 | 101 | } |
284 | ||
285 | /** | |
286 | * Fires a SAX characters event. | |
287 | * | |
288 | * @param text the text | |
289 | */ | |
290 | protected void fireCharacters(String text) | |
291 | { | |
292 | 67 | if (getException() == null) |
293 | { | |
294 | try | |
295 | { | |
296 | 53 | char[] ch = text.toCharArray(); |
297 | 53 | getContentHandler().characters(ch, 0, ch.length); |
298 | 52 | } |
299 | catch (SAXException ex) | |
300 | { | |
301 | 1 | exception = ex; |
302 | } | |
303 | } | |
304 | 67 | } |
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 | 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 | 5 | if (getParsedConfiguration() == null) |
326 | { | |
327 | 1 | throw new IOException("No configuration specified!"); |
328 | } | |
329 | ||
330 | 4 | if (getContentHandler() != null) |
331 | { | |
332 | 4 | exception = null; |
333 | 4 | getContentHandler().startDocument(); |
334 | 4 | processKeys(); |
335 | 4 | if (getException() != null) |
336 | { | |
337 | 1 | throw getException(); |
338 | } | |
339 | 3 | getContentHandler().endDocument(); |
340 | } | |
341 | 3 | } |
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 | } |