src/share/jaxws_classes/javax/xml/bind/JAXB.java

Tue, 09 Apr 2013 14:51:13 +0100

author
alanb
date
Tue, 09 Apr 2013 14:51:13 +0100
changeset 368
0989ad8c0860
parent 286
f50545b5e2f1
child 397
b99d7e355d4b
permissions
-rw-r--r--

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 }

mercurial