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.File;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.io.Reader;
23 import java.io.Writer;
24 import java.net.URL;
25 import javax.xml.parsers.DocumentBuilder;
26 import javax.xml.parsers.DocumentBuilderFactory;
27
28 import org.w3c.dom.Attr;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.NamedNodeMap;
32 import org.w3c.dom.NodeList;
33 import org.w3c.dom.Text;
34 import org.xml.sax.InputSource;
35
36 /***
37 * A specialized hierarchical configuration class that is able to parse
38 * XML documents.
39 *
40 * <p>The parsed document will be stored keeping its structure. The
41 * contained properties can be accessed using all methods supported by
42 * the base class <code>HierarchicalConfiguration</code>.
43 *
44 * @since commons-configuration 1.0
45 *
46 * @author Jörg Schaible
47 * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
48 * @version $Revision: 1.3 $, $Date: 2004/09/22 17:17:30 $
49 */
50 public class HierarchicalXMLConfiguration extends HierarchicalConfiguration implements FileConfiguration
51 {
52 private FileConfiguration delegate = new FileConfigurationDelegate();
53
54 /***
55 * Initializes this configuration from an XML document.
56 *
57 * @param document the document to be parsed
58 */
59 public void initProperties(Document document)
60 {
61 constructHierarchy(getRoot(), document.getDocumentElement());
62 }
63
64 /***
65 * Helper method for building the internal storage hierarchy. The XML
66 * elements are transformed into node objects.
67 *
68 * @param node the actual node
69 * @param element the actual XML element
70 */
71 private void constructHierarchy(Node node, Element element)
72 {
73 StringBuffer buffer = new StringBuffer();
74 NodeList list = element.getChildNodes();
75 for (int i = 0; i < list.getLength(); i++)
76 {
77 org.w3c.dom.Node w3cNode = list.item(i);
78 if (w3cNode instanceof Element)
79 {
80 Element child = (Element) w3cNode;
81 Node childNode = new Node(child.getTagName());
82 constructHierarchy(childNode, child);
83 node.addChild(childNode);
84 processAttributes(childNode, child);
85 }
86 else if (w3cNode instanceof Text)
87 {
88 Text data = (Text) w3cNode;
89 buffer.append(data.getData());
90 }
91 }
92 String text = buffer.toString().trim();
93 if (text.length() > 0)
94 {
95 node.setValue(text);
96 }
97 }
98
99 /***
100 * Helper method for constructing node objects for the attributes of the
101 * given XML element.
102 *
103 * @param node the actual node
104 * @param element the actual XML element
105 */
106 private void processAttributes(Node node, Element element)
107 {
108 NamedNodeMap attributes = element.getAttributes();
109 for (int i = 0; i < attributes.getLength(); ++i)
110 {
111 org.w3c.dom.Node w3cNode = attributes.item(i);
112 if (w3cNode instanceof Attr)
113 {
114 Attr attr = (Attr) w3cNode;
115 Node child =
116 new Node(
117 ConfigurationKey.constructAttributeKey(attr.getName()));
118 child.setValue(attr.getValue());
119 node.addChild(child);
120 }
121 }
122 }
123
124 public void load() throws ConfigurationException
125 {
126 delegate.load();
127 }
128
129 public void load(String fileName) throws ConfigurationException
130 {
131 delegate.load(fileName);
132 }
133
134 public void load(File file) throws ConfigurationException
135 {
136 delegate.load(file);
137 }
138
139 public void load(URL url) throws ConfigurationException
140 {
141 delegate.load(url);
142 }
143
144 public void load(InputStream in) throws ConfigurationException
145 {
146 delegate.load(in);
147 }
148
149 public void load(InputStream in, String encoding) throws ConfigurationException
150 {
151 delegate.load(in, encoding);
152 }
153
154 public void load(Reader in) throws ConfigurationException
155 {
156 try
157 {
158 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
159 initProperties(builder.parse(new InputSource(in)));
160 }
161 catch (Exception e)
162 {
163 throw new ConfigurationException(e.getMessage(), e);
164 }
165 }
166
167 public void save() throws ConfigurationException
168 {
169 delegate.save();
170 }
171
172 public void save(String fileName) throws ConfigurationException
173 {
174 delegate.save(fileName);
175 }
176
177 public void save(File file) throws ConfigurationException
178 {
179 delegate.save(file);
180 }
181
182 public void save(URL url) throws ConfigurationException
183 {
184 delegate.save(url);
185 }
186
187 public void save(OutputStream out) throws ConfigurationException
188 {
189 delegate.save(out);
190 }
191
192 public void save(OutputStream out, String encoding) throws ConfigurationException
193 {
194 delegate.save(out, encoding);
195 }
196
197 public void save(Writer out) throws ConfigurationException
198 {
199 throw new UnsupportedOperationException("Can't save HierarchicalXMLConfigurations");
200 }
201
202 public String getFileName()
203 {
204 return delegate.getFileName();
205 }
206
207 public void setFileName(String fileName)
208 {
209 delegate.setFileName(fileName);
210 }
211
212 public String getBasePath()
213 {
214 return delegate.getBasePath();
215 }
216
217 public void setBasePath(String basePath)
218 {
219 delegate.setBasePath(basePath);
220 }
221
222 public File getFile()
223 {
224 return delegate.getFile();
225 }
226
227 public void setFile(File file)
228 {
229 delegate.setFile(file);
230 }
231
232 public URL getURL()
233 {
234 return delegate.getURL();
235 }
236
237 public void setURL(URL url)
238 {
239 delegate.setURL(url);
240 }
241
242 private class FileConfigurationDelegate extends AbstractFileConfiguration {
243
244 public void load(Reader in) throws ConfigurationException
245 {
246 HierarchicalXMLConfiguration.this.load(in);
247 }
248
249 public void save(Writer out) throws ConfigurationException
250 {
251 HierarchicalXMLConfiguration.this.save(out);
252 }
253
254 }
255 }