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.File;
21 import java.io.PrintWriter;
22 import java.io.Reader;
23 import java.io.Writer;
24 import java.net.URL;
25 import java.util.Iterator;
26 import java.util.List;
27
28 import javax.xml.parsers.SAXParser;
29 import javax.xml.parsers.SAXParserFactory;
30
31 import org.apache.commons.lang.StringEscapeUtils;
32 import org.apache.commons.lang.StringUtils;
33 import org.xml.sax.Attributes;
34 import org.xml.sax.EntityResolver;
35 import org.xml.sax.InputSource;
36 import org.xml.sax.XMLReader;
37 import org.xml.sax.helpers.DefaultHandler;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class XMLPropertiesConfiguration extends PropertiesConfiguration
70 {
71
72
73
74 private static final String DEFAULT_ENCODING = "UTF-8";
75
76
77 {
78 setEncoding(DEFAULT_ENCODING);
79 }
80
81
82
83
84
85
86
87
88 public XMLPropertiesConfiguration()
89 {
90 super();
91 }
92
93
94
95
96
97
98
99
100
101 public XMLPropertiesConfiguration(String fileName) throws ConfigurationException
102 {
103 super(fileName);
104 }
105
106
107
108
109
110
111
112
113
114 public XMLPropertiesConfiguration(File file) throws ConfigurationException
115 {
116 super(file);
117 }
118
119
120
121
122
123
124
125
126
127 public XMLPropertiesConfiguration(URL url) throws ConfigurationException
128 {
129 super(url);
130 }
131
132 @Override
133 public void load(Reader in) throws ConfigurationException
134 {
135 SAXParserFactory factory = SAXParserFactory.newInstance();
136 factory.setNamespaceAware(false);
137 factory.setValidating(true);
138
139 try
140 {
141 SAXParser parser = factory.newSAXParser();
142
143 XMLReader xmlReader = parser.getXMLReader();
144 xmlReader.setEntityResolver(new EntityResolver()
145 {
146 public InputSource resolveEntity(String publicId, String systemId)
147 {
148 return new InputSource(getClass().getClassLoader().getResourceAsStream("properties.dtd"));
149 }
150 });
151 xmlReader.setContentHandler(new XMLPropertiesHandler());
152 xmlReader.parse(new InputSource(in));
153 }
154 catch (Exception e)
155 {
156 throw new ConfigurationException("Unable to parse the configuration file", e);
157 }
158
159
160 }
161
162 @Override
163 public void save(Writer out) throws ConfigurationException
164 {
165 PrintWriter writer = new PrintWriter(out);
166
167 String encoding = getEncoding() != null ? getEncoding() : DEFAULT_ENCODING;
168 writer.println("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>");
169 writer.println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">");
170 writer.println("<properties>");
171
172 if (getHeader() != null)
173 {
174 writer.println(" <comment>" + StringEscapeUtils.escapeXml(getHeader()) + "</comment>");
175 }
176
177 Iterator<String> keys = getKeys();
178 while (keys.hasNext())
179 {
180 String key = keys.next();
181 Object value = getProperty(key);
182
183 if (value instanceof List)
184 {
185 writeProperty(writer, key, (List<?>) value);
186 }
187 else
188 {
189 writeProperty(writer, key, value);
190 }
191 }
192
193 writer.println("</properties>");
194 writer.flush();
195 }
196
197
198
199
200
201
202
203
204 private void writeProperty(PrintWriter out, String key, Object value)
205 {
206
207 String k = StringEscapeUtils.escapeXml(key);
208
209 if (value != null)
210 {
211
212 String v = StringEscapeUtils.escapeXml(String.valueOf(value));
213 v = StringUtils.replace(v, String.valueOf(getListDelimiter()), "\\" + getListDelimiter());
214
215 out.println(" <entry key=\"" + k + "\">" + v + "</entry>");
216 }
217 else
218 {
219 out.println(" <entry key=\"" + k + "\"/>");
220 }
221 }
222
223
224
225
226
227
228
229
230 private void writeProperty(PrintWriter out, String key, List<?> values)
231 {
232 for (Object value : values)
233 {
234 writeProperty(out, key, value);
235 }
236 }
237
238
239
240
241
242
243
244 private class XMLPropertiesHandler extends DefaultHandler
245 {
246
247 private String key;
248
249
250 private StringBuilder value = new StringBuilder();
251
252
253 private boolean inCommentElement;
254
255
256 private boolean inEntryElement;
257
258 @Override
259 public void startElement(String uri, String localName, String qName, Attributes attrs)
260 {
261 if ("comment".equals(qName))
262 {
263 inCommentElement = true;
264 }
265
266 if ("entry".equals(qName))
267 {
268 key = attrs.getValue("key");
269 inEntryElement = true;
270 }
271 }
272
273 @Override
274 public void endElement(String uri, String localName, String qName)
275 {
276 if (inCommentElement)
277 {
278
279 setHeader(value.toString());
280 inCommentElement = false;
281 }
282
283 if (inEntryElement)
284 {
285
286 addProperty(key, value.toString());
287 inEntryElement = false;
288 }
289
290
291 value = new StringBuilder();
292 }
293
294 @Override
295 public void characters(char[] chars, int start, int length)
296 {
297
298
299
300
301 value.append(chars, start, length);
302 }
303 }
304 }