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