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