KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > xml > bind > JAXB


1 package javax.xml.bind;
2
3 import javax.xml.bind.annotation.XmlRootElement;
4 import javax.xml.namespace.QName JavaDoc;
5 import javax.xml.transform.Result JavaDoc;
6 import javax.xml.transform.Source JavaDoc;
7 import javax.xml.transform.stream.StreamResult JavaDoc;
8 import javax.xml.transform.stream.StreamSource JavaDoc;
9 import java.beans.Introspector JavaDoc;
10 import java.io.File JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.io.Reader JavaDoc;
15 import java.io.Writer JavaDoc;
16 import java.lang.ref.WeakReference JavaDoc;
17 import java.net.HttpURLConnection JavaDoc;
18 import java.net.URI JavaDoc;
19 import java.net.URISyntaxException JavaDoc;
20 import java.net.URL JavaDoc;
21 import java.net.URLConnection JavaDoc;
22
23 /**
24  * Class that defines convenience methods for common, simple use of JAXB.
25  *
26  * <p>
27  * Methods defined in this class are convenience methods that combine several basic operations
28  * in the {@link JAXBContext}, {@link Unmarshaller}, and {@link Marshaller}.
29  *
30  * They are designed
31  * to be the prefered methods for developers new to JAXB. They have
32  * the following characterstics:
33  *
34  * <ol>
35  * <li>Generally speaking, the performance is not necessarily optimal.
36  * It is expected that people who need to write performance
37  * critical code will use the rest of the JAXB API directly.
38  * <li>Errors that happen during the processing is wrapped into
39  * {@link DataBindingException} (which will have {@link JAXBException}
40  * as its {@link Throwable#getCause() cause}. It is expected that
41  * people who prefer the checked exception would use
42  * the rest of the JAXB API directly.
43  * </ol>
44  *
45  * <p>
46  * In addition, the <tt>unmarshal</tt> methods have the following characteristic:
47  *
48  * <ol>
49  * <li>Schema validation is not performed on the input XML.
50  * The processing will try to continue even if there
51  * are errors in the XML, as much as possible. Only as
52  * the last resort, this method fails with {@link DataBindingException}.
53  * </ol>
54  *
55  * <p>
56  * Similarly, the <tt>marshal</tt> methods have the following characteristic:
57  * <ol>
58  * <li>The processing will try to continue even if the Java object tree
59  * does not meet the validity requirement. Only as
60  * the last resort, this method fails with {@link DataBindingException}.
61  * </ol>
62  *
63  *
64  * <p>
65  * All the methods on this class require non-null arguments to all parameters.
66  * The <tt>unmarshal</tt> methods either fail with an exception or return
67  * a non-null value.
68  *
69  * @author Kohsuke Kawaguchi
70  * @since 2.1
71  */

72 public final class JAXB {
73     /**
74      * No instanciation is allowed.
75      */

76     private JAXB() {}
77
78     /**
79      * To improve the performance, we'll cache the last {@link JAXBContext} used.
80      */

81     private static final class Cache {
82         final Class JavaDoc type;
83         final JAXBContext context;
84
85         public Cache(Class JavaDoc type) throws JAXBException {
86             this.type = type;
87             this.context = JAXBContext.newInstance(type);
88         }
89     }
90
91     /**
92      * Cache. We don't want to prevent the {@link Cache#type} from GC-ed,
93      * hence {@link WeakReference}.
94      */

95     private static volatile WeakReference JavaDoc<Cache> cache;
96
97     /**
98      * Obtains the {@link JAXBContext} from the given type,
99      * by using the cache if possible.
100      *
101      * <p>
102      * We don't use locks to control access to {@link #cache}, but this code
103      * should be thread-safe thanks to the immutable {@link Cache} and {@code volatile}.
104      */

105     private static <T> JAXBContext getContext(Class JavaDoc<T> type) throws JAXBException {
106         WeakReference JavaDoc<Cache> c = cache;
107         if(c!=null) {
108             Cache d = c.get();
109             if(d!=null && d.type==type)
110                 return d.context;
111         }
112
113         // overwrite the cache
114
Cache d = new Cache(type);
115         cache = new WeakReference JavaDoc<Cache>(d);
116
117         return d.context;
118     }
119
120     /**
121      * Reads in a Java object tree from the given XML input.
122      *
123      * @param xml
124      * Reads the entire file as XML.
125      */

126     public static <T> T unmarshal( File JavaDoc xml, Class JavaDoc<T> type ) {
127         try {
128             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(new StreamSource JavaDoc(xml), type);
129             return item.getValue();
130         } catch (JAXBException e) {
131             throw new DataBindingException(e);
132         }
133     }
134
135     /**
136      * Reads in a Java object tree from the given XML input.
137      *
138      * @param xml
139      * The resource pointed by the URL is read in its entirety.
140      */

141     public static <T> T unmarshal( URL JavaDoc xml, Class JavaDoc<T> type ) {
142         try {
143             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
144             return item.getValue();
145         } catch (JAXBException e) {
146             throw new DataBindingException(e);
147         } catch (IOException JavaDoc e) {
148             throw new DataBindingException(e);
149         }
150     }
151
152     /**
153      * Reads in a Java object tree from the given XML input.
154      *
155      * @param xml
156      * The URI is {@link URI#toURL() turned into URL} and then
157      * follows the handling of <tt>URL</tt>.
158      */

159     public static <T> T unmarshal( URI JavaDoc xml, Class JavaDoc<T> type ) {
160         try {
161             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
162             return item.getValue();
163         } catch (JAXBException e) {
164             throw new DataBindingException(e);
165         } catch (IOException JavaDoc e) {
166             throw new DataBindingException(e);
167         }
168     }
169
170     /**
171      * Reads in a Java object tree from the given XML input.
172      *
173      * @param xml
174      * The string is first interpreted as an absolute <tt>URI</tt>.
175      * If it's not {@link URI#isAbsolute() a valid absolute URI},
176      * then it's interpreted as a <tt>File</tt>
177      */

178     public static <T> T unmarshal( String JavaDoc xml, Class JavaDoc<T> type ) {
179         try {
180             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
181             return item.getValue();
182         } catch (JAXBException e) {
183             throw new DataBindingException(e);
184         } catch (IOException JavaDoc e) {
185             throw new DataBindingException(e);
186         }
187     }
188
189     /**
190      * Reads in a Java object tree from the given XML input.
191      *
192      * @param xml
193      * The entire stream is read as an XML infoset.
194      * Upon a successful completion, the stream will be closed by this method.
195      */

196     public static <T> T unmarshal( InputStream JavaDoc xml, Class JavaDoc<T> type ) {
197         try {
198             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
199             return item.getValue();
200         } catch (JAXBException e) {
201             throw new DataBindingException(e);
202         } catch (IOException JavaDoc e) {
203             throw new DataBindingException(e);
204         }
205     }
206
207     /**
208      * Reads in a Java object tree from the given XML input.
209      *
210      * @param xml
211      * The character stream is read as an XML infoset.
212      * The encoding declaration in the XML will be ignored.
213      * Upon a successful completion, the stream will be closed by this method.
214      */

215     public static <T> T unmarshal( Reader JavaDoc xml, Class JavaDoc<T> type ) {
216         try {
217             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
218             return item.getValue();
219         } catch (JAXBException e) {
220             throw new DataBindingException(e);
221         } catch (IOException JavaDoc e) {
222             throw new DataBindingException(e);
223         }
224     }
225
226     /**
227      * Reads in a Java object tree from the given XML input.
228      *
229      * @param xml
230      * The XML infoset that the {@link Source} represents is read.
231      */

232     public static <T> T unmarshal( Source JavaDoc xml, Class JavaDoc<T> type ) {
233         try {
234             JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
235             return item.getValue();
236         } catch (JAXBException e) {
237             throw new DataBindingException(e);
238         } catch (IOException JavaDoc e) {
239             throw new DataBindingException(e);
240         }
241     }
242
243
244
245     /**
246      * Creates {@link Source} from various XML representation.
247      * See {@link #unmarshal} for the conversion rules.
248      */

249     private static Source JavaDoc toSource(Object JavaDoc xml) throws IOException JavaDoc {
250         if(xml==null)
251             throw new IllegalArgumentException JavaDoc("no XML is given");
252
253         if (xml instanceof String JavaDoc) {
254             try {
255                 xml=new URI JavaDoc((String JavaDoc)xml);
256             } catch (URISyntaxException JavaDoc e) {
257                 xml=new File JavaDoc((String JavaDoc)xml);
258             }
259         }
260         if (xml instanceof File JavaDoc) {
261             File JavaDoc file = (File JavaDoc) xml;
262             return new StreamSource JavaDoc(file);
263         }
264         if (xml instanceof URI JavaDoc) {
265             URI JavaDoc uri = (URI JavaDoc) xml;
266             xml=uri.toURL();
267         }
268         if (xml instanceof URL JavaDoc) {
269             URL JavaDoc url = (URL JavaDoc) xml;
270             return new StreamSource JavaDoc(url.toExternalForm());
271         }
272         if (xml instanceof InputStream JavaDoc) {
273             InputStream JavaDoc in = (InputStream JavaDoc) xml;
274             return new StreamSource JavaDoc(in);
275         }
276         if (xml instanceof Reader JavaDoc) {
277             Reader JavaDoc r = (Reader JavaDoc) xml;
278             return new StreamSource JavaDoc(r);
279         }
280         if (xml instanceof Source JavaDoc) {
281             return (Source JavaDoc) xml;
282         }
283         throw new IllegalArgumentException JavaDoc("I don't understand how to handle "+xml.getClass());
284     }
285
286     /**
287      * Writes a Java object tree to XML and store it to the specified location.
288      *
289      * @param jaxbObject
290      * The Java object to be marshalled into XML. If this object is
291      * a {@link JAXBElement}, it will provide the root tag name and
292      * the body. If this object has {@link XmlRootElement}
293      * on its class definition, that will be used as the root tag name
294      * and the given object will provide the body. Otherwise,
295      * the root tag name is {@link Introspector#decapitalize(String) infered} from
296      * {@link Class#getSimpleName() the short class name}.
297      * This parameter must not be null.
298      *
299      * @param xml
300      * XML will be written to this file. If it already exists,
301      * it will be overwritten.
302      *
303      * @throws DataBindingException
304      * If the operation fails, such as due to I/O error, unbindable classes.
305      */

306     public static void marshal( Object JavaDoc jaxbObject, File JavaDoc xml ) {
307         _marshal(jaxbObject,xml);
308     }
309
310     /**
311      * Writes a Java object tree to XML and store it to the specified location.
312      *
313      * @param jaxbObject
314      * The Java object to be marshalled into XML. If this object is
315      * a {@link JAXBElement}, it will provide the root tag name and
316      * the body. If this object has {@link XmlRootElement}
317      * on its class definition, that will be used as the root tag name
318      * and the given object will provide the body. Otherwise,
319      * the root tag name is {@link Introspector#decapitalize(String) infered} from
320      * {@link Class#getSimpleName() the short class name}.
321      * This parameter must not be null.
322      *
323      * @param xml
324      * The XML will be {@link URLConnection#getOutputStream() sent} to the
325      * resource pointed by this URL. Note that not all <tt>URL</tt>s support
326      * such operation, and exact semantics depends on the <tt>URL</tt>
327      * implementations. In case of {@link HttpURLConnection HTTP URLs},
328      * this will perform HTTP POST.
329      *
330      * @throws DataBindingException
331      * If the operation fails, such as due to I/O error, unbindable classes.
332      */

333     public static void marshal( Object JavaDoc jaxbObject, URL JavaDoc xml ) {
334         _marshal(jaxbObject,xml);
335     }
336
337     /**
338      * Writes a Java object tree to XML and store it to the specified location.
339      *
340      * @param jaxbObject
341      * The Java object to be marshalled into XML. If this object is
342      * a {@link JAXBElement}, it will provide the root tag name and
343      * the body. If this object has {@link XmlRootElement}
344      * on its class definition, that will be used as the root tag name
345      * and the given object will provide the body. Otherwise,
346      * the root tag name is {@link Introspector#decapitalize(String) infered} from
347      * {@link Class#getSimpleName() the short class name}.
348      * This parameter must not be null.
349      *
350      * @param xml
351      * The URI is {@link URI#toURL() turned into URL} and then
352      * follows the handling of <tt>URL</tt>. See above.
353      *
354      * @throws DataBindingException
355      * If the operation fails, such as due to I/O error, unbindable classes.
356      */

357     public static void marshal( Object JavaDoc jaxbObject, URI JavaDoc xml ) {
358         _marshal(jaxbObject,xml);
359     }
360
361     /**
362      * Writes a Java object tree to XML and store it to the specified location.
363      *
364      * @param jaxbObject
365      * The Java object to be marshalled into XML. If this object is
366      * a {@link JAXBElement}, it will provide the root tag name and
367      * the body. If this object has {@link XmlRootElement}
368      * on its class definition, that will be used as the root tag name
369      * and the given object will provide the body. Otherwise,
370      * the root tag name is {@link Introspector#decapitalize(String) infered} from
371      * {@link Class#getSimpleName() the short class name}.
372      * This parameter must not be null.
373      *
374      * @param xml
375      * The string is first interpreted as an absolute <tt>URI</tt>.
376      * If it's not {@link URI#isAbsolute() a valid absolute URI},
377      * then it's interpreted as a <tt>File</tt>
378      *
379      * @throws DataBindingException
380      * If the operation fails, such as due to I/O error, unbindable classes.
381      */

382     public static void marshal( Object JavaDoc jaxbObject, String JavaDoc xml ) {
383         _marshal(jaxbObject,xml);
384     }
385
386     /**
387      * Writes a Java object tree to XML and store it to the specified location.
388      *
389      * @param jaxbObject
390      * The Java object to be marshalled into XML. If this object is
391      * a {@link JAXBElement}, it will provide the root tag name and
392      * the body. If this object has {@link XmlRootElement}
393      * on its class definition, that will be used as the root tag name
394      * and the given object will provide the body. Otherwise,
395      * the root tag name is {@link Introspector#decapitalize(String) infered} from
396      * {@link Class#getSimpleName() the short class name}.
397      * This parameter must not be null.
398      *
399      * @param xml
400      * The XML will be sent to the given {@link OutputStream}.
401      * Upon a successful completion, the stream will be closed by this method.
402      *
403      * @throws DataBindingException
404      * If the operation fails, such as due to I/O error, unbindable classes.
405      */

406     public static void marshal( Object JavaDoc jaxbObject, OutputStream JavaDoc xml ) {
407         _marshal(jaxbObject,xml);
408     }
409
410     /**
411      * Writes a Java object tree to XML and store it to the specified location.
412      *
413      * @param jaxbObject
414      * The Java object to be marshalled into XML. If this object is
415      * a {@link JAXBElement}, it will provide the root tag name and
416      * the body. If this object has {@link XmlRootElement}
417      * on its class definition, that will be used as the root tag name
418      * and the given object will provide the body. Otherwise,
419      * the root tag name is {@link Introspector#decapitalize(String) infered} from
420      * {@link Class#getSimpleName() the short class name}.
421      * This parameter must not be null.
422      *
423      * @param xml
424      * The XML will be sent as a character stream to the given {@link Writer}.
425      * Upon a successful completion, the stream will be closed by this method.
426      *
427      * @throws DataBindingException
428      * If the operation fails, such as due to I/O error, unbindable classes.
429      */

430     public static void marshal( Object JavaDoc jaxbObject, Writer JavaDoc xml ) {
431         _marshal(jaxbObject,xml);
432     }
433
434     /**
435      * Writes a Java object tree to XML and store it to the specified location.
436      *
437      * @param jaxbObject
438      * The Java object to be marshalled into XML. If this object is
439      * a {@link JAXBElement}, it will provide the root tag name and
440      * the body. If this object has {@link XmlRootElement}
441      * on its class definition, that will be used as the root tag name
442      * and the given object will provide the body. Otherwise,
443      * the root tag name is {@link Introspector#decapitalize(String) infered} from
444      * {@link Class#getSimpleName() the short class name}.
445      * This parameter must not be null.
446      *
447      * @param xml
448      * The XML will be sent to the {@link Result} object.
449      *
450      * @throws DataBindingException
451      * If the operation fails, such as due to I/O error, unbindable classes.
452      */

453     public static void marshal( Object JavaDoc jaxbObject, Result JavaDoc xml ) {
454         _marshal(jaxbObject,xml);
455     }
456
457     /**
458      * Writes a Java object tree to XML and store it to the specified location.
459      *
460      * <p>
461      * This method is a convenience method that combines several basic operations
462      * in the {@link JAXBContext} and {@link Marshaller}. This method is designed
463      * to be the prefered method for developers new to JAXB. This method
464      * has the following characterstics:
465      *
466      * <ol>
467      * <li>Generally speaking, the performance is not necessarily optimal.
468      * It is expected that those people who need to write performance
469      * critical code will use the rest of the JAXB API directly.
470      * <li>Errors that happen during the processing is wrapped into
471      * {@link DataBindingException} (which will have {@link JAXBException}
472      * as its {@link Throwable#getCause() cause}. It is expected that
473      * those people who prefer the checked exception would use
474      * the rest of the JAXB API directly.
475      * </ol>
476      *
477      * @param jaxbObject
478      * The Java object to be marshalled into XML. If this object is
479      * a {@link JAXBElement}, it will provide the root tag name and
480      * the body. If this object has {@link XmlRootElement}
481      * on its class definition, that will be used as the root tag name
482      * and the given object will provide the body. Otherwise,
483      * the root tag name is {@link Introspector#decapitalize(String) infered} from
484      * {@link Class#getSimpleName() the short class name}.
485      * This parameter must not be null.
486      *
487      * @param xml
488      * Represents the receiver of XML. Objects of the following types are allowed.
489      *
490      * <table><tr>
491      * <th>Type</th>
492      * <th>Operation</th>
493      * </tr><tr>
494      * <td>{@link File}</td>
495      * <td>XML will be written to this file. If it already exists,
496      * it will be overwritten.</td>
497      * </tr><tr>
498      * <td>{@link URL}</td>
499      * <td>The XML will be {@link URLConnection#getOutputStream() sent} to the
500      * resource pointed by this URL. Note that not all <tt>URL</tt>s support
501      * such operation, and exact semantics depends on the <tt>URL</tt>
502      * implementations. In case of {@link HttpURLConnection HTTP URLs},
503      * this will perform HTTP POST.</td>
504      * </tr><tr>
505      * <td>{@link URI}</td>
506      * <td>The URI is {@link URI#toURL() turned into URL} and then
507      * follows the handling of <tt>URL</tt>. See above.</td>
508      * </tr><tr>
509      * <td>{@link String}</td>
510      * <td>The string is first interpreted as an absolute <tt>URI</tt>.
511      * If it's not {@link URI#isAbsolute() a valid absolute URI},
512      * then it's interpreted as a <tt>File</tt></td>
513      * </tr><tr>
514      * <td>{@link OutputStream}</td>
515      * <td>The XML will be sent to the given {@link OutputStream}.
516      * Upon a successful completion, the stream will be closed by this method.</td>
517      * </tr><tr>
518      * <td>{@link Writer}</td>
519      * <td>The XML will be sent as a character stream to the given {@link Writer}.
520      * Upon a successful completion, the stream will be closed by this method.</td>
521      * </tr><tr>
522      * <td>{@link Result}</td>
523      * <td>The XML will be sent to the {@link Result} object.</td>
524      * </tr></table>
525      *
526      * @throws DataBindingException
527      * If the operation fails, such as due to I/O error, unbindable classes.
528      */

529     private static void _marshal( Object JavaDoc jaxbObject, Object JavaDoc xml ) {
530         try {
531             JAXBContext context;
532
533             if(jaxbObject instanceof JAXBElement) {
534                 context = getContext(((JAXBElement<?>)jaxbObject).getDeclaredType());
535             } else {
536                 Class JavaDoc<?> clazz = jaxbObject.getClass();
537                 XmlRootElement r = clazz.getAnnotation(XmlRootElement.class);
538                 context = getContext(clazz);
539                 if(r==null) {
540                     // we need to infer the name
541
jaxbObject = new JAXBElement(new QName JavaDoc(inferName(clazz)),clazz,jaxbObject);
542                 }
543             }
544
545             Marshaller m = context.createMarshaller();
546             m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
547             m.marshal(jaxbObject, toResult(xml));
548         } catch (JAXBException e) {
549             throw new DataBindingException(e);
550         } catch (IOException JavaDoc e) {
551             throw new DataBindingException(e);
552         }
553     }
554
555     private static String JavaDoc inferName(Class JavaDoc clazz) {
556         return Introspector.decapitalize(clazz.getSimpleName());
557     }
558
559     /**
560      * Creates {@link Result} from various XML representation.
561      * See {@link #_marshal(Object,Object)} for the conversion rules.
562      */

563     private static Result JavaDoc toResult(Object JavaDoc xml) throws IOException JavaDoc {
564         if(xml==null)
565             throw new IllegalArgumentException JavaDoc("no XML is given");
566
567         if (xml instanceof String JavaDoc) {
568             try {
569                 xml=new URI JavaDoc((String JavaDoc)xml);
570             } catch (URISyntaxException JavaDoc e) {
571                 xml=new File JavaDoc((String JavaDoc)xml);
572             }
573         }
574         if (xml instanceof File JavaDoc) {
575             File JavaDoc file = (File JavaDoc) xml;
576             return new StreamResult JavaDoc(file);
577         }
578         if (xml instanceof URI JavaDoc) {
579             URI JavaDoc uri = (URI JavaDoc) xml;
580             xml=uri.toURL();
581         }
582         if (xml instanceof URL JavaDoc) {
583             URL JavaDoc url = (URL JavaDoc) xml;
584             URLConnection JavaDoc con = url.openConnection();
585             con.setDoOutput(true);
586             con.setDoInput(false);
587             con.connect();
588             return new StreamResult JavaDoc(con.getOutputStream());
589         }
590         if (xml instanceof OutputStream JavaDoc) {
591             OutputStream JavaDoc os = (OutputStream JavaDoc) xml;
592             return new StreamResult JavaDoc(os);
593         }
594         if (xml instanceof Writer JavaDoc) {
595             Writer JavaDoc w = (Writer JavaDoc)xml;
596             return new StreamResult JavaDoc(w);
597         }
598         if (xml instanceof Result JavaDoc) {
599             return (Result JavaDoc) xml;
600         }
601         throw new IllegalArgumentException JavaDoc("I don't understand how to handle "+xml.getClass());
602     }
603
604 }
605
Popular Tags