1
2
3
4
5
6
7
8 package net.sf.jour.rt.view.config.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 {
58 /*** Indentation string. Default is four whitespaces. */
59 private String indent = " ";
60
61 /*** Used to assign prefixes to namespace URIs. */
62 private NamespacePrefixMapper prefixMapper = null;
63
64 /*** Object that handles character escaping. */
65 private CharacterEscapeHandler escapeHandler = null;
66
67 /*** Whether the xml declaration will be printed or not. */
68 private boolean printXmlDeclaration = true;
69
70 /*** XML BLOB written after the XML declaration. */
71 private String header=null;
72
73 /*** reference to the context that created this object */
74 final DefaultJAXBContextImpl context;
75
76 public MarshallerImpl( DefaultJAXBContextImpl c ) {
77
78 DatatypeConverter.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().castToXMLSerializable(obj);
86
87 if(so==null)
88 throw new MarshalException(
89 Messages.format( Messages.NOT_MARSHALLABLE ) );
90
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.newInstance();
102 dbf.setNamespaceAware(true);
103 DocumentBuilder db = dbf.newDocumentBuilder();
104 Document doc = db.newDocument();
105 ((DOMResult) result).setNode(doc);
106 write(so, new SAX2DOMEx(doc));
107 } catch (ParserConfigurationException pce) {
108 throw new JAXBAssertionError(pce);
109 }
110 } else {
111 write(so, new SAX2DOMEx(node));
112 }
113
114 return;
115 }
116 if (result instanceof StreamResult) {
117 StreamResult sr = (StreamResult) result;
118 XMLWriter w = null;
119
120 if (sr.getWriter() != null)
121 w = createWriter(sr.getWriter());
122 else if (sr.getOutputStream() != null)
123 w = createWriter(sr.getOutputStream());
124 else if (sr.getSystemId() != null) {
125 String fileURL = sr.getSystemId();
126
127 if (fileURL.startsWith("file:///")) {
128 if (fileURL.substring(8).indexOf(":") > 0)
129 fileURL = fileURL.substring(8);
130 else
131 fileURL = fileURL.substring(7);
132 }
133
134 try {
135 w = createWriter(new FileOutputStream(fileURL));
136 } catch (IOException e) {
137 throw new MarshalException(e);
138 }
139 }
140
141 if (w == null)
142 throw new IllegalArgumentException();
143
144 write(so, w);
145 return;
146 }
147
148
149 throw new MarshalException(
150 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(
161 getSchemaLocation(),
162 getNoNSSchemaLocation(),
163 writer );
164 }
165
166 SAXMarshaller serializer = new SAXMarshaller(writer,prefixMapper,this);
167
168
169 writer.setDocumentLocator( new LocatorImpl() );
170 writer.startDocument();
171 obj.serializeBody(serializer);
172 writer.endDocument();
173
174 serializer.reconcileID();
175 } catch( SAXException e ) {
176 throw new MarshalException(e);
177 }
178 }
179
180
181
182
183
184
185
186
187 protected CharacterEscapeHandler createEscapeHandler( String encoding ) {
188 if( escapeHandler!=null )
189
190 return escapeHandler;
191
192 if( encoding.startsWith("UTF") )
193
194
195 return MinimumEscapeHandler.theInstance;
196
197
198 try {
199
200 return new NioEscapeHandler( getJavaEncoding(encoding) );
201 } catch( Throwable e ) {
202
203 return DumbEscapeHandler.theInstance;
204 }
205 }
206
207 public XMLWriter createWriter( Writer w, String encoding ) throws JAXBException {
208
209
210 w = new BufferedWriter(w);
211
212 CharacterEscapeHandler ceh = createEscapeHandler(encoding);
213 XMLWriter xw;
214
215 if(isFormattedOutput()) {
216 DataWriter d = new DataWriter(w,encoding,ceh);
217 d.setIndentStep(indent);
218 xw=d;
219 }
220 else
221 xw = new XMLWriter(w,encoding,ceh);
222
223 xw.setXmlDecl(printXmlDeclaration);
224 xw.setHeader(header);
225 return xw;
226 }
227
228 public XMLWriter createWriter(Writer w) throws JAXBException{
229 return createWriter(w, getEncoding());
230 }
231
232 public XMLWriter createWriter( OutputStream os ) throws JAXBException {
233 return createWriter(os, getEncoding());
234 }
235
236 public XMLWriter createWriter( OutputStream os, String encoding ) throws JAXBException {
237 try {
238 return createWriter(
239 new OutputStreamWriter(os,getJavaEncoding(encoding)),
240 encoding );
241 } catch( UnsupportedEncodingException e ) {
242 throw new MarshalException(
243 Messages.format( Messages.UNSUPPORTED_ENCODING, encoding ),
244 e );
245 }
246 }
247
248
249 public Object getProperty(String name) throws PropertyException {
250 if( INDENT_STRING.equals(name) )
251 return indent;
252 if( ENCODING_HANDLER.equals(name) )
253 return escapeHandler;
254 if( PREFIX_MAPPER.equals(name) )
255 return prefixMapper;
256 if( XMLDECLARATION.equals(name) )
257 return printXmlDeclaration ? Boolean.TRUE : Boolean.FALSE;
258 if( XML_HEADERS.equals(name) )
259 return header;
260
261 return super.getProperty(name);
262 }
263
264 public void setProperty(String name, Object value) throws PropertyException {
265 if( INDENT_STRING.equals(name) && value instanceof String ) {
266 indent = (String)value;
267 return;
268 }
269 if( ENCODING_HANDLER.equals(name) ) {
270 escapeHandler = (CharacterEscapeHandler)value;
271 return;
272 }
273 if( PREFIX_MAPPER.equals(name) ) {
274 prefixMapper = (NamespacePrefixMapper)value;
275 return;
276 }
277 if( XMLDECLARATION.equals(name) ) {
278 printXmlDeclaration = ((Boolean)value).booleanValue();
279 return;
280 }
281 if( XML_HEADERS.equals(name) ) {
282 header = (String)value;
283 return;
284 }
285
286 super.setProperty(name, value);
287 }
288
289 private static final String INDENT_STRING = "com.sun.xml.bind.indentString";
290 private static final String PREFIX_MAPPER = "com.sun.xml.bind.namespacePrefixMapper";
291 private static final String ENCODING_HANDLER = "com.sun.xml.bind.characterEscapeHandler";
292 private static final String XMLDECLARATION = "com.sun.xml.bind.xmlDeclaration";
293 private static final String XML_HEADERS = "com.sun.xml.bind.xmlHeaders";
294 }