Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxws/src/share/jaxws_classes/javax/xml/bind/JAXB.java
38890 views
/*1* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.xml.bind;2627import javax.xml.bind.annotation.XmlRootElement;28import javax.xml.namespace.QName;29import javax.xml.transform.Result;30import javax.xml.transform.Source;31import javax.xml.transform.stream.StreamResult;32import javax.xml.transform.stream.StreamSource;33import java.beans.Introspector;34import java.io.File;35import java.io.IOException;36import java.io.InputStream;37import java.io.OutputStream;38import java.io.Reader;39import java.io.Writer;40import java.lang.ref.WeakReference;41import java.net.HttpURLConnection;42import java.net.URI;43import java.net.URISyntaxException;44import java.net.URL;45import java.net.URLConnection;4647/**48* Class that defines convenience methods for common, simple use of JAXB.49*50* <p>51* Methods defined in this class are convenience methods that combine several basic operations52* in the {@link JAXBContext}, {@link Unmarshaller}, and {@link Marshaller}.53*54* They are designed55* to be the prefered methods for developers new to JAXB. They have56* the following characterstics:57*58* <ol>59* <li>Generally speaking, the performance is not necessarily optimal.60* It is expected that people who need to write performance61* critical code will use the rest of the JAXB API directly.62* <li>Errors that happen during the processing is wrapped into63* {@link DataBindingException} (which will have {@link JAXBException}64* as its {@link Throwable#getCause() cause}. It is expected that65* people who prefer the checked exception would use66* the rest of the JAXB API directly.67* </ol>68*69* <p>70* In addition, the <tt>unmarshal</tt> methods have the following characteristic:71*72* <ol>73* <li>Schema validation is not performed on the input XML.74* The processing will try to continue even if there75* are errors in the XML, as much as possible. Only as76* the last resort, this method fails with {@link DataBindingException}.77* </ol>78*79* <p>80* Similarly, the <tt>marshal</tt> methods have the following characteristic:81* <ol>82* <li>The processing will try to continue even if the Java object tree83* does not meet the validity requirement. Only as84* the last resort, this method fails with {@link DataBindingException}.85* </ol>86*87*88* <p>89* All the methods on this class require non-null arguments to all parameters.90* The <tt>unmarshal</tt> methods either fail with an exception or return91* a non-null value.92*93* @author Kohsuke Kawaguchi94* @since 2.195*/96public final class JAXB {97/**98* No instanciation is allowed.99*/100private JAXB() {}101102/**103* To improve the performance, we'll cache the last {@link JAXBContext} used.104*/105private static final class Cache {106final Class type;107final JAXBContext context;108109public Cache(Class type) throws JAXBException {110this.type = type;111this.context = JAXBContext.newInstance(type);112}113}114115/**116* Cache. We don't want to prevent the {@link Cache#type} from GC-ed,117* hence {@link WeakReference}.118*/119private static volatile WeakReference<Cache> cache;120121/**122* Obtains the {@link JAXBContext} from the given type,123* by using the cache if possible.124*125* <p>126* We don't use locks to control access to {@link #cache}, but this code127* should be thread-safe thanks to the immutable {@link Cache} and {@code volatile}.128*/129private static <T> JAXBContext getContext(Class<T> type) throws JAXBException {130WeakReference<Cache> c = cache;131if(c!=null) {132Cache d = c.get();133if(d!=null && d.type==type)134return d.context;135}136137// overwrite the cache138Cache d = new Cache(type);139cache = new WeakReference<Cache>(d);140141return d.context;142}143144/**145* Reads in a Java object tree from the given XML input.146*147* @param xml148* Reads the entire file as XML.149*/150public static <T> T unmarshal( File xml, Class<T> type ) {151try {152JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(new StreamSource(xml), type);153return item.getValue();154} catch (JAXBException e) {155throw new DataBindingException(e);156}157}158159/**160* Reads in a Java object tree from the given XML input.161*162* @param xml163* The resource pointed by the URL is read in its entirety.164*/165public static <T> T unmarshal( URL xml, Class<T> type ) {166try {167JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);168return item.getValue();169} catch (JAXBException e) {170throw new DataBindingException(e);171} catch (IOException e) {172throw new DataBindingException(e);173}174}175176/**177* Reads in a Java object tree from the given XML input.178*179* @param xml180* The URI is {@link URI#toURL() turned into URL} and then181* follows the handling of <tt>URL</tt>.182*/183public static <T> T unmarshal( URI xml, Class<T> type ) {184try {185JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);186return item.getValue();187} catch (JAXBException e) {188throw new DataBindingException(e);189} catch (IOException e) {190throw new DataBindingException(e);191}192}193194/**195* Reads in a Java object tree from the given XML input.196*197* @param xml198* The string is first interpreted as an absolute <tt>URI</tt>.199* If it's not {@link URI#isAbsolute() a valid absolute URI},200* then it's interpreted as a <tt>File</tt>201*/202public static <T> T unmarshal( String xml, Class<T> type ) {203try {204JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);205return item.getValue();206} catch (JAXBException e) {207throw new DataBindingException(e);208} catch (IOException e) {209throw new DataBindingException(e);210}211}212213/**214* Reads in a Java object tree from the given XML input.215*216* @param xml217* The entire stream is read as an XML infoset.218* Upon a successful completion, the stream will be closed by this method.219*/220public static <T> T unmarshal( InputStream xml, Class<T> type ) {221try {222JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);223return item.getValue();224} catch (JAXBException e) {225throw new DataBindingException(e);226} catch (IOException e) {227throw new DataBindingException(e);228}229}230231/**232* Reads in a Java object tree from the given XML input.233*234* @param xml235* The character stream is read as an XML infoset.236* The encoding declaration in the XML will be ignored.237* Upon a successful completion, the stream will be closed by this method.238*/239public static <T> T unmarshal( Reader xml, Class<T> type ) {240try {241JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);242return item.getValue();243} catch (JAXBException e) {244throw new DataBindingException(e);245} catch (IOException e) {246throw new DataBindingException(e);247}248}249250/**251* Reads in a Java object tree from the given XML input.252*253* @param xml254* The XML infoset that the {@link Source} represents is read.255*/256public static <T> T unmarshal( Source xml, Class<T> type ) {257try {258JAXBElement<T> item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);259return item.getValue();260} catch (JAXBException e) {261throw new DataBindingException(e);262} catch (IOException e) {263throw new DataBindingException(e);264}265}266267268269/**270* Creates {@link Source} from various XML representation.271* See {@link #unmarshal} for the conversion rules.272*/273private static Source toSource(Object xml) throws IOException {274if(xml==null)275throw new IllegalArgumentException("no XML is given");276277if (xml instanceof String) {278try {279xml=new URI((String)xml);280} catch (URISyntaxException e) {281xml=new File((String)xml);282}283}284if (xml instanceof File) {285File file = (File) xml;286return new StreamSource(file);287}288if (xml instanceof URI) {289URI uri = (URI) xml;290xml=uri.toURL();291}292if (xml instanceof URL) {293URL url = (URL) xml;294return new StreamSource(url.toExternalForm());295}296if (xml instanceof InputStream) {297InputStream in = (InputStream) xml;298return new StreamSource(in);299}300if (xml instanceof Reader) {301Reader r = (Reader) xml;302return new StreamSource(r);303}304if (xml instanceof Source) {305return (Source) xml;306}307throw new IllegalArgumentException("I don't understand how to handle "+xml.getClass());308}309310/**311* Writes a Java object tree to XML and store it to the specified location.312*313* @param jaxbObject314* The Java object to be marshalled into XML. If this object is315* a {@link JAXBElement}, it will provide the root tag name and316* the body. If this object has {@link XmlRootElement}317* on its class definition, that will be used as the root tag name318* and the given object will provide the body. Otherwise,319* the root tag name is {@link Introspector#decapitalize(String) infered} from320* {@link Class#getSimpleName() the short class name}.321* This parameter must not be null.322*323* @param xml324* XML will be written to this file. If it already exists,325* it will be overwritten.326*327* @throws DataBindingException328* If the operation fails, such as due to I/O error, unbindable classes.329*/330public static void marshal( Object jaxbObject, File xml ) {331_marshal(jaxbObject,xml);332}333334/**335* Writes a Java object tree to XML and store it to the specified location.336*337* @param jaxbObject338* The Java object to be marshalled into XML. If this object is339* a {@link JAXBElement}, it will provide the root tag name and340* the body. If this object has {@link XmlRootElement}341* on its class definition, that will be used as the root tag name342* and the given object will provide the body. Otherwise,343* the root tag name is {@link Introspector#decapitalize(String) infered} from344* {@link Class#getSimpleName() the short class name}.345* This parameter must not be null.346*347* @param xml348* The XML will be {@link URLConnection#getOutputStream() sent} to the349* resource pointed by this URL. Note that not all <tt>URL</tt>s support350* such operation, and exact semantics depends on the <tt>URL</tt>351* implementations. In case of {@link HttpURLConnection HTTP URLs},352* this will perform HTTP POST.353*354* @throws DataBindingException355* If the operation fails, such as due to I/O error, unbindable classes.356*/357public static void marshal( Object jaxbObject, URL xml ) {358_marshal(jaxbObject,xml);359}360361/**362* Writes a Java object tree to XML and store it to the specified location.363*364* @param jaxbObject365* The Java object to be marshalled into XML. If this object is366* a {@link JAXBElement}, it will provide the root tag name and367* the body. If this object has {@link XmlRootElement}368* on its class definition, that will be used as the root tag name369* and the given object will provide the body. Otherwise,370* the root tag name is {@link Introspector#decapitalize(String) infered} from371* {@link Class#getSimpleName() the short class name}.372* This parameter must not be null.373*374* @param xml375* The URI is {@link URI#toURL() turned into URL} and then376* follows the handling of <tt>URL</tt>. See above.377*378* @throws DataBindingException379* If the operation fails, such as due to I/O error, unbindable classes.380*/381public static void marshal( Object jaxbObject, URI xml ) {382_marshal(jaxbObject,xml);383}384385/**386* Writes a Java object tree to XML and store it to the specified location.387*388* @param jaxbObject389* The Java object to be marshalled into XML. If this object is390* a {@link JAXBElement}, it will provide the root tag name and391* the body. If this object has {@link XmlRootElement}392* on its class definition, that will be used as the root tag name393* and the given object will provide the body. Otherwise,394* the root tag name is {@link Introspector#decapitalize(String) infered} from395* {@link Class#getSimpleName() the short class name}.396* This parameter must not be null.397*398* @param xml399* The string is first interpreted as an absolute <tt>URI</tt>.400* If it's not {@link URI#isAbsolute() a valid absolute URI},401* then it's interpreted as a <tt>File</tt>402*403* @throws DataBindingException404* If the operation fails, such as due to I/O error, unbindable classes.405*/406public static void marshal( Object jaxbObject, String xml ) {407_marshal(jaxbObject,xml);408}409410/**411* Writes a Java object tree to XML and store it to the specified location.412*413* @param jaxbObject414* The Java object to be marshalled into XML. If this object is415* a {@link JAXBElement}, it will provide the root tag name and416* the body. If this object has {@link XmlRootElement}417* on its class definition, that will be used as the root tag name418* and the given object will provide the body. Otherwise,419* the root tag name is {@link Introspector#decapitalize(String) infered} from420* {@link Class#getSimpleName() the short class name}.421* This parameter must not be null.422*423* @param xml424* The XML will be sent to the given {@link OutputStream}.425* Upon a successful completion, the stream will be closed by this method.426*427* @throws DataBindingException428* If the operation fails, such as due to I/O error, unbindable classes.429*/430public static void marshal( Object jaxbObject, OutputStream xml ) {431_marshal(jaxbObject,xml);432}433434/**435* Writes a Java object tree to XML and store it to the specified location.436*437* @param jaxbObject438* The Java object to be marshalled into XML. If this object is439* a {@link JAXBElement}, it will provide the root tag name and440* the body. If this object has {@link XmlRootElement}441* on its class definition, that will be used as the root tag name442* and the given object will provide the body. Otherwise,443* the root tag name is {@link Introspector#decapitalize(String) infered} from444* {@link Class#getSimpleName() the short class name}.445* This parameter must not be null.446*447* @param xml448* The XML will be sent as a character stream to the given {@link Writer}.449* Upon a successful completion, the stream will be closed by this method.450*451* @throws DataBindingException452* If the operation fails, such as due to I/O error, unbindable classes.453*/454public static void marshal( Object jaxbObject, Writer xml ) {455_marshal(jaxbObject,xml);456}457458/**459* Writes a Java object tree to XML and store it to the specified location.460*461* @param jaxbObject462* The Java object to be marshalled into XML. If this object is463* a {@link JAXBElement}, it will provide the root tag name and464* the body. If this object has {@link XmlRootElement}465* on its class definition, that will be used as the root tag name466* and the given object will provide the body. Otherwise,467* the root tag name is {@link Introspector#decapitalize(String) infered} from468* {@link Class#getSimpleName() the short class name}.469* This parameter must not be null.470*471* @param xml472* The XML will be sent to the {@link Result} object.473*474* @throws DataBindingException475* If the operation fails, such as due to I/O error, unbindable classes.476*/477public static void marshal( Object jaxbObject, Result xml ) {478_marshal(jaxbObject,xml);479}480481/**482* Writes a Java object tree to XML and store it to the specified location.483*484* <p>485* This method is a convenience method that combines several basic operations486* in the {@link JAXBContext} and {@link Marshaller}. This method is designed487* to be the prefered method for developers new to JAXB. This method488* has the following characterstics:489*490* <ol>491* <li>Generally speaking, the performance is not necessarily optimal.492* It is expected that those people who need to write performance493* critical code will use the rest of the JAXB API directly.494* <li>Errors that happen during the processing is wrapped into495* {@link DataBindingException} (which will have {@link JAXBException}496* as its {@link Throwable#getCause() cause}. It is expected that497* those people who prefer the checked exception would use498* the rest of the JAXB API directly.499* </ol>500*501* @param jaxbObject502* The Java object to be marshalled into XML. If this object is503* a {@link JAXBElement}, it will provide the root tag name and504* the body. If this object has {@link XmlRootElement}505* on its class definition, that will be used as the root tag name506* and the given object will provide the body. Otherwise,507* the root tag name is {@link Introspector#decapitalize(String) infered} from508* {@link Class#getSimpleName() the short class name}.509* This parameter must not be null.510*511* @param xml512* Represents the receiver of XML. Objects of the following types are allowed.513*514* <table><tr>515* <th>Type</th>516* <th>Operation</th>517* </tr><tr>518* <td>{@link File}</td>519* <td>XML will be written to this file. If it already exists,520* it will be overwritten.</td>521* </tr><tr>522* <td>{@link URL}</td>523* <td>The XML will be {@link URLConnection#getOutputStream() sent} to the524* resource pointed by this URL. Note that not all <tt>URL</tt>s support525* such operation, and exact semantics depends on the <tt>URL</tt>526* implementations. In case of {@link HttpURLConnection HTTP URLs},527* this will perform HTTP POST.</td>528* </tr><tr>529* <td>{@link URI}</td>530* <td>The URI is {@link URI#toURL() turned into URL} and then531* follows the handling of <tt>URL</tt>. See above.</td>532* </tr><tr>533* <td>{@link String}</td>534* <td>The string is first interpreted as an absolute <tt>URI</tt>.535* If it's not {@link URI#isAbsolute() a valid absolute URI},536* then it's interpreted as a <tt>File</tt></td>537* </tr><tr>538* <td>{@link OutputStream}</td>539* <td>The XML will be sent to the given {@link OutputStream}.540* Upon a successful completion, the stream will be closed by this method.</td>541* </tr><tr>542* <td>{@link Writer}</td>543* <td>The XML will be sent as a character stream to the given {@link Writer}.544* Upon a successful completion, the stream will be closed by this method.</td>545* </tr><tr>546* <td>{@link Result}</td>547* <td>The XML will be sent to the {@link Result} object.</td>548* </tr></table>549*550* @throws DataBindingException551* If the operation fails, such as due to I/O error, unbindable classes.552*/553private static void _marshal( Object jaxbObject, Object xml ) {554try {555JAXBContext context;556557if(jaxbObject instanceof JAXBElement) {558context = getContext(((JAXBElement<?>)jaxbObject).getDeclaredType());559} else {560Class<?> clazz = jaxbObject.getClass();561XmlRootElement r = clazz.getAnnotation(XmlRootElement.class);562context = getContext(clazz);563if(r==null) {564// we need to infer the name565jaxbObject = new JAXBElement(new QName(inferName(clazz)),clazz,jaxbObject);566}567}568569Marshaller m = context.createMarshaller();570m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);571m.marshal(jaxbObject, toResult(xml));572} catch (JAXBException e) {573throw new DataBindingException(e);574} catch (IOException e) {575throw new DataBindingException(e);576}577}578579private static String inferName(Class clazz) {580return Introspector.decapitalize(clazz.getSimpleName());581}582583/**584* Creates {@link Result} from various XML representation.585* See {@link #_marshal(Object,Object)} for the conversion rules.586*/587private static Result toResult(Object xml) throws IOException {588if(xml==null)589throw new IllegalArgumentException("no XML is given");590591if (xml instanceof String) {592try {593xml=new URI((String)xml);594} catch (URISyntaxException e) {595xml=new File((String)xml);596}597}598if (xml instanceof File) {599File file = (File) xml;600return new StreamResult(file);601}602if (xml instanceof URI) {603URI uri = (URI) xml;604xml=uri.toURL();605}606if (xml instanceof URL) {607URL url = (URL) xml;608URLConnection con = url.openConnection();609con.setDoOutput(true);610con.setDoInput(false);611con.connect();612return new StreamResult(con.getOutputStream());613}614if (xml instanceof OutputStream) {615OutputStream os = (OutputStream) xml;616return new StreamResult(os);617}618if (xml instanceof Writer) {619Writer w = (Writer)xml;620return new StreamResult(w);621}622if (xml instanceof Result) {623return (Result) xml;624}625throw new IllegalArgumentException("I don't understand how to handle "+xml.getClass());626}627628}629630631