1
2
3
4
5
6
7
8 package de.nierbeck.timeTrack.model.impl.runtime;
9
10 import java.io.BufferedWriter;
11 import java.io.FileOutputStream;
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.io.OutputStreamWriter;
15 import java.io.UnsupportedEncodingException;
16 import java.io.Writer;
17
18 import javax.xml.bind.DatatypeConverter;
19 import javax.xml.bind.JAXBException;
20 import javax.xml.bind.MarshalException;
21 import javax.xml.bind.PropertyException;
22 import javax.xml.bind.helpers.AbstractMarshallerImpl;
23 import javax.xml.parsers.DocumentBuilder;
24 import javax.xml.parsers.DocumentBuilderFactory;
25 import javax.xml.parsers.ParserConfigurationException;
26 import javax.xml.transform.Result;
27 import javax.xml.transform.dom.DOMResult;
28 import javax.xml.transform.sax.SAXResult;
29 import javax.xml.transform.stream.StreamResult;
30
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Node;
33 import org.xml.sax.ContentHandler;
34 import org.xml.sax.SAXException;
35 import org.xml.sax.helpers.LocatorImpl;
36
37 import com.sun.xml.bind.DatatypeConverterImpl;
38 import com.sun.xml.bind.JAXBAssertionError;
39 import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
40 import com.sun.xml.bind.marshaller.DataWriter;
41 import com.sun.xml.bind.marshaller.DumbEscapeHandler;
42 import com.sun.xml.bind.marshaller.Messages;
43 import com.sun.xml.bind.marshaller.MinimumEscapeHandler;
44 import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
45 import com.sun.xml.bind.marshaller.NioEscapeHandler;
46 import com.sun.xml.bind.marshaller.SAX2DOMEx;
47 import com.sun.xml.bind.marshaller.SchemaLocationFilter;
48 import com.sun.xml.bind.marshaller.XMLWriter;
49
50 /***
51 * Implementation of {@link Marshaller} interface for JAXB RI.
52 *
53 * @author Kohsuke Kawaguchi
54 * @author Vivek Pandey
55 */
56 public class MarshallerImpl extends AbstractMarshallerImpl {
57 /*** Indentation string. Default is four whitespaces. */
58 private String indent = " ";
59
60 /*** Used to assign prefixes to namespace URIs. */
61 private NamespacePrefixMapper prefixMapper = null;
62
63 /*** Object that handles character escaping. */
64 private CharacterEscapeHandler escapeHandler = null;
65
66 /*** Whether the xml declaration will be printed or not. */
67 private boolean printXmlDeclaration = true;
68
69 /*** XML BLOB written after the XML declaration. */
70 private String header = null;
71
72 /*** reference to the context that created this object */
73 final DefaultJAXBContextImpl context;
74
75 public MarshallerImpl(DefaultJAXBContextImpl c) {
76
77 DatatypeConverter
78 .setDatatypeConverter(DatatypeConverterImpl.theInstance);
79
80 context = c;
81 }
82
83 public void marshal(Object obj, Result result) throws JAXBException {
84
85 XMLSerializable so = context.getGrammarInfo()
86 .castToXMLSerializable(obj);
87
88 if (so == null)
89 throw new MarshalException(Messages
90 .format(Messages.NOT_MARSHALLABLE));
91
92 if (result instanceof SAXResult) {
93 write(so, ((SAXResult) result).getHandler());
94 return;
95 }
96 if (result instanceof DOMResult) {
97 Node node = ((DOMResult) result).getNode();
98
99 if (node == null) {
100 try {
101 DocumentBuilderFactory dbf = DocumentBuilderFactory
102 .newInstance();
103 dbf.setNamespaceAware(true);
104 DocumentBuilder db = dbf.newDocumentBuilder();
105 Document doc = db.newDocument();
106 ((DOMResult) result).setNode(doc);
107 write(so, new SAX2DOMEx(doc));
108 } catch (ParserConfigurationException pce) {
109 throw new JAXBAssertionError(pce);
110 }
111 } else {
112 write(so, new SAX2DOMEx(node));
113 }
114
115 return;
116 }
117 if (result instanceof StreamResult) {
118 StreamResult sr = (StreamResult) result;
119 XMLWriter w = null;
120
121 if (sr.getWriter() != null)
122 w = createWriter(sr.getWriter());
123 else if (sr.getOutputStream() != null)
124 w = createWriter(sr.getOutputStream());
125 else if (sr.getSystemId() != null) {
126 String fileURL = sr.getSystemId();
127
128 if (fileURL.startsWith("file:///")) {
129 if (fileURL.substring(8).indexOf(":") > 0)
130 fileURL = fileURL.substring(8);
131 else
132 fileURL = fileURL.substring(7);
133 }
134
135 try {
136 w = createWriter(new FileOutputStream(fileURL));
137 } catch (IOException e) {
138 throw new MarshalException(e);
139 }
140 }
141
142 if (w == null)
143 throw new IllegalArgumentException();
144
145 write(so, w);
146 return;
147 }
148
149
150 throw new MarshalException(Messages.format(Messages.UNSUPPORTED_RESULT));
151 }
152
153 private void write(XMLSerializable obj, ContentHandler writer)
154 throws JAXBException {
155
156 try {
157 if (getSchemaLocation() != null || getNoNSSchemaLocation() != null) {
158
159
160 writer = new SchemaLocationFilter(getSchemaLocation(),
161 getNoNSSchemaLocation(), writer);
162 }
163
164 SAXMarshaller serializer = new SAXMarshaller(writer, prefixMapper,
165 this);
166
167
168 writer.setDocumentLocator(new LocatorImpl());
169 writer.startDocument();
170 serializer.childAsBody(obj, null);
171 writer.endDocument();
172
173 serializer.reconcileID();
174 } catch (SAXException e) {
175 throw new MarshalException(e);
176 }
177 }
178
179
180
181
182
183
184
185 protected CharacterEscapeHandler createEscapeHandler(String encoding) {
186 if (escapeHandler != null)
187
188 return escapeHandler;
189
190 if (encoding.startsWith("UTF"))
191
192
193 return MinimumEscapeHandler.theInstance;
194
195
196 try {
197
198 return new NioEscapeHandler(getJavaEncoding(encoding));
199 } catch (Throwable e) {
200
201 return DumbEscapeHandler.theInstance;
202 }
203 }
204
205 public XMLWriter createWriter(Writer w, String encoding)
206 throws JAXBException {
207
208
209 w = new BufferedWriter(w);
210
211 CharacterEscapeHandler ceh = createEscapeHandler(encoding);
212 XMLWriter xw;
213
214 if (isFormattedOutput()) {
215 DataWriter d = new DataWriter(w, encoding, ceh);
216 d.setIndentStep(indent);
217 xw = d;
218 } else
219 xw = new XMLWriter(w, encoding, ceh);
220
221 xw.setXmlDecl(printXmlDeclaration);
222 xw.setHeader(header);
223 return xw;
224 }
225
226 public XMLWriter createWriter(Writer w) throws JAXBException {
227 return createWriter(w, getEncoding());
228 }
229
230 public XMLWriter createWriter(OutputStream os) throws JAXBException {
231 return createWriter(os, getEncoding());
232 }
233
234 public XMLWriter createWriter(OutputStream os, String encoding)
235 throws JAXBException {
236 try {
237 return createWriter(new OutputStreamWriter(os,
238 getJavaEncoding(encoding)), encoding);
239 } catch (UnsupportedEncodingException e) {
240 throw new MarshalException(Messages.format(
241 Messages.UNSUPPORTED_ENCODING, encoding), e);
242 }
243 }
244
245 public Object getProperty(String name) throws PropertyException {
246 if (INDENT_STRING.equals(name))
247 return indent;
248 if (ENCODING_HANDLER.equals(name))
249 return escapeHandler;
250 if (PREFIX_MAPPER.equals(name))
251 return prefixMapper;
252 if (XMLDECLARATION.equals(name))
253 return printXmlDeclaration ? Boolean.TRUE : Boolean.FALSE;
254 if (XML_HEADERS.equals(name))
255 return header;
256
257 return super.getProperty(name);
258 }
259
260 public void setProperty(String name, Object value) throws PropertyException {
261 if (INDENT_STRING.equals(name) && value instanceof String) {
262 indent = (String) value;
263 return;
264 }
265 if (ENCODING_HANDLER.equals(name)) {
266 escapeHandler = (CharacterEscapeHandler) value;
267 return;
268 }
269 if (PREFIX_MAPPER.equals(name)) {
270 prefixMapper = (NamespacePrefixMapper) value;
271 return;
272 }
273 if (XMLDECLARATION.equals(name)) {
274 printXmlDeclaration = ((Boolean) value).booleanValue();
275 return;
276 }
277 if (XML_HEADERS.equals(name)) {
278 header = (String) value;
279 return;
280 }
281
282 super.setProperty(name, value);
283 }
284
285 private static final String INDENT_STRING = "com.sun.xml.bind.indentString";
286
287 private static final String PREFIX_MAPPER = "com.sun.xml.bind.namespacePrefixMapper";
288
289 private static final String ENCODING_HANDLER = "com.sun.xml.bind.characterEscapeHandler";
290
291 private static final String XMLDECLARATION = "com.sun.xml.bind.xmlDeclaration";
292
293 private static final String XML_HEADERS = "com.sun.xml.bind.xmlHeaders";
294 }