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