Tue, 09 Apr 2013 14:51:13 +0100
8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com
1 /*
2 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package javax.xml.bind;
28 import javax.xml.bind.annotation.XmlRootElement;
29 import javax.xml.namespace.QName;
30 import javax.xml.transform.Result;
31 import javax.xml.transform.Source;
32 import javax.xml.transform.stream.StreamResult;
33 import javax.xml.transform.stream.StreamSource;
34 import java.beans.Introspector;
35 import java.io.File;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.io.Reader;
40 import java.io.Writer;
41 import java.lang.ref.WeakReference;
42 import java.net.HttpURLConnection;
43 import java.net.URI;
44 import java.net.URISyntaxException;
45 import java.net.URL;
46 import java.net.URLConnection;
48 /**
49 * Class that defines convenience methods for common, simple use of JAXB.
50 *
51 * <p>
52 * Methods defined in this class are convenience methods that combine several basic operations
53 * in the {@link JAXBContext}, {@link Unmarshaller}, and {@link Marshaller}.
54 *
55 * They are designed
56 * to be the prefered methods for developers new to JAXB. They have
57 * the following characterstics:
58 *
59 * <ol>
60 * <li>Generally speaking, the performance is not necessarily optimal.
61 * It is expected that people who need to write performance
62 * critical code will use the rest of the JAXB API directly.
63 * <li>Errors that happen during the processing is wrapped into
64 * {@link DataBindingException} (which will have {@link JAXBException}
65 * as its {@link Throwable#getCause() cause}. It is expected that
66 * people who prefer the checked exception would use
67 * the rest of the JAXB API directly.
68 * </ol>
69 *
70 * <p>
71 * In addition, the <tt>unmarshal</tt> methods have the following characteristic:
72 *
73 * <ol>
74 * <li>Schema validation is not performed on the input XML.
75 * The processing will try to continue even if there
76 * are errors in the XML, as much as possible. Only as
77 * the last resort, this method fails with {@link DataBindingException}.
78 * </ol>
79 *
80 * <p>
81 * Similarly, the <tt>marshal</tt> methods have the following characteristic:
82 * <ol>
83 * <li>The processing will try to continue even if the Java object tree
84 * does not meet the validity requirement. Only as
85 * the last resort, this method fails with {@link DataBindingException}.
86 * </ol>
87 *
88 *
89 * <p>
90 * All the methods on this class require non-null arguments to all parameters.
91 * The <tt>unmarshal</tt> methods either fail with an exception or return
92 * a non-null value.
93 *
94 * @author Kohsuke Kawaguchi
95 * @since 2.1
96 */
97 public final class JAXB {
98 /**
99 * No instanciation is allowed.
100 */
101 private JAXB() {}
103 /**
104 * To improve the performance, we'll cache the last {@link JAXBContext} used.
105 */
106 private static final class Cache {
107 final Class type;
108 final JAXBContext context;
110 public Cache(Class type) throws JAXBException {
111 this.type = type;
112 this.context = JAXBContext.newInstance(type);
113 }
114 }
116 /**
117 * Cache. We don't want to prevent the {@link Cache#type} from GC-ed,
118 * hence {@link WeakReference}.
119 */
120 private static volatile WeakReference<Cache> cache;
122 /**
123 * Obtains the {@link JAXBContext} from the given type,
124 * by using the cache if possible.
125 *
126 * <p>
127 * We don't use locks to control access to {@link #cache}, but this code
128 * should be thread-safe thanks to the immutable {@link Cache} and {@code volatile}.
129 */
130 private static <T> JAXBContext getContext(Class<T> type) throws JAXBException {
131 WeakReference<Cache> c = cache;
132 if(c!=null) {
133 Cache d = c.get();
134 if(d!=null && d.type==type)
135 return d.context;
136 }
138 // overwrite the cache
139 Cache d = new Cache(type);
140 cache = new WeakReference<Cache>(d);
142 return d.context;
143 }
145 /**
146 * Reads in a Java object tree from the given XML input.
147 *
148 * @param xml
149 * Reads the entire file as XML.
150 */
151 public static <T> T unmarshal( File xml, Class<T> type ) {
152 try {
153 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(new StreamSource(xml), type);
154 return item.getValue();
155 } catch (JAXBException e) {
156 throw new DataBindingException(e);
157 }
158 }
160 /**
161 * Reads in a Java object tree from the given XML input.
162 *
163 * @param xml
164 * The resource pointed by the URL is read in its entirety.
165 */
166 public static <T> T unmarshal( URL xml, Class<T> type ) {
167 try {
168 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
169 return item.getValue();
170 } catch (JAXBException e) {
171 throw new DataBindingException(e);
172 } catch (IOException e) {
173 throw new DataBindingException(e);
174 }
175 }
177 /**
178 * Reads in a Java object tree from the given XML input.
179 *
180 * @param xml
181 * The URI is {@link URI#toURL() turned into URL} and then
182 * follows the handling of <tt>URL</tt>.
183 */
184 public static <T> T unmarshal( URI xml, Class<T> type ) {
185 try {
186 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
187 return item.getValue();
188 } catch (JAXBException e) {
189 throw new DataBindingException(e);
190 } catch (IOException e) {
191 throw new DataBindingException(e);
192 }
193 }
195 /**
196 * Reads in a Java object tree from the given XML input.
197 *
198 * @param xml
199 * The string is first interpreted as an absolute <tt>URI</tt>.
200 * If it's not {@link URI#isAbsolute() a valid absolute URI},
201 * then it's interpreted as a <tt>File</tt>
202 */
203 public static <T> T unmarshal( String xml, Class<T> type ) {
204 try {
205 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
206 return item.getValue();
207 } catch (JAXBException e) {
208 throw new DataBindingException(e);
209 } catch (IOException e) {
210 throw new DataBindingException(e);
211 }
212 }
214 /**
215 * Reads in a Java object tree from the given XML input.
216 *
217 * @param xml
218 * The entire stream is read as an XML infoset.
219 * Upon a successful completion, the stream will be closed by this method.
220 */
221 public static <T> T unmarshal( InputStream xml, Class<T> type ) {
222 try {
223 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
224 return item.getValue();
225 } catch (JAXBException e) {
226 throw new DataBindingException(e);
227 } catch (IOException e) {
228 throw new DataBindingException(e);
229 }
230 }
232 /**
233 * Reads in a Java object tree from the given XML input.
234 *
235 * @param xml
236 * The character stream is read as an XML infoset.
237 * The encoding declaration in the XML will be ignored.
238 * Upon a successful completion, the stream will be closed by this method.
239 */
240 public static <T> T unmarshal( Reader xml, Class<T> type ) {
241 try {
242 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
243 return item.getValue();
244 } catch (JAXBException e) {
245 throw new DataBindingException(e);
246 } catch (IOException e) {
247 throw new DataBindingException(e);
248 }
249 }
251 /**
252 * Reads in a Java object tree from the given XML input.
253 *
254 * @param xml
255 * The XML infoset that the {@link Source} represents is read.
256 */
257 public static <T> T unmarshal( Source xml, Class<T> type ) {
258 try {
259 JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
260 return item.getValue();
261 } catch (JAXBException e) {
262 throw new DataBindingException(e);
263 } catch (IOException e) {
264 throw new DataBindingException(e);
265 }
266 }
270 /**
271 * Creates {@link Source} from various XML representation.
272 * See {@link #unmarshal} for the conversion rules.
273 */
274 private static Source toSource(Object xml) throws IOException {
275 if(xml==null)
276 throw new IllegalArgumentException("no XML is given");
278 if (xml instanceof String) {
279 try {
280 xml=new URI((String)xml);
281 } catch (URISyntaxException e) {
282 xml=new File((String)xml);
283 }
284 }
285 if (xml instanceof File) {
286 File file = (File) xml;
287 return new StreamSource(file);
288 }
289 if (xml instanceof URI) {
290 URI uri = (URI) xml;
291 xml=uri.toURL();
292 }
293 if (xml instanceof URL) {
294 URL url = (URL) xml;
295 return new StreamSource(url.toExternalForm());
296 }
297 if (xml instanceof InputStream) {
298 InputStream in = (InputStream) xml;
299 return new StreamSource(in);
300 }
301 if (xml instanceof Reader) {
302 Reader r = (Reader) xml;
303 return new StreamSource(r);
304 }
305 if (xml instanceof Source) {
306 return (Source) xml;
307 }
308 throw new IllegalArgumentException("I don't understand how to handle "+xml.getClass());
309 }
311 /**
312 * Writes a Java object tree to XML and store it to the specified location.
313 *
314 * @param jaxbObject
315 * The Java object to be marshalled into XML. If this object is
316 * a {@link JAXBElement}, it will provide the root tag name and
317 * the body. If this object has {@link XmlRootElement}
318 * on its class definition, that will be used as the root tag name
319 * and the given object will provide the body. Otherwise,
320 * the root tag name is {@link Introspector#decapitalize(String) infered} from
321 * {@link Class#getSimpleName() the short class name}.
322 * This parameter must not be null.
323 *
324 * @param xml
325 * XML will be written to this file. If it already exists,
326 * it will be overwritten.
327 *
328 * @throws DataBindingException
329 * If the operation fails, such as due to I/O error, unbindable classes.
330 */
331 public static void marshal( Object jaxbObject, File xml ) {
332 _marshal(jaxbObject,xml);
333 }
335 /**
336 * Writes a Java object tree to XML and store it to the specified location.
337 *
338 * @param jaxbObject
339 * The Java object to be marshalled into XML. If this object is
340 * a {@link JAXBElement}, it will provide the root tag name and
341 * the body. If this object has {@link XmlRootElement}
342 * on its class definition, that will be used as the root tag name
343 * and the given object will provide the body. Otherwise,
344 * the root tag name is {@link Introspector#decapitalize(String) infered} from
345 * {@link Class#getSimpleName() the short class name}.
346 * This parameter must not be null.
347 *
348 * @param xml
349 * The XML will be {@link URLConnection#getOutputStream() sent} to the
350 * resource pointed by this URL. Note that not all <tt>URL</tt>s support
351 * such operation, and exact semantics depends on the <tt>URL</tt>
352 * implementations. In case of {@link HttpURLConnection HTTP URLs},
353 * this will perform HTTP POST.
354 *
355 * @throws DataBindingException
356 * If the operation fails, such as due to I/O error, unbindable classes.
357 */
358 public static void marshal( Object jaxbObject, URL xml ) {
359 _marshal(jaxbObject,xml);
360 }
362 /**
363 * Writes a Java object tree to XML and store it to the specified location.
364 *
365 * @param jaxbObject
366 * The Java object to be marshalled into XML. If this object is
367 * a {@link JAXBElement}, it will provide the root tag name and
368 * the body. If this object has {@link XmlRootElement}
369 * on its class definition, that will be used as the root tag name
370 * and the given object will provide the body. Otherwise,
371 * the root tag name is {@link Introspector#decapitalize(String) infered} from
372 * {@link Class#getSimpleName() the short class name}.
373 * This parameter must not be null.
374 *
375 * @param xml
376 * The URI is {@link URI#toURL() turned into URL} and then
377 * follows the handling of <tt>URL</tt>. See above.
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 jaxbObject, URI xml ) {
383 _marshal(jaxbObject,xml);
384 }
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 string is first interpreted as an absolute <tt>URI</tt>.
401 * If it's not {@link URI#isAbsolute() a valid absolute URI},
402 * then it's interpreted as a <tt>File</tt>
403 *
404 * @throws DataBindingException
405 * If the operation fails, such as due to I/O error, unbindable classes.
406 */
407 public static void marshal( Object jaxbObject, String xml ) {
408 _marshal(jaxbObject,xml);
409 }
411 /**
412 * Writes a Java object tree to XML and store it to the specified location.
413 *
414 * @param jaxbObject
415 * The Java object to be marshalled into XML. If this object is
416 * a {@link JAXBElement}, it will provide the root tag name and
417 * the body. If this object has {@link XmlRootElement}
418 * on its class definition, that will be used as the root tag name
419 * and the given object will provide the body. Otherwise,
420 * the root tag name is {@link Introspector#decapitalize(String) infered} from
421 * {@link Class#getSimpleName() the short class name}.
422 * This parameter must not be null.
423 *
424 * @param xml
425 * The XML will be sent to the given {@link OutputStream}.
426 * Upon a successful completion, the stream will be closed by this method.
427 *
428 * @throws DataBindingException
429 * If the operation fails, such as due to I/O error, unbindable classes.
430 */
431 public static void marshal( Object jaxbObject, OutputStream xml ) {
432 _marshal(jaxbObject,xml);
433 }
435 /**
436 * Writes a Java object tree to XML and store it to the specified location.
437 *
438 * @param jaxbObject
439 * The Java object to be marshalled into XML. If this object is
440 * a {@link JAXBElement}, it will provide the root tag name and
441 * the body. If this object has {@link XmlRootElement}
442 * on its class definition, that will be used as the root tag name
443 * and the given object will provide the body. Otherwise,
444 * the root tag name is {@link Introspector#decapitalize(String) infered} from
445 * {@link Class#getSimpleName() the short class name}.
446 * This parameter must not be null.
447 *
448 * @param xml
449 * The XML will be sent as a character stream to the given {@link Writer}.
450 * Upon a successful completion, the stream will be closed by this method.
451 *
452 * @throws DataBindingException
453 * If the operation fails, such as due to I/O error, unbindable classes.
454 */
455 public static void marshal( Object jaxbObject, Writer xml ) {
456 _marshal(jaxbObject,xml);
457 }
459 /**
460 * Writes a Java object tree to XML and store it to the specified location.
461 *
462 * @param jaxbObject
463 * The Java object to be marshalled into XML. If this object is
464 * a {@link JAXBElement}, it will provide the root tag name and
465 * the body. If this object has {@link XmlRootElement}
466 * on its class definition, that will be used as the root tag name
467 * and the given object will provide the body. Otherwise,
468 * the root tag name is {@link Introspector#decapitalize(String) infered} from
469 * {@link Class#getSimpleName() the short class name}.
470 * This parameter must not be null.
471 *
472 * @param xml
473 * The XML will be sent to the {@link Result} object.
474 *
475 * @throws DataBindingException
476 * If the operation fails, such as due to I/O error, unbindable classes.
477 */
478 public static void marshal( Object jaxbObject, Result xml ) {
479 _marshal(jaxbObject,xml);
480 }
482 /**
483 * Writes a Java object tree to XML and store it to the specified location.
484 *
485 * <p>
486 * This method is a convenience method that combines several basic operations
487 * in the {@link JAXBContext} and {@link Marshaller}. This method is designed
488 * to be the prefered method for developers new to JAXB. This method
489 * has the following characterstics:
490 *
491 * <ol>
492 * <li>Generally speaking, the performance is not necessarily optimal.
493 * It is expected that those people who need to write performance
494 * critical code will use the rest of the JAXB API directly.
495 * <li>Errors that happen during the processing is wrapped into
496 * {@link DataBindingException} (which will have {@link JAXBException}
497 * as its {@link Throwable#getCause() cause}. It is expected that
498 * those people who prefer the checked exception would use
499 * the rest of the JAXB API directly.
500 * </ol>
501 *
502 * @param jaxbObject
503 * The Java object to be marshalled into XML. If this object is
504 * a {@link JAXBElement}, it will provide the root tag name and
505 * the body. If this object has {@link XmlRootElement}
506 * on its class definition, that will be used as the root tag name
507 * and the given object will provide the body. Otherwise,
508 * the root tag name is {@link Introspector#decapitalize(String) infered} from
509 * {@link Class#getSimpleName() the short class name}.
510 * This parameter must not be null.
511 *
512 * @param xml
513 * Represents the receiver of XML. Objects of the following types are allowed.
514 *
515 * <table><tr>
516 * <th>Type</th>
517 * <th>Operation</th>
518 * </tr><tr>
519 * <td>{@link File}</td>
520 * <td>XML will be written to this file. If it already exists,
521 * it will be overwritten.</td>
522 * </tr><tr>
523 * <td>{@link URL}</td>
524 * <td>The XML will be {@link URLConnection#getOutputStream() sent} to the
525 * resource pointed by this URL. Note that not all <tt>URL</tt>s support
526 * such operation, and exact semantics depends on the <tt>URL</tt>
527 * implementations. In case of {@link HttpURLConnection HTTP URLs},
528 * this will perform HTTP POST.</td>
529 * </tr><tr>
530 * <td>{@link URI}</td>
531 * <td>The URI is {@link URI#toURL() turned into URL} and then
532 * follows the handling of <tt>URL</tt>. See above.</td>
533 * </tr><tr>
534 * <td>{@link String}</td>
535 * <td>The string is first interpreted as an absolute <tt>URI</tt>.
536 * If it's not {@link URI#isAbsolute() a valid absolute URI},
537 * then it's interpreted as a <tt>File</tt></td>
538 * </tr><tr>
539 * <td>{@link OutputStream}</td>
540 * <td>The XML will be sent to the given {@link OutputStream}.
541 * Upon a successful completion, the stream will be closed by this method.</td>
542 * </tr><tr>
543 * <td>{@link Writer}</td>
544 * <td>The XML will be sent as a character stream to the given {@link Writer}.
545 * Upon a successful completion, the stream will be closed by this method.</td>
546 * </tr><tr>
547 * <td>{@link Result}</td>
548 * <td>The XML will be sent to the {@link Result} object.</td>
549 * </tr></table>
550 *
551 * @throws DataBindingException
552 * If the operation fails, such as due to I/O error, unbindable classes.
553 */
554 private static void _marshal( Object jaxbObject, Object xml ) {
555 try {
556 JAXBContext context;
558 if(jaxbObject instanceof JAXBElement) {
559 context = getContext(((JAXBElement<?>)jaxbObject).getDeclaredType());
560 } else {
561 Class<?> clazz = jaxbObject.getClass();
562 XmlRootElement r = clazz.getAnnotation(XmlRootElement.class);
563 context = getContext(clazz);
564 if(r==null) {
565 // we need to infer the name
566 jaxbObject = new JAXBElement(new QName(inferName(clazz)),clazz,jaxbObject);
567 }
568 }
570 Marshaller m = context.createMarshaller();
571 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
572 m.marshal(jaxbObject, toResult(xml));
573 } catch (JAXBException e) {
574 throw new DataBindingException(e);
575 } catch (IOException e) {
576 throw new DataBindingException(e);
577 }
578 }
580 private static String inferName(Class clazz) {
581 return Introspector.decapitalize(clazz.getSimpleName());
582 }
584 /**
585 * Creates {@link Result} from various XML representation.
586 * See {@link #_marshal(Object,Object)} for the conversion rules.
587 */
588 private static Result toResult(Object xml) throws IOException {
589 if(xml==null)
590 throw new IllegalArgumentException("no XML is given");
592 if (xml instanceof String) {
593 try {
594 xml=new URI((String)xml);
595 } catch (URISyntaxException e) {
596 xml=new File((String)xml);
597 }
598 }
599 if (xml instanceof File) {
600 File file = (File) xml;
601 return new StreamResult(file);
602 }
603 if (xml instanceof URI) {
604 URI uri = (URI) xml;
605 xml=uri.toURL();
606 }
607 if (xml instanceof URL) {
608 URL url = (URL) xml;
609 URLConnection con = url.openConnection();
610 con.setDoOutput(true);
611 con.setDoInput(false);
612 con.connect();
613 return new StreamResult(con.getOutputStream());
614 }
615 if (xml instanceof OutputStream) {
616 OutputStream os = (OutputStream) xml;
617 return new StreamResult(os);
618 }
619 if (xml instanceof Writer) {
620 Writer w = (Writer)xml;
621 return new StreamResult(w);
622 }
623 if (xml instanceof Result) {
624 return (Result) xml;
625 }
626 throw new IllegalArgumentException("I don't understand how to handle "+xml.getClass());
627 }
629 }