ohair@286: /*
ohair@286: * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286: *
ohair@286: * This code is free software; you can redistribute it and/or modify it
ohair@286: * under the terms of the GNU General Public License version 2 only, as
ohair@286: * published by the Free Software Foundation. Oracle designates this
ohair@286: * particular file as subject to the "Classpath" exception as provided
ohair@286: * by Oracle in the LICENSE file that accompanied this code.
ohair@286: *
ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286: * version 2 for more details (a copy is included in the LICENSE file that
ohair@286: * accompanied this code).
ohair@286: *
ohair@286: * You should have received a copy of the GNU General Public License version
ohair@286: * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286: *
ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286: * or visit www.oracle.com if you need additional information or have any
ohair@286: * questions.
ohair@286: */
ohair@286:
ohair@286: package javax.xml.bind;
ohair@286:
ohair@286: import javax.xml.bind.annotation.XmlRootElement;
ohair@286: import javax.xml.namespace.QName;
ohair@286: import javax.xml.transform.Result;
ohair@286: import javax.xml.transform.Source;
ohair@286: import javax.xml.transform.stream.StreamResult;
ohair@286: import javax.xml.transform.stream.StreamSource;
ohair@286: import java.beans.Introspector;
ohair@286: import java.io.File;
ohair@286: import java.io.IOException;
ohair@286: import java.io.InputStream;
ohair@286: import java.io.OutputStream;
ohair@286: import java.io.Reader;
ohair@286: import java.io.Writer;
ohair@286: import java.lang.ref.WeakReference;
ohair@286: import java.net.HttpURLConnection;
ohair@286: import java.net.URI;
ohair@286: import java.net.URISyntaxException;
ohair@286: import java.net.URL;
ohair@286: import java.net.URLConnection;
ohair@286:
ohair@286: /**
ohair@286: * Class that defines convenience methods for common, simple use of JAXB.
ohair@286: *
ohair@286: *
ohair@286: * Methods defined in this class are convenience methods that combine several basic operations
ohair@286: * in the {@link JAXBContext}, {@link Unmarshaller}, and {@link Marshaller}.
ohair@286: *
ohair@286: * They are designed
ohair@286: * to be the prefered methods for developers new to JAXB. They have
ohair@286: * the following characterstics:
ohair@286: *
ohair@286: *
ohair@286: * - Generally speaking, the performance is not necessarily optimal.
ohair@286: * It is expected that people who need to write performance
ohair@286: * critical code will use the rest of the JAXB API directly.
ohair@286: *
- Errors that happen during the processing is wrapped into
ohair@286: * {@link DataBindingException} (which will have {@link JAXBException}
ohair@286: * as its {@link Throwable#getCause() cause}. It is expected that
ohair@286: * people who prefer the checked exception would use
ohair@286: * the rest of the JAXB API directly.
ohair@286: *
ohair@286: *
ohair@286: *
ohair@286: * In addition, the unmarshal methods have the following characteristic:
ohair@286: *
ohair@286: *
ohair@286: * - Schema validation is not performed on the input XML.
ohair@286: * The processing will try to continue even if there
ohair@286: * are errors in the XML, as much as possible. Only as
ohair@286: * the last resort, this method fails with {@link DataBindingException}.
ohair@286: *
ohair@286: *
ohair@286: *
ohair@286: * Similarly, the marshal methods have the following characteristic:
ohair@286: *
ohair@286: * - The processing will try to continue even if the Java object tree
ohair@286: * does not meet the validity requirement. Only as
ohair@286: * the last resort, this method fails with {@link DataBindingException}.
ohair@286: *
ohair@286: *
ohair@286: *
ohair@286: *
ohair@286: * All the methods on this class require non-null arguments to all parameters.
ohair@286: * The unmarshal methods either fail with an exception or return
ohair@286: * a non-null value.
ohair@286: *
ohair@286: * @author Kohsuke Kawaguchi
ohair@286: * @since 2.1
ohair@286: */
ohair@286: public final class JAXB {
ohair@286: /**
ohair@286: * No instanciation is allowed.
ohair@286: */
ohair@286: private JAXB() {}
ohair@286:
ohair@286: /**
ohair@286: * To improve the performance, we'll cache the last {@link JAXBContext} used.
ohair@286: */
ohair@286: private static final class Cache {
ohair@286: final Class type;
ohair@286: final JAXBContext context;
ohair@286:
ohair@286: public Cache(Class type) throws JAXBException {
ohair@286: this.type = type;
ohair@286: this.context = JAXBContext.newInstance(type);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Cache. We don't want to prevent the {@link Cache#type} from GC-ed,
ohair@286: * hence {@link WeakReference}.
ohair@286: */
ohair@286: private static volatile WeakReference cache;
ohair@286:
ohair@286: /**
ohair@286: * Obtains the {@link JAXBContext} from the given type,
ohair@286: * by using the cache if possible.
ohair@286: *
ohair@286: *
ohair@286: * We don't use locks to control access to {@link #cache}, but this code
ohair@286: * should be thread-safe thanks to the immutable {@link Cache} and {@code volatile}.
ohair@286: */
ohair@286: private static JAXBContext getContext(Class type) throws JAXBException {
ohair@286: WeakReference c = cache;
ohair@286: if(c!=null) {
ohair@286: Cache d = c.get();
ohair@286: if(d!=null && d.type==type)
ohair@286: return d.context;
ohair@286: }
ohair@286:
ohair@286: // overwrite the cache
ohair@286: Cache d = new Cache(type);
ohair@286: cache = new WeakReference(d);
ohair@286:
ohair@286: return d.context;
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * Reads the entire file as XML.
ohair@286: */
ohair@286: public static T unmarshal( File xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(new StreamSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The resource pointed by the URL is read in its entirety.
ohair@286: */
ohair@286: public static T unmarshal( URL xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The URI is {@link URI#toURL() turned into URL} and then
ohair@286: * follows the handling of URL.
ohair@286: */
ohair@286: public static T unmarshal( URI xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The string is first interpreted as an absolute URI.
ohair@286: * If it's not {@link URI#isAbsolute() a valid absolute URI},
ohair@286: * then it's interpreted as a File
ohair@286: */
ohair@286: public static T unmarshal( String xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The entire stream is read as an XML infoset.
ohair@286: * Upon a successful completion, the stream will be closed by this method.
ohair@286: */
ohair@286: public static T unmarshal( InputStream xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The character stream is read as an XML infoset.
ohair@286: * The encoding declaration in the XML will be ignored.
ohair@286: * Upon a successful completion, the stream will be closed by this method.
ohair@286: */
ohair@286: public static T unmarshal( Reader xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Reads in a Java object tree from the given XML input.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The XML infoset that the {@link Source} represents is read.
ohair@286: */
ohair@286: public static T unmarshal( Source xml, Class type ) {
ohair@286: try {
ohair@286: JAXBElement item = getContext(type).createUnmarshaller().unmarshal(toSource(xml), type);
ohair@286: return item.getValue();
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286:
ohair@286:
ohair@286: /**
ohair@286: * Creates {@link Source} from various XML representation.
ohair@286: * See {@link #unmarshal} for the conversion rules.
ohair@286: */
ohair@286: private static Source toSource(Object xml) throws IOException {
ohair@286: if(xml==null)
ohair@286: throw new IllegalArgumentException("no XML is given");
ohair@286:
ohair@286: if (xml instanceof String) {
ohair@286: try {
ohair@286: xml=new URI((String)xml);
ohair@286: } catch (URISyntaxException e) {
ohair@286: xml=new File((String)xml);
ohair@286: }
ohair@286: }
ohair@286: if (xml instanceof File) {
ohair@286: File file = (File) xml;
ohair@286: return new StreamSource(file);
ohair@286: }
ohair@286: if (xml instanceof URI) {
ohair@286: URI uri = (URI) xml;
ohair@286: xml=uri.toURL();
ohair@286: }
ohair@286: if (xml instanceof URL) {
ohair@286: URL url = (URL) xml;
ohair@286: return new StreamSource(url.toExternalForm());
ohair@286: }
ohair@286: if (xml instanceof InputStream) {
ohair@286: InputStream in = (InputStream) xml;
ohair@286: return new StreamSource(in);
ohair@286: }
ohair@286: if (xml instanceof Reader) {
ohair@286: Reader r = (Reader) xml;
ohair@286: return new StreamSource(r);
ohair@286: }
ohair@286: if (xml instanceof Source) {
ohair@286: return (Source) xml;
ohair@286: }
ohair@286: throw new IllegalArgumentException("I don't understand how to handle "+xml.getClass());
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * XML will be written to this file. If it already exists,
ohair@286: * it will be overwritten.
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, File xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The XML will be {@link URLConnection#getOutputStream() sent} to the
ohair@286: * resource pointed by this URL. Note that not all URLs support
ohair@286: * such operation, and exact semantics depends on the URL
ohair@286: * implementations. In case of {@link HttpURLConnection HTTP URLs},
ohair@286: * this will perform HTTP POST.
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, URL xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The URI is {@link URI#toURL() turned into URL} and then
ohair@286: * follows the handling of URL. See above.
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, URI xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The string is first interpreted as an absolute URI.
ohair@286: * If it's not {@link URI#isAbsolute() a valid absolute URI},
ohair@286: * then it's interpreted as a File
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, String xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The XML will be sent to the given {@link OutputStream}.
ohair@286: * Upon a successful completion, the stream will be closed by this method.
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, OutputStream xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The XML will be sent as a character stream to the given {@link Writer}.
ohair@286: * Upon a successful completion, the stream will be closed by this method.
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, Writer xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * The XML will be sent to the {@link Result} object.
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: public static void marshal( Object jaxbObject, Result xml ) {
ohair@286: _marshal(jaxbObject,xml);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Writes a Java object tree to XML and store it to the specified location.
ohair@286: *
ohair@286: *
ohair@286: * This method is a convenience method that combines several basic operations
ohair@286: * in the {@link JAXBContext} and {@link Marshaller}. This method is designed
ohair@286: * to be the prefered method for developers new to JAXB. This method
ohair@286: * has the following characterstics:
ohair@286: *
ohair@286: *
ohair@286: * - Generally speaking, the performance is not necessarily optimal.
ohair@286: * It is expected that those people who need to write performance
ohair@286: * critical code will use the rest of the JAXB API directly.
ohair@286: *
- Errors that happen during the processing is wrapped into
ohair@286: * {@link DataBindingException} (which will have {@link JAXBException}
ohair@286: * as its {@link Throwable#getCause() cause}. It is expected that
ohair@286: * those people who prefer the checked exception would use
ohair@286: * the rest of the JAXB API directly.
ohair@286: *
ohair@286: *
ohair@286: * @param jaxbObject
ohair@286: * The Java object to be marshalled into XML. If this object is
ohair@286: * a {@link JAXBElement}, it will provide the root tag name and
ohair@286: * the body. If this object has {@link XmlRootElement}
ohair@286: * on its class definition, that will be used as the root tag name
ohair@286: * and the given object will provide the body. Otherwise,
ohair@286: * the root tag name is {@link Introspector#decapitalize(String) infered} from
ohair@286: * {@link Class#getSimpleName() the short class name}.
ohair@286: * This parameter must not be null.
ohair@286: *
ohair@286: * @param xml
ohair@286: * Represents the receiver of XML. Objects of the following types are allowed.
ohair@286: *
ohair@286: *
ohair@286: * Type |
ohair@286: * Operation |
ohair@286: *
ohair@286: * {@link File} |
ohair@286: * XML will be written to this file. If it already exists,
ohair@286: * it will be overwritten. |
ohair@286: *
ohair@286: * {@link URL} |
ohair@286: * The XML will be {@link URLConnection#getOutputStream() sent} to the
ohair@286: * resource pointed by this URL. Note that not all URLs support
ohair@286: * such operation, and exact semantics depends on the URL
ohair@286: * implementations. In case of {@link HttpURLConnection HTTP URLs},
ohair@286: * this will perform HTTP POST. |
ohair@286: *
ohair@286: * {@link URI} |
ohair@286: * The URI is {@link URI#toURL() turned into URL} and then
ohair@286: * follows the handling of URL. See above. |
ohair@286: *
ohair@286: * {@link String} |
ohair@286: * The string is first interpreted as an absolute URI.
ohair@286: * If it's not {@link URI#isAbsolute() a valid absolute URI},
ohair@286: * then it's interpreted as a File |
ohair@286: *
ohair@286: * {@link OutputStream} |
ohair@286: * The XML will be sent to the given {@link OutputStream}.
ohair@286: * Upon a successful completion, the stream will be closed by this method. |
ohair@286: *
ohair@286: * {@link Writer} |
ohair@286: * The XML will be sent as a character stream to the given {@link Writer}.
ohair@286: * Upon a successful completion, the stream will be closed by this method. |
ohair@286: *
ohair@286: * {@link Result} |
ohair@286: * The XML will be sent to the {@link Result} object. |
ohair@286: *
ohair@286: *
ohair@286: * @throws DataBindingException
ohair@286: * If the operation fails, such as due to I/O error, unbindable classes.
ohair@286: */
ohair@286: private static void _marshal( Object jaxbObject, Object xml ) {
ohair@286: try {
ohair@286: JAXBContext context;
ohair@286:
ohair@286: if(jaxbObject instanceof JAXBElement) {
ohair@286: context = getContext(((JAXBElement>)jaxbObject).getDeclaredType());
ohair@286: } else {
ohair@286: Class> clazz = jaxbObject.getClass();
ohair@286: XmlRootElement r = clazz.getAnnotation(XmlRootElement.class);
ohair@286: context = getContext(clazz);
ohair@286: if(r==null) {
ohair@286: // we need to infer the name
ohair@286: jaxbObject = new JAXBElement(new QName(inferName(clazz)),clazz,jaxbObject);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: Marshaller m = context.createMarshaller();
ohair@286: m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
ohair@286: m.marshal(jaxbObject, toResult(xml));
ohair@286: } catch (JAXBException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: } catch (IOException e) {
ohair@286: throw new DataBindingException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: private static String inferName(Class clazz) {
ohair@286: return Introspector.decapitalize(clazz.getSimpleName());
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Creates {@link Result} from various XML representation.
ohair@286: * See {@link #_marshal(Object,Object)} for the conversion rules.
ohair@286: */
ohair@286: private static Result toResult(Object xml) throws IOException {
ohair@286: if(xml==null)
ohair@286: throw new IllegalArgumentException("no XML is given");
ohair@286:
ohair@286: if (xml instanceof String) {
ohair@286: try {
ohair@286: xml=new URI((String)xml);
ohair@286: } catch (URISyntaxException e) {
ohair@286: xml=new File((String)xml);
ohair@286: }
ohair@286: }
ohair@286: if (xml instanceof File) {
ohair@286: File file = (File) xml;
ohair@286: return new StreamResult(file);
ohair@286: }
ohair@286: if (xml instanceof URI) {
ohair@286: URI uri = (URI) xml;
ohair@286: xml=uri.toURL();
ohair@286: }
ohair@286: if (xml instanceof URL) {
ohair@286: URL url = (URL) xml;
ohair@286: URLConnection con = url.openConnection();
ohair@286: con.setDoOutput(true);
ohair@286: con.setDoInput(false);
ohair@286: con.connect();
ohair@286: return new StreamResult(con.getOutputStream());
ohair@286: }
ohair@286: if (xml instanceof OutputStream) {
ohair@286: OutputStream os = (OutputStream) xml;
ohair@286: return new StreamResult(os);
ohair@286: }
ohair@286: if (xml instanceof Writer) {
ohair@286: Writer w = (Writer)xml;
ohair@286: return new StreamResult(w);
ohair@286: }
ohair@286: if (xml instanceof Result) {
ohair@286: return (Result) xml;
ohair@286: }
ohair@286: throw new IllegalArgumentException("I don't understand how to handle "+xml.getClass());
ohair@286: }
ohair@286:
ohair@286: }