1
2
3
4
5
6
7
8 package org.dom4j.jaxb;
9
10 import java.io.File;
11 import java.io.FileInputStream;
12 import java.io.FileNotFoundException;
13 import java.io.FileOutputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.InputStreamReader;
17 import java.io.OutputStream;
18 import java.io.Reader;
19 import java.io.Writer;
20 import java.net.URL;
21 import java.nio.charset.Charset;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.Map;
25
26 import org.dom4j.Document;
27 import org.dom4j.DocumentException;
28 import org.dom4j.io.ElementModifier;
29 import org.dom4j.io.OutputFormat;
30 import org.dom4j.io.SAXModifier;
31 import org.dom4j.io.XMLWriter;
32
33 import org.xml.sax.InputSource;
34
35 /***
36 * Reads an XML document using SAX and writes its content to the provided
37 * {@link org.dom4j.io.XMLWriter}. Modifications must be provided by {@link
38 * org.dom4j.jaxb.JAXBObjectModifier} objects, which are called prior to writing
39 * the XML fragment they are registered for.
40 *
41 * @author Wonne Keysers (Realsoftware.be)
42 *
43 * @see org.dom4j.io.SAXModifier
44 */
45 public class JAXBModifier extends JAXBSupport {
46 private SAXModifier modifier;
47
48 private XMLWriter xmlWriter;
49
50 private boolean pruneElements;
51
52 private OutputFormat outputFormat;
53
54 private HashMap modifiers = new HashMap();
55
56 /***
57 * Creates a new JAXBModifier for the given JAXB context path. This is the
58 * Java package where JAXB can find the generated XML classes. This package
59 * MUST contain jaxb.properties!
60 *
61 * @param contextPath
62 * JAXB context path to be used
63 *
64 * @see javax.xml.bind.JAXBContext
65 */
66 public JAXBModifier(String contextPath) {
67 super(contextPath);
68 this.outputFormat = new OutputFormat();
69 }
70
71 /***
72 * Creates a new JAXBModifier for the given JAXB context path, using the
73 * given {@link java.lang.ClassLoader}. This is the Java package where JAXB
74 * can find the generated XML classes. This package MUST contain
75 * jaxb.properties!
76 *
77 * @param contextPath
78 * JAXB context path to be used
79 * @param classloader
80 * the classloader to use
81 *
82 * @see javax.xml.bind.JAXBContext
83 */
84 public JAXBModifier(String contextPath, ClassLoader classloader) {
85 super(contextPath, classloader);
86 this.outputFormat = new OutputFormat();
87 }
88
89 /***
90 * Creates a new JAXBModifier for the given JAXB context path. The specified
91 * {@link org.dom4j.io.OutputFormat}will be used while writing the XML
92 * stream.
93 *
94 * @param contextPath
95 * JAXB context path to be used
96 * @param outputFormat
97 * the DOM4J {@link org.dom4j.io.OutputFormat}to be used
98 *
99 * @see javax.xml.bind.JAXBContext
100 */
101 public JAXBModifier(String contextPath, OutputFormat outputFormat) {
102 super(contextPath);
103 this.outputFormat = outputFormat;
104 }
105
106 /***
107 * Creates a new JAXBModifier for the given JAXB context path, using the
108 * specified {@link java.lang.Classloader}. The specified {@link
109 * org.dom4j.io.OutputFormat} will be used while writing the XML stream.
110 *
111 * @param contextPath
112 * JAXB context path to be used
113 * @param classloader
114 * the class loader to be used to load JAXB
115 * @param outputFormat
116 * the DOM4J {@link org.dom4j.io.OutputFormat}to be used
117 *
118 * @see javax.xml.bind.JAXBContext
119 */
120 public JAXBModifier(String contextPath, ClassLoader classloader,
121 OutputFormat outputFormat) {
122 super(contextPath, classloader);
123 this.outputFormat = outputFormat;
124 }
125
126 /***
127 * Parses the specified {@link java.io.File}with SAX
128 *
129 * @param source
130 * the file to parse
131 *
132 * @return the resulting DOM4J document
133 *
134 * @throws DocumentException
135 * when an error occurs while parsing
136 * @throws IOException
137 * when an error occurs while writing to the {@link
138 * org.dom4j.io.XMLWriter}
139 */
140 public Document modify(File source) throws DocumentException, IOException {
141 return installModifier().modify(source);
142 }
143
144 /***
145 * Parses the specified {@link java.io.File}with SAX, using the given
146 * {@link java.nio.charset.Charset}.
147 *
148 * @param source
149 * the file to parse
150 * @param charset
151 * the character set to use
152 *
153 * @return the resulting DOM4J document
154 *
155 * @throws DocumentException
156 * when an error occurs while parsing
157 * @throws IOException
158 * when an error occurs while writing to the {@link
159 * org.dom4j.io.XMLWriter}
160 */
161 public Document modify(File source, Charset charset)
162 throws DocumentException, IOException {
163 try {
164 Reader reader = new InputStreamReader(new FileInputStream(source),
165 charset);
166
167 return installModifier().modify(reader);
168 } catch (JAXBRuntimeException ex) {
169 Throwable cause = ex.getCause();
170 throw new DocumentException(cause.getMessage(), cause);
171 } catch (FileNotFoundException ex) {
172 throw new DocumentException(ex.getMessage(), ex);
173 }
174 }
175
176 /***
177 * Parses the specified {@link org.xml.sax.InputSource}with SAX.
178 *
179 * @param source
180 * the input source to parse
181 *
182 * @return the resulting DOM4J document
183 *
184 * @throws DocumentException
185 * when an error occurs while parsing
186 * @throws IOException
187 * when an error occurs while writing to the {@link
188 * org.dom4j.io.XMLWriter}
189 */
190 public Document modify(InputSource source) throws DocumentException,
191 IOException {
192 try {
193 return installModifier().modify(source);
194 } catch (JAXBRuntimeException ex) {
195 Throwable cause = ex.getCause();
196 throw new DocumentException(cause.getMessage(), cause);
197 }
198 }
199
200 /***
201 * Parses the specified {@link java.io.InputStream}with SAX.
202 *
203 * @param source
204 * the inputstream to parse
205 *
206 * @return the resulting DOM4J document
207 *
208 * @throws DocumentException
209 * when an error occurs while parsing
210 * @throws IOException
211 * when an error occurs while writing to the {@link
212 * org.dom4j.io.XMLWriter}
213 */
214 public Document modify(InputStream source) throws DocumentException,
215 IOException {
216 try {
217 return installModifier().modify(source);
218 } catch (JAXBRuntimeException ex) {
219 Throwable cause = ex.getCause();
220 throw new DocumentException(cause.getMessage(), cause);
221 }
222 }
223
224 /***
225 * Parses the specified {@link java.io.InputStream}with SAX.
226 *
227 * @param source
228 * the inputstream to parse
229 * @param systemId
230 * the URI of the given inputstream
231 *
232 * @return the resulting DOM4J document
233 *
234 * @throws DocumentException
235 * when an error occurs while parsing
236 * @throws IOException
237 * when an error occurs while writing to the {@link
238 * org.dom4j.io.XMLWriter}
239 */
240 public Document modify(InputStream source, String systemId)
241 throws DocumentException, IOException {
242 try {
243 return installModifier().modify(source);
244 } catch (JAXBRuntimeException ex) {
245 Throwable cause = ex.getCause();
246 throw new DocumentException(cause.getMessage(), cause);
247 }
248 }
249
250 /***
251 * Parses the specified {@link java.io.Reader}with SAX.
252 *
253 * @param r
254 * the reader to use for parsing
255 *
256 * @return the resulting DOM4J document
257 *
258 * @throws DocumentException
259 * when an error occurs while parsing
260 * @throws IOException
261 * when an error occurs while writing to the {@link
262 * org.dom4j.io.XMLWriter}
263 */
264 public Document modify(Reader r) throws DocumentException, IOException {
265 try {
266 return installModifier().modify(r);
267 } catch (JAXBRuntimeException ex) {
268 Throwable cause = ex.getCause();
269 throw new DocumentException(cause.getMessage(), cause);
270 }
271 }
272
273 /***
274 * Parses the specified {@link java.io.Reader}with SAX.
275 *
276 * @param source
277 * the reader to parse
278 * @param systemId
279 * the URI of the given reader
280 *
281 * @return the resulting DOM4J document
282 *
283 * @throws DocumentException
284 * when an error occurs while parsing
285 * @throws IOException
286 * when an error occurs while writing to the {@link
287 * org.dom4j.io.XMLWriter}
288 */
289 public Document modify(Reader source, String systemId)
290 throws DocumentException, IOException {
291 try {
292 return installModifier().modify(source);
293 } catch (JAXBRuntimeException ex) {
294 Throwable cause = ex.getCause();
295 throw new DocumentException(cause.getMessage(), cause);
296 }
297 }
298
299 /***
300 * Parses the the given URL or filename.
301 *
302 * @param url
303 * the URL or filename to parse
304 *
305 * @return the resulting DOM4J document
306 *
307 * @throws DocumentException
308 * when an error occurs while parsing
309 * @throws IOException
310 * when an error occurs while writing to the {@link
311 * org.dom4j.io.XMLWriter}
312 */
313 public Document modify(String url) throws DocumentException, IOException {
314 try {
315 return installModifier().modify(url);
316 } catch (JAXBRuntimeException ex) {
317 Throwable cause = ex.getCause();
318 throw new DocumentException(cause.getMessage(), cause);
319 }
320 }
321
322 /***
323 * Parses the the given URL.
324 *
325 * @param source
326 * the URL to parse
327 *
328 * @return the resulting DOM4J document
329 *
330 * @throws DocumentException
331 * when an error occurs while parsing
332 * @throws IOException
333 * when an error occurs while writing to the {@link
334 * org.dom4j.io.XMLWriter}
335 */
336 public Document modify(URL source) throws DocumentException, IOException {
337 try {
338 return installModifier().modify(source);
339 } catch (JAXBRuntimeException ex) {
340 Throwable cause = ex.getCause();
341 throw new DocumentException(cause.getMessage(), cause);
342 }
343 }
344
345 /***
346 * Sets the Output to write the (modified) xml document to.
347 *
348 * @param file
349 * the {@link java.io.File}to write to
350 *
351 * @throws IOException
352 * when the file cannot be found or when the outputformat
353 */
354 public void setOutput(File file) throws IOException {
355 createXMLWriter().setOutputStream(new FileOutputStream(file));
356 }
357
358 /***
359 * Sets the Output to write the (modified) xml document to.
360 *
361 * @param outputStream
362 * the {@link java.io.OutputStream}to write to
363 *
364 * @throws IOException
365 * when an error occurs
366 */
367 public void setOutput(OutputStream outputStream) throws IOException {
368 createXMLWriter().setOutputStream(outputStream);
369 }
370
371 /***
372 * Sets the Output to write the (modified) xml document to.
373 *
374 * @param writer
375 * the {@link java.io.Writer}to write to
376 *
377 * @throws IOException
378 * when an error occurs
379 */
380 public void setOutput(Writer writer) throws IOException {
381 createXMLWriter().setWriter(writer);
382 }
383
384 /***
385 * Adds the {@link JAXBObjectModifier}to be called when the specified xml
386 * path is encounted while parsing the source.
387 *
388 * @param path
389 * the element path to listen for
390 * @param mod
391 * the modifier to register
392 */
393 public void addObjectModifier(String path, JAXBObjectModifier mod) {
394 modifiers.put(path, mod);
395 }
396
397 /***
398 * Removes the {@link JAXBObjectModifier}from the event based processor,
399 * for the specified element path.
400 *
401 * @param path
402 * the xml path to remove the modifier for
403 */
404 public void removeObjectModifier(String path) {
405 modifiers.remove(path);
406 getModifier().removeModifier(path);
407 }
408
409 /***
410 * Removes all registered {@link JAXBObjectModifier}instances from the
411 * event based processor.
412 */
413 public void resetObjectModifiers() {
414 modifiers.clear();
415 getModifier().resetModifiers();
416 }
417
418 /***
419 * Returns true when the modified {@link org.dom4j.Document}is not kept in
420 * memory.
421 *
422 * @return Returns true if elements are pruned.
423 */
424 public boolean isPruneElements() {
425 return pruneElements;
426 }
427
428 /***
429 * Define whether the modified {@link org.dom4j.Document}must only be
430 * written to the output and pruned from the DOM4J tree.
431 *
432 * @param pruneElements
433 * When true, elements will not be kept in memory
434 */
435 public void setPruneElements(boolean pruneElements) {
436 this.pruneElements = pruneElements;
437 }
438
439 private SAXModifier installModifier() throws IOException {
440 modifier = new SAXModifier(isPruneElements());
441
442 modifier.resetModifiers();
443
444 Iterator modifierIt = modifiers.entrySet().iterator();
445
446 while (modifierIt.hasNext()) {
447 Map.Entry entry = (Map.Entry) modifierIt.next();
448 ElementModifier mod = new JAXBElementModifier(this,
449 (JAXBObjectModifier) entry.getValue());
450 getModifier().addModifier((String) entry.getKey(), mod);
451 }
452
453 modifier.setXMLWriter(getXMLWriter());
454
455 return modifier;
456 }
457
458 private SAXModifier getModifier() {
459 if (this.modifier == null) {
460 modifier = new SAXModifier(isPruneElements());
461 }
462
463 return modifier;
464 }
465
466 private XMLWriter getXMLWriter() {
467 return xmlWriter;
468 }
469
470 private XMLWriter createXMLWriter() throws IOException {
471 if (this.xmlWriter == null) {
472 xmlWriter = new XMLWriter(outputFormat);
473 }
474
475 return xmlWriter;
476 }
477
478 private class JAXBElementModifier implements ElementModifier {
479 private JAXBModifier jaxbModifier;
480
481 private JAXBObjectModifier objectModifier;
482
483 public JAXBElementModifier(JAXBModifier jaxbModifier,
484 JAXBObjectModifier objectModifier) {
485 this.jaxbModifier = jaxbModifier;
486 this.objectModifier = objectModifier;
487 }
488
489 public org.dom4j.Element modifyElement(org.dom4j.Element element)
490 throws Exception {
491 javax.xml.bind.Element originalObject = jaxbModifier
492 .unmarshal(element);
493 javax.xml.bind.Element modifiedObject = objectModifier
494 .modifyObject(originalObject);
495
496 return jaxbModifier.marshal(modifiedObject);
497 }
498 }
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536