1 /* 2 * Copyright (c) 2003, 2013, 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 */ 25 26 package javax.xml.bind.helpers; 27 28 import javax.xml.bind.JAXBException; 29 import javax.xml.bind.Marshaller; 30 import javax.xml.bind.PropertyException; 31 import javax.xml.bind.ValidationEventHandler; 32 import javax.xml.bind.annotation.adapters.XmlAdapter; 33 import javax.xml.bind.attachment.AttachmentMarshaller; 34 import javax.xml.stream.XMLEventWriter; 35 import javax.xml.stream.XMLStreamWriter; 36 import javax.xml.transform.dom.DOMResult; 37 import javax.xml.transform.sax.SAXResult; 38 import javax.xml.transform.stream.StreamResult; 39 import javax.xml.validation.Schema; 40 import java.io.UnsupportedEncodingException; 41 import java.io.File; 42 import java.io.OutputStream; 43 import java.io.FileOutputStream; 44 import java.io.BufferedOutputStream; 45 import java.io.IOException; 46 // J2SE1.4 feature 47 // import java.nio.charset.Charset; 48 // import java.nio.charset.UnsupportedCharsetException; 49 50 /** 51 * Partial default <tt>Marshaller</tt> implementation. 52 * 53 * <p> 54 * This class provides a partial default implementation for the 55 * {@link javax.xml.bind.Marshaller} interface. 56 * 57 * <p> 58 * The only methods that a JAXB Provider has to implement are 59 * {@link Marshaller#marshal(Object, javax.xml.transform.Result) marshal(Object, javax.xml.transform.Result)}, 60 * {@link Marshaller#marshal(Object, javax.xml.transform.Result) marshal(Object, javax.xml.stream.XMLStreamWriter)}, and 61 * {@link Marshaller#marshal(Object, javax.xml.transform.Result) marshal(Object, javax.xml.stream.XMLEventWriter)}. 62 * 63 * @author <ul><li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li></ul> 64 * @see javax.xml.bind.Marshaller 65 * @since 1.6, JAXB 1.0 66 */ 67 public abstract class AbstractMarshallerImpl implements Marshaller 68 { 69 /** handler that will be used to process errors and warnings during marshal */ 70 private ValidationEventHandler eventHandler = 71 new DefaultValidationEventHandler(); 72 73 //J2SE1.4 feature 74 //private Charset encoding = null; 75 76 /** store the value of the encoding property. */ 77 private String encoding = "UTF-8"; 78 79 /** store the value of the schemaLocation property. */ 80 private String schemaLocation = null; 81 82 /** store the value of the noNamespaceSchemaLocation property. */ 83 private String noNSSchemaLocation = null; 84 85 /** store the value of the formattedOutput property. */ 86 private boolean formattedOutput = false; 87 88 /** store the value of the fragment property. */ 89 private boolean fragment = false; 90 91 public final void marshal( Object obj, java.io.OutputStream os ) 92 throws JAXBException { 93 94 checkNotNull( obj, "obj", os, "os" ); 95 marshal( obj, new StreamResult(os) ); 96 } 97 98 public void marshal(Object jaxbElement, File output) throws JAXBException { 99 checkNotNull(jaxbElement, "jaxbElement", output, "output" ); 100 try { 101 OutputStream os = new BufferedOutputStream(new FileOutputStream(output)); 102 try { 103 marshal( jaxbElement, new StreamResult(os) ); 104 } finally { 105 os.close(); 106 } 107 } catch (IOException e) { 108 throw new JAXBException(e); 109 } 110 } 111 112 public final void marshal( Object obj, java.io.Writer w ) 113 throws JAXBException { 114 115 checkNotNull( obj, "obj", w, "writer" ); 116 marshal( obj, new StreamResult(w) ); 117 } 118 119 public final void marshal( Object obj, org.xml.sax.ContentHandler handler ) 120 throws JAXBException { 121 122 checkNotNull( obj, "obj", handler, "handler" ); 123 marshal( obj, new SAXResult(handler) ); 124 } 125 126 public final void marshal( Object obj, org.w3c.dom.Node node ) 127 throws JAXBException { 128 129 checkNotNull( obj, "obj", node, "node" ); 130 marshal( obj, new DOMResult(node) ); 131 } 132 133 /** 134 * By default, the getNode method is unsupported and throw 135 * an {@link java.lang.UnsupportedOperationException}. 136 * 137 * Implementations that choose to support this method must 138 * override this method. 139 */ 140 public org.w3c.dom.Node getNode( Object obj ) throws JAXBException { 141 142 checkNotNull( obj, "obj", Boolean.TRUE, "foo" ); 143 144 throw new UnsupportedOperationException(); 145 } 146 147 /** 148 * Convenience method for getting the current output encoding. 149 * 150 * @return the current encoding or "UTF-8" if it hasn't been set. 151 */ 152 protected String getEncoding() { 153 return encoding; 154 } 155 156 /** 157 * Convenience method for setting the output encoding. 158 * 159 * @param encoding a valid encoding as specified in the Marshaller class 160 * documentation 161 */ 162 protected void setEncoding( String encoding ) { 163 this.encoding = encoding; 164 } 165 166 /** 167 * Convenience method for getting the current schemaLocation. 168 * 169 * @return the current schemaLocation or null if it hasn't been set 170 */ 171 protected String getSchemaLocation() { 172 return schemaLocation; 173 } 174 175 /** 176 * Convenience method for setting the schemaLocation. 177 * 178 * @param location the schemaLocation value 179 */ 180 protected void setSchemaLocation( String location ) { 181 schemaLocation = location; 182 } 183 184 /** 185 * Convenience method for getting the current noNamespaceSchemaLocation. 186 * 187 * @return the current noNamespaceSchemaLocation or null if it hasn't 188 * been set 189 */ 190 protected String getNoNSSchemaLocation() { 191 return noNSSchemaLocation; 192 } 193 194 /** 195 * Convenience method for setting the noNamespaceSchemaLocation. 196 * 197 * @param location the noNamespaceSchemaLocation value 198 */ 199 protected void setNoNSSchemaLocation( String location ) { 200 noNSSchemaLocation = location; 201 } 202 203 /** 204 * Convenience method for getting the formatted output flag. 205 * 206 * @return the current value of the formatted output flag or false if 207 * it hasn't been set. 208 */ 209 protected boolean isFormattedOutput() { 210 return formattedOutput; 211 } 212 213 /** 214 * Convenience method for setting the formatted output flag. 215 * 216 * @param v value of the formatted output flag. 217 */ 218 protected void setFormattedOutput( boolean v ) { 219 formattedOutput = v; 220 } 221 222 223 /** 224 * Convenience method for getting the fragment flag. 225 * 226 * @return the current value of the fragment flag or false if 227 * it hasn't been set. 228 */ 229 protected boolean isFragment() { 230 return fragment; 231 } 232 233 /** 234 * Convenience method for setting the fragment flag. 235 * 236 * @param v value of the fragment flag. 237 */ 238 protected void setFragment( boolean v ) { 239 fragment = v; 240 } 241 242 243 static String[] aliases = { 244 "UTF-8", "UTF8", 245 "UTF-16", "Unicode", 246 "UTF-16BE", "UnicodeBigUnmarked", 247 "UTF-16LE", "UnicodeLittleUnmarked", 248 "US-ASCII", "ASCII", 249 "TIS-620", "TIS620", 250 251 // taken from the project-X parser 252 "ISO-10646-UCS-2", "Unicode", 253 254 "EBCDIC-CP-US", "cp037", 255 "EBCDIC-CP-CA", "cp037", 256 "EBCDIC-CP-NL", "cp037", 257 "EBCDIC-CP-WT", "cp037", 258 259 "EBCDIC-CP-DK", "cp277", 260 "EBCDIC-CP-NO", "cp277", 261 "EBCDIC-CP-FI", "cp278", 262 "EBCDIC-CP-SE", "cp278", 263 264 "EBCDIC-CP-IT", "cp280", 265 "EBCDIC-CP-ES", "cp284", 266 "EBCDIC-CP-GB", "cp285", 267 "EBCDIC-CP-FR", "cp297", 268 269 "EBCDIC-CP-AR1", "cp420", 270 "EBCDIC-CP-HE", "cp424", 271 "EBCDIC-CP-BE", "cp500", 272 "EBCDIC-CP-CH", "cp500", 273 274 "EBCDIC-CP-ROECE", "cp870", 275 "EBCDIC-CP-YU", "cp870", 276 "EBCDIC-CP-IS", "cp871", 277 "EBCDIC-CP-AR2", "cp918", 278 279 // IANA also defines two that JDK 1.2 doesn't handle: 280 // EBCDIC-CP-GR --> CP423 281 // EBCDIC-CP-TR --> CP905 282 }; 283 284 /** 285 * Gets the corresponding Java encoding name from an IANA name. 286 * 287 * This method is a helper method for the derived class to convert 288 * encoding names. 289 * 290 * @exception UnsupportedEncodingException 291 * If this implementation couldn't find the Java encoding name. 292 */ 293 protected String getJavaEncoding( String encoding ) throws UnsupportedEncodingException { 294 try { 295 "1".getBytes(encoding); 296 return encoding; 297 } catch( UnsupportedEncodingException e ) { 298 // try known alias 299 for( int i=0; i<aliases.length; i+=2 ) { 300 if(encoding.equals(aliases[i])) { 301 "1".getBytes(aliases[i+1]); 302 return aliases[i+1]; 303 } 304 } 305 306 throw new UnsupportedEncodingException(encoding); 307 } 308 /* J2SE1.4 feature 309 try { 310 this.encoding = Charset.forName( _encoding ); 311 } catch( UnsupportedCharsetException uce ) { 312 throw new JAXBException( uce ); 313 } 314 */ 315 } 316 317 /** 318 * Default implementation of the setProperty method handles 319 * the four defined properties in Marshaller. If a provider 320 * needs to handle additional properties, it should override 321 * this method in a derived class. 322 */ 323 public void setProperty( String name, Object value ) 324 throws PropertyException { 325 326 if( name == null ) { 327 throw new IllegalArgumentException( 328 Messages.format( Messages.MUST_NOT_BE_NULL, "name" ) ); 329 } 330 331 // recognize and handle four pre-defined properties. 332 if( JAXB_ENCODING.equals(name) ) { 333 checkString( name, value ); 334 setEncoding( (String)value ); 335 return; 336 } 337 if( JAXB_FORMATTED_OUTPUT.equals(name) ) { 338 checkBoolean( name, value ); 339 setFormattedOutput((Boolean) value ); 340 return; 341 } 342 if( JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(name) ) { 343 checkString( name, value ); 344 setNoNSSchemaLocation( (String)value ); 345 return; 346 } 347 if( JAXB_SCHEMA_LOCATION.equals(name) ) { 348 checkString( name, value ); 349 setSchemaLocation( (String)value ); 350 return; 351 } 352 if( JAXB_FRAGMENT.equals(name) ) { 353 checkBoolean(name, value); 354 setFragment((Boolean) value ); 355 return; 356 } 357 358 throw new PropertyException(name, value); 359 } 360 361 /** 362 * Default implementation of the getProperty method handles 363 * the four defined properties in Marshaller. If a provider 364 * needs to support additional provider specific properties, 365 * it should override this method in a derived class. 366 */ 367 public Object getProperty( String name ) 368 throws PropertyException { 369 370 if( name == null ) { 371 throw new IllegalArgumentException( 372 Messages.format( Messages.MUST_NOT_BE_NULL, "name" ) ); 373 } 374 375 // recognize and handle four pre-defined properties. 376 if( JAXB_ENCODING.equals(name) ) 377 return getEncoding(); 378 if( JAXB_FORMATTED_OUTPUT.equals(name) ) 379 return isFormattedOutput()?Boolean.TRUE:Boolean.FALSE; 380 if( JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(name) ) 381 return getNoNSSchemaLocation(); 382 if( JAXB_SCHEMA_LOCATION.equals(name) ) 383 return getSchemaLocation(); 384 if( JAXB_FRAGMENT.equals(name) ) 385 return isFragment()?Boolean.TRUE:Boolean.FALSE; 386 387 throw new PropertyException(name); 388 } 389 /** 390 * @see javax.xml.bind.Marshaller#getEventHandler() 391 */ 392 public ValidationEventHandler getEventHandler() throws JAXBException { 393 return eventHandler; 394 } 395 396 /** 397 * @see javax.xml.bind.Marshaller#setEventHandler(ValidationEventHandler) 398 */ 399 public void setEventHandler(ValidationEventHandler handler) 400 throws JAXBException { 401 402 if( handler == null ) { 403 eventHandler = new DefaultValidationEventHandler(); 404 } else { 405 eventHandler = handler; 406 } 407 } 408 409 410 411 412 /* 413 * assert that the given object is a Boolean 414 */ 415 private void checkBoolean( String name, Object value ) throws PropertyException { 416 if(!(value instanceof Boolean)) 417 throw new PropertyException( 418 Messages.format( Messages.MUST_BE_BOOLEAN, name ) ); 419 } 420 421 /* 422 * assert that the given object is a String 423 */ 424 private void checkString( String name, Object value ) throws PropertyException { 425 if(!(value instanceof String)) 426 throw new PropertyException( 427 Messages.format( Messages.MUST_BE_STRING, name ) ); 428 } 429 430 /* 431 * assert that the parameters are not null 432 */ 433 private void checkNotNull( Object o1, String o1Name, 434 Object o2, String o2Name ) { 435 436 if( o1 == null ) { 437 throw new IllegalArgumentException( 438 Messages.format( Messages.MUST_NOT_BE_NULL, o1Name ) ); 439 } 440 if( o2 == null ) { 441 throw new IllegalArgumentException( 442 Messages.format( Messages.MUST_NOT_BE_NULL, o2Name ) ); 443 } 444 } 445 446 public void marshal(Object obj, XMLEventWriter writer) 447 throws JAXBException { 448 449 throw new UnsupportedOperationException(); 450 } 451 452 public void marshal(Object obj, XMLStreamWriter writer) 453 throws JAXBException { 454 455 throw new UnsupportedOperationException(); 456 } 457 458 public void setSchema(Schema schema) { 459 throw new UnsupportedOperationException(); 460 } 461 462 public Schema getSchema() { 463 throw new UnsupportedOperationException(); 464 } 465 466 public void setAdapter(XmlAdapter adapter) { 467 if(adapter==null) 468 throw new IllegalArgumentException(); 469 setAdapter((Class)adapter.getClass(),adapter); 470 } 471 472 public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) { 473 throw new UnsupportedOperationException(); 474 } 475 476 public <A extends XmlAdapter> A getAdapter(Class<A> type) { 477 throw new UnsupportedOperationException(); 478 } 479 480 public void setAttachmentMarshaller(AttachmentMarshaller am) { 481 throw new UnsupportedOperationException(); 482 } 483 484 public AttachmentMarshaller getAttachmentMarshaller() { 485 throw new UnsupportedOperationException(); 486 } 487 488 public void setListener(Listener listener) { 489 throw new UnsupportedOperationException(); 490 } 491 492 public Listener getListener() { 493 throw new UnsupportedOperationException(); 494 } 495 }