001: /*
002: * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
003: * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
004: */
005: package javax.xml.bind.helpers;
006:
007: import javax.xml.bind.JAXBException;
008: import javax.xml.bind.Marshaller;
009: import javax.xml.bind.PropertyException;
010: import javax.xml.bind.ValidationEventHandler;
011: import javax.xml.bind.annotation.adapters.XmlAdapter;
012: import javax.xml.bind.attachment.AttachmentMarshaller;
013: import javax.xml.stream.XMLEventWriter;
014: import javax.xml.stream.XMLStreamWriter;
015: import javax.xml.transform.dom.DOMResult;
016: import javax.xml.transform.sax.SAXResult;
017: import javax.xml.transform.stream.StreamResult;
018: import javax.xml.validation.Schema;
019: import java.io.UnsupportedEncodingException;
020: import java.io.File;
021: import java.io.OutputStream;
022: import java.io.FileOutputStream;
023: import java.io.BufferedOutputStream;
024: import java.io.IOException;
025:
026: // J2SE1.4 feature
027: // import java.nio.charset.Charset;
028: // import java.nio.charset.UnsupportedCharsetException;
029:
030: /**
031: * Partial default <tt>Marshaller</tt> implementation.
032: *
033: * <p>
034: * This class provides a partial default implementation for the
035: * {@link javax.xml.bind.Marshaller} interface.
036: *
037: * <p>
038: * The only methods that a JAXB Provider has to implement are
039: * {@link Marshaller#marshal(Object, javax.xml.transform.Result) marshal(Object, javax.xml.transform.Result)},
040: * {@link Marshaller#marshal(Object, javax.xml.transform.Result) marshal(Object, javax.xml.stream.XMLStreamWriter)}, and
041: * {@link Marshaller#marshal(Object, javax.xml.transform.Result) marshal(Object, javax.xml.stream.XMLEventWriter)}.
042: *
043: * @author <ul><li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li></ul>
044: * @version $Revision: 1.8 $ $Date: 2006/08/28 17:56:38 $
045: * @see javax.xml.bind.Marshaller
046: * @since JAXB1.0
047: */
048: public abstract class AbstractMarshallerImpl implements Marshaller {
049: /** handler that will be used to process errors and warnings during marshal */
050: private ValidationEventHandler eventHandler = new DefaultValidationEventHandler();
051:
052: //J2SE1.4 feature
053: //private Charset encoding = null;
054:
055: /** store the value of the encoding property. */
056: private String encoding = "UTF-8";
057:
058: /** store the value of the schemaLocation property. */
059: private String schemaLocation = null;
060:
061: /** store the value of the noNamespaceSchemaLocation property. */
062: private String noNSSchemaLocation = null;
063:
064: /** store the value of the formattedOutput property. */
065: private boolean formattedOutput = false;
066:
067: /** store the value of the fragment property. */
068: private boolean fragment = false;
069:
070: public final void marshal(Object obj, java.io.OutputStream os)
071: throws JAXBException {
072:
073: checkNotNull(obj, "obj", os, "os");
074: marshal(obj, new StreamResult(os));
075: }
076:
077: public void marshal(Object jaxbElement, File output)
078: throws JAXBException {
079: checkNotNull(jaxbElement, "jaxbElement", output, "output");
080: try {
081: OutputStream os = new BufferedOutputStream(
082: new FileOutputStream(output));
083: try {
084: marshal(jaxbElement, new StreamResult(os));
085: } finally {
086: os.close();
087: }
088: } catch (IOException e) {
089: throw new JAXBException(e);
090: }
091: }
092:
093: public final void marshal(Object obj, java.io.Writer w)
094: throws JAXBException {
095:
096: checkNotNull(obj, "obj", w, "writer");
097: marshal(obj, new StreamResult(w));
098: }
099:
100: public final void marshal(Object obj,
101: org.xml.sax.ContentHandler handler) throws JAXBException {
102:
103: checkNotNull(obj, "obj", handler, "handler");
104: marshal(obj, new SAXResult(handler));
105: }
106:
107: public final void marshal(Object obj, org.w3c.dom.Node node)
108: throws JAXBException {
109:
110: checkNotNull(obj, "obj", node, "node");
111: marshal(obj, new DOMResult(node));
112: }
113:
114: /**
115: * By default, the getNode method is unsupported and throw
116: * an {@link java.lang.UnsupportedOperationException}.
117: *
118: * Implementations that choose to support this method must
119: * override this method.
120: */
121: public org.w3c.dom.Node getNode(Object obj) throws JAXBException {
122:
123: checkNotNull(obj, "obj", Boolean.TRUE, "foo");
124:
125: throw new UnsupportedOperationException();
126: }
127:
128: /**
129: * Convenience method for getting the current output encoding.
130: *
131: * @return the current encoding or "UTF-8" if it hasn't been set.
132: */
133: protected String getEncoding() {
134: return encoding;
135: }
136:
137: /**
138: * Convenience method for setting the output encoding.
139: *
140: * @param encoding a valid encoding as specified in the Marshaller class
141: * documentation
142: */
143: protected void setEncoding(String encoding) {
144: this .encoding = encoding;
145: }
146:
147: /**
148: * Convenience method for getting the current schemaLocation.
149: *
150: * @return the current schemaLocation or null if it hasn't been set
151: */
152: protected String getSchemaLocation() {
153: return schemaLocation;
154: }
155:
156: /**
157: * Convenience method for setting the schemaLocation.
158: *
159: * @param location the schemaLocation value
160: */
161: protected void setSchemaLocation(String location) {
162: schemaLocation = location;
163: }
164:
165: /**
166: * Convenience method for getting the current noNamespaceSchemaLocation.
167: *
168: * @return the current noNamespaceSchemaLocation or null if it hasn't
169: * been set
170: */
171: protected String getNoNSSchemaLocation() {
172: return noNSSchemaLocation;
173: }
174:
175: /**
176: * Convenience method for setting the noNamespaceSchemaLocation.
177: *
178: * @param location the noNamespaceSchemaLocation value
179: */
180: protected void setNoNSSchemaLocation(String location) {
181: noNSSchemaLocation = location;
182: }
183:
184: /**
185: * Convenience method for getting the formatted output flag.
186: *
187: * @return the current value of the formatted output flag or false if
188: * it hasn't been set.
189: */
190: protected boolean isFormattedOutput() {
191: return formattedOutput;
192: }
193:
194: /**
195: * Convenience method for setting the formatted output flag.
196: *
197: * @param v value of the formatted output flag.
198: */
199: protected void setFormattedOutput(boolean v) {
200: formattedOutput = v;
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: static String[] aliases = { "UTF-8", "UTF8", "UTF-16", "Unicode",
223: "UTF-16BE", "UnicodeBigUnmarked",
224: "UTF-16LE",
225: "UnicodeLittleUnmarked",
226: "US-ASCII",
227: "ASCII",
228: "TIS-620",
229: "TIS620",
230:
231: // taken from the project-X parser
232: "ISO-10646-UCS-2", "Unicode",
233:
234: "EBCDIC-CP-US", "cp037", "EBCDIC-CP-CA", "cp037",
235: "EBCDIC-CP-NL", "cp037", "EBCDIC-CP-WT", "cp037",
236:
237: "EBCDIC-CP-DK", "cp277", "EBCDIC-CP-NO", "cp277",
238: "EBCDIC-CP-FI", "cp278", "EBCDIC-CP-SE", "cp278",
239:
240: "EBCDIC-CP-IT", "cp280", "EBCDIC-CP-ES", "cp284",
241: "EBCDIC-CP-GB", "cp285", "EBCDIC-CP-FR", "cp297",
242:
243: "EBCDIC-CP-AR1", "cp420", "EBCDIC-CP-HE", "cp424",
244: "EBCDIC-CP-BE", "cp500", "EBCDIC-CP-CH", "cp500",
245:
246: "EBCDIC-CP-ROECE", "cp870", "EBCDIC-CP-YU", "cp870",
247: "EBCDIC-CP-IS", "cp871", "EBCDIC-CP-AR2", "cp918",
248:
249: // IANA also defines two that JDK 1.2 doesn't handle:
250: // EBCDIC-CP-GR --> CP423
251: // EBCDIC-CP-TR --> CP905
252: };
253:
254: /**
255: * Gets the corresponding Java encoding name from an IANA name.
256: *
257: * This method is a helper method for the derived class to convert
258: * encoding names.
259: *
260: * @exception UnsupportedEncodingException
261: * If this implementation couldn't find the Java encoding name.
262: */
263: protected String getJavaEncoding(String encoding)
264: throws UnsupportedEncodingException {
265: try {
266: "1".getBytes(encoding);
267: return encoding;
268: } catch (UnsupportedEncodingException e) {
269: // try known alias
270: for (int i = 0; i < aliases.length; i += 2) {
271: if (encoding.equals(aliases[i])) {
272: "1".getBytes(aliases[i + 1]);
273: return aliases[i + 1];
274: }
275: }
276:
277: throw new UnsupportedEncodingException(encoding);
278: }
279: /* J2SE1.4 feature
280: try {
281: this.encoding = Charset.forName( _encoding );
282: } catch( UnsupportedCharsetException uce ) {
283: throw new JAXBException( uce );
284: }
285: */
286: }
287:
288: /**
289: * Default implementation of the setProperty method handles
290: * the four defined properties in Marshaller. If a provider
291: * needs to handle additional properties, it should override
292: * this method in a derived class.
293: */
294: public void setProperty(String name, Object value)
295: throws PropertyException {
296:
297: if (name == null) {
298: throw new IllegalArgumentException(Messages.format(
299: Messages.MUST_NOT_BE_NULL, "name"));
300: }
301:
302: // recognize and handle four pre-defined properties.
303: if (JAXB_ENCODING.equals(name)) {
304: checkString(name, value);
305: setEncoding((String) value);
306: return;
307: }
308: if (JAXB_FORMATTED_OUTPUT.equals(name)) {
309: checkBoolean(name, value);
310: setFormattedOutput((Boolean) value);
311: return;
312: }
313: if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(name)) {
314: checkString(name, value);
315: setNoNSSchemaLocation((String) value);
316: return;
317: }
318: if (JAXB_SCHEMA_LOCATION.equals(name)) {
319: checkString(name, value);
320: setSchemaLocation((String) value);
321: return;
322: }
323: if (JAXB_FRAGMENT.equals(name)) {
324: checkBoolean(name, value);
325: setFragment((Boolean) value);
326: return;
327: }
328:
329: throw new PropertyException(name, value);
330: }
331:
332: /**
333: * Default implementation of the getProperty method handles
334: * the four defined properties in Marshaller. If a provider
335: * needs to support additional provider specific properties,
336: * it should override this method in a derived class.
337: */
338: public Object getProperty(String name) throws PropertyException {
339:
340: if (name == null) {
341: throw new IllegalArgumentException(Messages.format(
342: Messages.MUST_NOT_BE_NULL, "name"));
343: }
344:
345: // recognize and handle four pre-defined properties.
346: if (JAXB_ENCODING.equals(name))
347: return getEncoding();
348: if (JAXB_FORMATTED_OUTPUT.equals(name))
349: return isFormattedOutput() ? Boolean.TRUE : Boolean.FALSE;
350: if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(name))
351: return getNoNSSchemaLocation();
352: if (JAXB_SCHEMA_LOCATION.equals(name))
353: return getSchemaLocation();
354: if (JAXB_FRAGMENT.equals(name))
355: return isFragment() ? Boolean.TRUE : Boolean.FALSE;
356:
357: throw new PropertyException(name);
358: }
359:
360: /**
361: * @see javax.xml.bind.Marshaller#getEventHandler()
362: */
363: public ValidationEventHandler getEventHandler()
364: throws JAXBException {
365: return eventHandler;
366: }
367:
368: /**
369: * @see javax.xml.bind.Marshaller#setEventHandler(ValidationEventHandler)
370: */
371: public void setEventHandler(ValidationEventHandler handler)
372: throws JAXBException {
373:
374: if (handler == null) {
375: eventHandler = new DefaultValidationEventHandler();
376: } else {
377: eventHandler = handler;
378: }
379: }
380:
381: /*
382: * assert that the given object is a Boolean
383: */
384: private void checkBoolean(String name, Object value)
385: throws PropertyException {
386: if (!(value instanceof Boolean))
387: throw new PropertyException(Messages.format(
388: Messages.MUST_BE_BOOLEAN, name));
389: }
390:
391: /*
392: * assert that the given object is a String
393: */
394: private void checkString(String name, Object value)
395: throws PropertyException {
396: if (!(value instanceof String))
397: throw new PropertyException(Messages.format(
398: Messages.MUST_BE_STRING, name));
399: }
400:
401: /*
402: * assert that the parameters are not null
403: */
404: private void checkNotNull(Object o1, String o1Name, Object o2,
405: String o2Name) {
406:
407: if (o1 == null) {
408: throw new IllegalArgumentException(Messages.format(
409: Messages.MUST_NOT_BE_NULL, o1Name));
410: }
411: if (o2 == null) {
412: throw new IllegalArgumentException(Messages.format(
413: Messages.MUST_NOT_BE_NULL, o2Name));
414: }
415: }
416:
417: public void marshal(Object obj, XMLEventWriter writer)
418: throws JAXBException {
419:
420: throw new UnsupportedOperationException();
421: }
422:
423: public void marshal(Object obj, XMLStreamWriter writer)
424: throws JAXBException {
425:
426: throw new UnsupportedOperationException();
427: }
428:
429: public void setSchema(Schema schema) {
430: throw new UnsupportedOperationException();
431: }
432:
433: public Schema getSchema() {
434: throw new UnsupportedOperationException();
435: }
436:
437: public void setAdapter(XmlAdapter adapter) {
438: if (adapter == null)
439: throw new IllegalArgumentException();
440: setAdapter((Class) adapter.getClass(), adapter);
441: }
442:
443: public <A extends XmlAdapter> void setAdapter(Class<A> type,
444: A adapter) {
445: throw new UnsupportedOperationException();
446: }
447:
448: public <A extends XmlAdapter> A getAdapter(Class<A> type) {
449: throw new UnsupportedOperationException();
450: }
451:
452: public void setAttachmentMarshaller(AttachmentMarshaller am) {
453: throw new UnsupportedOperationException();
454: }
455:
456: public AttachmentMarshaller getAttachmentMarshaller() {
457: throw new UnsupportedOperationException();
458: }
459:
460: public void setListener(Listener listener) {
461: throw new UnsupportedOperationException();
462: }
463:
464: public Listener getListener() {
465: throw new UnsupportedOperationException();
466: }
467: }
|