1
2
3
4
5
6
7
8
9
10 package org.dom4j.jaxb;
11
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.io.FileNotFoundException;
15 import java.io.InputStream;
16 import java.io.InputStreamReader;
17 import java.io.Reader;
18 import java.net.URL;
19 import java.nio.charset.Charset;
20
21 import org.dom4j.Document;
22 import org.dom4j.DocumentException;
23 import org.dom4j.Element;
24 import org.dom4j.ElementHandler;
25 import org.dom4j.ElementPath;
26 import org.dom4j.io.SAXReader;
27 import org.xml.sax.InputSource;
28
29 /***
30 * Reads an XML document and creates a DOM4J tree from SAX parsing events.
31 * {@link JAXBObjectHandler} objects can be registered to automatically receive
32 * unmarshalled XML fragments.
33 *
34 * @see org.dom4j.io.SAXReader
35 * @see javax.xml.bind.JAXBContext
36 * @author Wonne Keysers (Realsoftware.be)
37 */
38 public class JAXBReader extends JAXBSupport {
39
40 private SAXReader reader;
41 private boolean pruneElements;
42
43 /***
44 * Creates a new JAXBReader for the given JAXB context path.
45 * This is the Java package where JAXB can find the generated XML classes.
46 * This package MUST contain jaxb.properties!
47 *
48 * @param contextPath context path to be used
49 * @see javax.xml.bind.JAXBContext
50 */
51 public JAXBReader(String contextPath) {
52 super(contextPath);
53 }
54
55 /***
56 * Creates a new JAXBReader for the given JAXB context path,
57 * using the specified {@link java.lang.Classloader}.
58 * This is the Java package where JAXB can find the generated XML classes.
59 * This package MUST contain jaxb.properties!
60 *
61 * @param contextPath to be used
62 * @param classloader to be used
63 * @see javax.xml.bind.JAXBContext
64 */
65 public JAXBReader(String contextPath, ClassLoader classloader) {
66 super(contextPath, classloader);
67 }
68
69 /***
70 * Parses the specified {@link java.io.File}
71 *
72 * @param source the file to parse
73 * @return the resulting DOM4J document
74 * @throws DocumentException when an error occurs while parsing
75 */
76 public Document read(File source) throws DocumentException {
77 return getReader().read(source);
78 }
79
80 /***
81 * Parses the specified {@link java.io.File}, using the given {@link java.nio.charset.Charset}.
82 *
83 * @param source the file to parse
84 * @param charset the charset to be used
85 * @return the resulting DOM4J document
86 * @throws DocumentException when an error occurs while parsing
87 */
88 public Document read(File source, Charset charset) throws DocumentException {
89 try {
90 return getReader().read(new InputStreamReader(new FileInputStream(source), charset));
91 }
92 catch (JAXBRuntimeException ex) {
93 Throwable cause = ex.getCause();
94 throw new DocumentException(cause.getMessage(), cause);
95 }
96 catch (FileNotFoundException ex) {
97 throw new DocumentException(ex.getMessage(), ex);
98 }
99 }
100
101 /***
102 * Parses the specified {@link org.xml.sax.InputSource}
103 *
104 * @param source the source to parse
105 * @return the resulting DOM4J document
106 * @throws DocumentException when an error occurs while parsing
107 */
108 public Document read(InputSource source) throws DocumentException {
109 try {
110 return getReader().read(source);
111 }
112 catch (JAXBRuntimeException ex) {
113 Throwable cause = ex.getCause();
114 throw new DocumentException(cause.getMessage(), cause);
115 }
116 }
117
118 /***
119 * Parses the specified {@link java.io.InputStream}
120 *
121 * @param source the input stream to parse
122 * @return the resulting DOM4J document
123 * @throws DocumentException when an error occurs while parsing
124 */
125 public Document read(InputStream source) throws DocumentException {
126 try {
127 return getReader().read(source);
128 }
129 catch (JAXBRuntimeException ex) {
130 Throwable cause = ex.getCause();
131 throw new DocumentException(cause.getMessage(), cause);
132 }
133 }
134
135 /***
136 * Parses the specified {@link java.io.InputStream}
137 *
138 * @param source the input stream to parse
139 * @param systemId is the URI for the input
140 * @return the resulting DOM4J document
141 * @throws DocumentException when an error occurs while parsing
142 */
143 public Document read(InputStream source, String systemId) throws DocumentException {
144 try {
145 return getReader().read(source);
146 }
147 catch (JAXBRuntimeException ex) {
148 Throwable cause = ex.getCause();
149 throw new DocumentException(cause.getMessage(), cause);
150 }
151 }
152
153 /***
154 * Parses the specified {@link java.io.Reader}
155 *
156 * @param source the input reader to use
157 * @return the resulting DOM4J document
158 * @throws DocumentException when an error occurs while parsing
159 */
160 public Document read(Reader source) throws DocumentException {
161 try {
162 return getReader().read(source);
163 }
164 catch (JAXBRuntimeException ex) {
165 Throwable cause = ex.getCause();
166 throw new DocumentException(cause.getMessage(), cause);
167 }
168 }
169
170 /***
171 * Parses the specified {@link java.io.Reader}
172 *
173 * @param source the input reader to parse
174 * @param systemId is the URI for the input
175 * @return the resulting DOM4J document
176 * @throws DocumentException when an error occurs while parsing
177 */
178 public Document read(Reader source, String systemId) throws DocumentException {
179 try {
180 return getReader().read(source);
181 }
182 catch (JAXBRuntimeException ex) {
183 Throwable cause = ex.getCause();
184 throw new DocumentException(cause.getMessage(), cause);
185 }
186 }
187
188 /***
189 * Parses the the given URL or filename.
190 *
191 * @param source the location to parse
192 * @return the resulting DOM4J document
193 * @throws DocumentException when an error occurs while parsing
194 */
195 public Document read(String source) throws DocumentException {
196 try {
197 return getReader().read(source);
198 }
199 catch (JAXBRuntimeException ex) {
200 Throwable cause = ex.getCause();
201 throw new DocumentException(cause.getMessage(), cause);
202 }
203 }
204
205 /***
206 * Parses the the given URL.
207 *
208 * @param source the URL to parse
209 * @return the resulting DOM4J document
210 * @throws DocumentException when an error occurs while parsing
211 */
212 public Document read(URL source) throws DocumentException {
213 try {
214 return getReader().read(source);
215 }
216 catch (JAXBRuntimeException ex) {
217 Throwable cause = ex.getCause();
218 throw new DocumentException(cause.getMessage(), cause);
219 }
220 }
221
222 /***
223 * Registers a {@link JAXBObjectHandler} that will be supplied with the unmarshalled representation
224 * of the xml fragment whenever the specified path is encounted.
225 *
226 * @param path the path to listen for
227 * @param handler the handler to be notified
228 */
229 public void addObjectHandler(String path, JAXBObjectHandler handler) {
230 getReader().addHandler(path, new UnmarshalElementHandler(this, handler));
231 }
232
233 /***
234 * Removes the {@link JAXBObjectHandler} from the event based processor,
235 * for the specified element path.
236 *
237 * @param path The path to remove the {@link JAXBObjectHandler} for
238 */
239 public void removeObjectHandler(String path) {
240 getReader().removeHandler(path);
241 }
242
243 /***
244 * Removes all registered {@link JAXBObjectHandler} instances from the event based processor.
245 */
246 public void resetObjectHandlers() {
247 getReader().resetHandlers();
248 }
249
250 /***
251 * When 'true', the DOM4J document will not be kept in memory while parsing.
252 *
253 * @return Returns the pruneElements.
254 */
255 public boolean isPruneElements() {
256 return pruneElements;
257 }
258
259 /***
260 * Set to true when DOM4J elements must immediately be pruned from the tree.
261 * The {@link Document} will not be available afterwards!
262 *
263 * @param pruneElements
264 */
265 public void setPruneElements(boolean pruneElements) {
266 this.pruneElements = pruneElements;
267 if (pruneElements) {
268 getReader().setDefaultHandler(new PruningElementHandler());
269 }
270 }
271
272 private SAXReader getReader() {
273 if (reader == null) {
274 reader = new SAXReader();
275 }
276 return reader;
277 }
278
279 private class UnmarshalElementHandler implements ElementHandler {
280
281 private JAXBReader jaxbReader;
282 private JAXBObjectHandler handler;
283
284 public UnmarshalElementHandler(JAXBReader documentReader, JAXBObjectHandler handler) {
285 this.jaxbReader = documentReader;
286 this.handler = handler;
287 }
288
289 public void onStart(ElementPath elementPath) {
290 }
291
292 public void onEnd(ElementPath elementPath) {
293 try {
294 org.dom4j.Element elem = elementPath.getCurrent();
295
296 javax.xml.bind.Element jaxbObject = (javax.xml.bind.Element) jaxbReader.unmarshal(elem);
297
298 if (jaxbReader.isPruneElements()) {
299 elem.detach();
300 }
301
302 handler.handleObject(jaxbObject);
303 }
304 catch (Exception ex) {
305 throw new JAXBRuntimeException(ex);
306 }
307 }
308
309 }
310
311 private class PruningElementHandler implements ElementHandler {
312
313 public PruningElementHandler() {
314 }
315
316 public void onStart(ElementPath parm1) {
317 }
318
319 public void onEnd(ElementPath elementPath) {
320 Element elem = elementPath.getCurrent();
321 elem.detach();
322 elem = null;
323 }
324
325 }
326
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375