1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.smartlab.config;
24
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.ObjectInputStream;
30 import java.io.ObjectOutputStream;
31 import java.io.StringReader;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34 import java.security.InvalidKeyException;
35 import java.security.Key;
36 import java.security.NoSuchAlgorithmException;
37
38 import javax.crypto.Cipher;
39 import javax.crypto.CipherInputStream;
40 import javax.crypto.CipherOutputStream;
41 import javax.crypto.KeyGenerator;
42 import javax.crypto.NoSuchPaddingException;
43 import javax.crypto.spec.SecretKeySpec;
44 import javax.xml.parsers.SAXParserFactory;
45
46 import org.xml.sax.Attributes;
47 import org.xml.sax.InputSource;
48 import org.xml.sax.Locator;
49 import org.xml.sax.SAXException;
50 import org.xml.sax.XMLReader;
51 import org.xml.sax.helpers.DefaultHandler;
52
53
54
55
56
57
58 public final class XMLConfiguration extends Configuration {
59
60
61
62
63
64 private long access;
65
66
67
68
69 private URL source;
70
71
72
73
74 private Cipher cipher;
75
76
77
78
79
80
81
82
83
84
85 public XMLConfiguration(File source) throws ConfigurationException {
86 try {
87 this.source = source.toURL();
88 } catch (MalformedURLException murle) {
89 throw new ConfigurationException(murle);
90 }
91 this.update();
92 }
93
94
95
96
97
98
99
100
101
102
103 public XMLConfiguration(String source) throws ConfigurationException {
104 this(new File(source));
105 }
106
107
108
109
110
111
112
113
114
115
116 public XMLConfiguration(URL source) throws ConfigurationException {
117 this(source, null);
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132 public XMLConfiguration(File source, Cipher cipher) throws ConfigurationException {
133 try {
134 this.source = source.toURL();
135 } catch (MalformedURLException murle) {
136 throw new ConfigurationException(murle);
137 }
138 this.cipher = cipher;
139 this.update();
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 public XMLConfiguration(String source, Cipher cipher) throws ConfigurationException {
156 this(new File(source), cipher);
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 public XMLConfiguration(URL source, Cipher cipher) throws ConfigurationException {
174 this.cipher = cipher;
175 this.source = source;
176 this.update();
177 }
178
179
180
181
182 public boolean isChanged() throws ConfigurationException {
183 try {
184 if (source.openConnection().getLastModified() > access) {
185 return true;
186 } else {
187 return false;
188 }
189 } catch (IOException ioe) {
190 throw new ConfigurationException(ioe);
191 }
192 }
193
194
195
196
197 public void update() throws ConfigurationException {
198 try {
199 this.access = System.currentTimeMillis();
200 this.parent = null;
201 this.children.clear();
202 SAXParserFactory factory = SAXParserFactory.newInstance();
203 if (cipher != null) {
204 factory.setValidating(true);
205 factory.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
206 factory.newSAXParser().parse(new CipherInputStream(source.openStream(), cipher), new XMLHandler(this));
207 } else {
208 factory.setValidating(true);
209 factory.setFeature("http://xml.org/sax/features/external-parameter-entities", true);
210 factory.newSAXParser().parse(source.openStream(), new XMLConfiguration.XMLHandler(this));
211 }
212 } catch (Exception e) {
213 throw new ConfigurationException(e);
214 }
215 }
216
217
218
219
220
221
222
223
224 static protected class XMLHandler extends DefaultHandler {
225
226
227
228
229 protected Element owner;
230
231
232
233
234 protected Locator locator;
235
236
237
238
239 protected XMLReader reader;
240
241
242
243
244
245
246
247 public XMLHandler(Configuration owner) {
248 this.owner = owner;
249 }
250
251
252
253
254 public void setDocumentLocator(Locator locator) {
255 this.locator = locator;
256 }
257
258
259
260
261
262 public void startElement(String namespace, String prefix, String name, Attributes attributes) {
263 try {
264 if (owner instanceof Configuration && owner.parent == null) {
265 ((Configuration)owner).init(name, attributes);
266 } else {
267 Element child = null;
268 if (attributes.getIndex(Reference.REFERENCE) > -1) {
269 child = new Reference((Node)owner, name, attributes.getValue(Reference.REFERENCE));
270 } else {
271 child = new Node((Node)owner, name, attributes);
272 }
273 ((Node)owner).children.add(child);
274 owner = child;
275 }
276 } catch (ClassCastException cce) {
277 throw new RuntimeException("Reference elements cannot have a body");
278 }
279 }
280
281
282
283
284 public void characters(char[] chars, int start, int length) {
285 try {
286 ((Node)owner).setContent(new String(chars, start, length));
287 } catch (ClassCastException cce) {
288 throw new RuntimeException("Reference elements cannot have contents");
289 }
290 }
291
292
293
294
295
296 public void endElement(String namespace, String prefix, String name) {
297 owner = owner.parent;
298 }
299
300
301
302
303
304
305
306 public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
307 try {
308 InputSource source = super.resolveEntity(publicId, systemId);
309 if (source == null) {
310 return new InputSource(new StringReader(""));
311 }
312 return source;
313 } catch (IOException ioe) {
314 throw new SAXException(ioe);
315 }
316 }
317 }
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333 public static void encrypt(File plain, File symKey, File ciphered, String algorithm) throws IOException,
334 ClassNotFoundException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
335 Key key = null;
336 try {
337 ObjectInputStream in = new ObjectInputStream(new FileInputStream(symKey));
338 key = (Key)in.readObject();
339 } catch (IOException ioe) {
340 KeyGenerator generator = KeyGenerator.getInstance(algorithm);
341 key = generator.generateKey();
342 ObjectOutputStream out = new ObjectOutputStream(new java.io.FileOutputStream(symKey));
343 out.writeObject(key);
344 out.close();
345 }
346 Cipher cipher = Cipher.getInstance(algorithm);
347 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getEncoded(), algorithm));
348 FileInputStream in = new FileInputStream(plain);
349 CipherOutputStream out = new CipherOutputStream(new FileOutputStream(ciphered), cipher);
350 byte[] buffer = new byte[4096];
351 for (int read = in.read(buffer); read > -1; read = in.read(buffer)) {
352 out.write(buffer, 0, read);
353 }
354 out.close();
355 }
356 }