1
15
16 package com.ctc.wstx.stax;
17
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import java.io.OutputStreamWriter;
21 import java.io.Writer;
22
23 import javax.xml.stream.XMLEventWriter;
24 import javax.xml.stream.XMLOutputFactory;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.XMLStreamWriter;
27 import javax.xml.transform.Result;
28 import javax.xml.transform.dom.DOMResult;
29 import javax.xml.transform.sax.SAXResult;
30 import javax.xml.transform.stream.StreamResult;
31
32 import org.codehaus.stax2.XMLOutputFactory2;
33 import org.codehaus.stax2.XMLStreamWriter2;
34 import org.codehaus.stax2.io.Stax2Result;
35 import org.codehaus.stax2.ri.Stax2EventWriterImpl;
36 import org.codehaus.stax2.ri.Stax2WriterAdapter;
37
38 import com.ctc.wstx.api.WriterConfig;
39 import com.ctc.wstx.api.WstxOutputProperties;
40 import com.ctc.wstx.cfg.OutputConfigFlags;
41 import com.ctc.wstx.dom.WstxDOMWrappingWriter;
42 import com.ctc.wstx.exc.WstxIOException;
43 import com.ctc.wstx.io.CharsetNames;
44 import com.ctc.wstx.io.UTF8Writer;
45 import com.ctc.wstx.sw.AsciiXmlWriter;
46 import com.ctc.wstx.sw.BufferingXmlWriter;
47 import com.ctc.wstx.sw.ISOLatin1XmlWriter;
48 import com.ctc.wstx.sw.NonNsStreamWriter;
49 import com.ctc.wstx.sw.RepairingNsStreamWriter;
50 import com.ctc.wstx.sw.SimpleNsStreamWriter;
51 import com.ctc.wstx.sw.XmlWriter;
52 import com.ctc.wstx.util.URLUtil;
53
54
64 public class WstxOutputFactory
65 extends XMLOutputFactory2
66 implements OutputConfigFlags
67 {
68
73
74 protected final WriterConfig mConfig;
75
76
81
82 public WstxOutputFactory() {
83 mConfig = WriterConfig.createFullDefaults();
84 }
85
86
91
92 @Override
93 public XMLEventWriter createXMLEventWriter(OutputStream out)
94 throws XMLStreamException
95 {
96 return createXMLEventWriter(out, null);
97 }
98
99 @Override
100 public XMLEventWriter createXMLEventWriter(OutputStream out, String enc)
101 throws XMLStreamException
102 {
103 if (out == null) {
104 throw new IllegalArgumentException("Null OutputStream is not a valid argument");
105 }
106 return new Stax2EventWriterImpl(createSW(out, null, enc, false));
107 }
108
109 @Override
110 public XMLEventWriter createXMLEventWriter(javax.xml.transform.Result result)
111 throws XMLStreamException
112 {
113 return new Stax2EventWriterImpl(createSW(result));
114 }
115
116 @Override
117 public XMLEventWriter createXMLEventWriter(Writer w)
118 throws XMLStreamException
119 {
120 if (w == null) {
121 throw new IllegalArgumentException("Null Writer is not a valid argument");
122 }
123 return new Stax2EventWriterImpl(createSW(null, w, null, false));
124 }
125
126 @Override
127 public XMLStreamWriter createXMLStreamWriter(OutputStream out)
128 throws XMLStreamException
129 {
130 return createXMLStreamWriter(out, null);
131 }
132
133 @Override
134 public XMLStreamWriter createXMLStreamWriter(OutputStream out, String enc)
135 throws XMLStreamException
136 {
137 if (out == null) {
138 throw new IllegalArgumentException("Null OutputStream is not a valid argument");
139 }
140 return createSW(out, null, enc, false);
141 }
142
143 @Override
144 public XMLStreamWriter createXMLStreamWriter(javax.xml.transform.Result result)
145 throws XMLStreamException
146 {
147 return createSW(result);
148 }
149
150 @Override
151 public XMLStreamWriter createXMLStreamWriter(Writer w)
152 throws XMLStreamException
153 {
154 if (w == null) {
155 throw new IllegalArgumentException("Null Writer is not a valid argument");
156 }
157 return createSW(null, w, null, false);
158 }
159
160 @Override
161 public Object getProperty(String name) {
162 return mConfig.getProperty(name);
163 }
164
165 @Override
166 public boolean isPropertySupported(String name) {
167 return mConfig.isPropertySupported(name);
168 }
169
170 @Override
171 public void setProperty(String name, Object value)
172 {
173 mConfig.setProperty(name, value);
174 }
175
176
181
182
183
184 @Override
185 public XMLEventWriter createXMLEventWriter(Writer w, String enc)
186 throws XMLStreamException
187 {
188 return new Stax2EventWriterImpl(createSW(null, w, enc, false));
189 }
190
191 @Override
192 public XMLEventWriter createXMLEventWriter(XMLStreamWriter sw)
193 throws XMLStreamException
194 {
195 XMLStreamWriter2 sw2 = Stax2WriterAdapter.wrapIfNecessary(sw);
196 return new Stax2EventWriterImpl(sw2);
197 }
198
199 @Override
200 public XMLStreamWriter2 createXMLStreamWriter(Writer w, String enc)
201 throws XMLStreamException
202 {
203 return createSW(null, w, enc, false);
204 }
205
206
207
208 @Override
209 public void configureForXmlConformance() {
210 mConfig.configureForXmlConformance();
211 }
212
213 @Override
214 public void configureForRobustness() {
215 mConfig.configureForRobustness();
216 }
217
218 @Override
219 public void configureForSpeed() {
220 mConfig.configureForSpeed();
221 }
222
223
228
229 public WriterConfig getConfig() {
230 return mConfig;
231 }
232
233
238
239
247 @SuppressWarnings("resource")
248 private XMLStreamWriter2 createSW(OutputStream out, Writer w, String enc,
249 boolean requireAutoClose)
250 throws XMLStreamException
251 {
252
256 WriterConfig cfg = mConfig.createNonShared();
257 XmlWriter xw;
258
259 boolean autoCloseOutput = requireAutoClose || mConfig.willAutoCloseOutput();
260
261 if (w == null) {
262 if (enc == null) {
263 enc = WstxOutputProperties.DEFAULT_OUTPUT_ENCODING;
264 } else {
265
268 if (enc != CharsetNames.CS_UTF8
269 && enc != CharsetNames.CS_ISO_LATIN1
270 && enc != CharsetNames.CS_US_ASCII) {
271 enc = CharsetNames.normalize(enc);
272 }
273 }
274
275 try {
276 if (enc == CharsetNames.CS_UTF8) {
277 w = new UTF8Writer(cfg, out, autoCloseOutput);
278 xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, out, 16);
279 } else if (enc == CharsetNames.CS_ISO_LATIN1) {
280 xw = new ISOLatin1XmlWriter(out, cfg, autoCloseOutput);
281 } else if (enc == CharsetNames.CS_US_ASCII) {
282 xw = new AsciiXmlWriter(out, cfg, autoCloseOutput);
283 } else {
284 w = new OutputStreamWriter(out, enc);
285 xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, out, -1);
286 }
287 } catch (IOException ex) {
288 throw new XMLStreamException(ex);
289 }
290 } else {
291
292 if (enc == null) {
293 enc = CharsetNames.findEncodingFor(w);
294 }
295 try {
296 xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, null, -1);
297 } catch (IOException ex) {
298 throw new XMLStreamException(ex);
299 }
300 }
301
302 return createSW(enc, cfg, xw);
303 }
304
305
309 protected XMLStreamWriter2 createSW(String enc, WriterConfig cfg, XmlWriter xw) {
310 if (cfg.willSupportNamespaces()) {
311 if (cfg.automaticNamespacesEnabled()) {
312 return new RepairingNsStreamWriter(xw, enc, cfg);
313 }
314 return new SimpleNsStreamWriter(xw, enc, cfg);
315 }
316 return new NonNsStreamWriter(xw, enc, cfg);
317 }
318
319 @SuppressWarnings("resource")
320 private XMLStreamWriter2 createSW(Result res)
321 throws XMLStreamException
322 {
323 OutputStream out = null;
324 Writer w = null;
325 String encoding = null;
326 boolean requireAutoClose;
327 String sysId = null;
328
329 if (res instanceof Stax2Result) {
330 Stax2Result sr = (Stax2Result) res;
331 try {
332 out = sr.constructOutputStream();
333 if (out == null) {
334 w = sr.constructWriter();
335 }
336 } catch (IOException ioe) {
337 throw new WstxIOException(ioe);
338 }
339
340 requireAutoClose = true;
341 } else if (res instanceof StreamResult) {
342 StreamResult sr = (StreamResult) res;
343 out = sr.getOutputStream();
344 sysId = sr.getSystemId();
345 if (out == null) {
346 w = sr.getWriter();
347 }
348
352 requireAutoClose = false;
353 } else if (res instanceof SAXResult) {
354 SAXResult sr = (SAXResult) res;
355 sysId = sr.getSystemId();
356 if (sysId == null || sysId.length() == 0) {
357 throw new XMLStreamException("Can not create a stream writer for a SAXResult that does not have System Id (support for using SAX input source not implemented)");
358 }
359 requireAutoClose = true;
360 } else if (res instanceof DOMResult) {
361 return WstxDOMWrappingWriter.createFrom(mConfig.createNonShared(), (DOMResult) res);
362 } else {
363 throw new IllegalArgumentException("Can not instantiate a writer for XML result type "+res.getClass()+" (unrecognized type)");
364 }
365
366 if (out != null) {
367 return createSW(out, null, encoding, requireAutoClose);
368 }
369 if (w != null) {
370 return createSW(null, w, encoding, requireAutoClose);
371 }
372 if (sysId != null && sysId.length() > 0) {
373
377 requireAutoClose = true;
378 try {
379 out = URLUtil.outputStreamFromURL(URLUtil.urlFromSystemId(sysId));
380 } catch (IOException ioe) {
381 throw new WstxIOException(ioe);
382 }
383 return createSW(out, null, encoding, requireAutoClose);
384 }
385 throw new XMLStreamException("Can not create Stax writer for passed-in Result -- neither writer, output stream or system id was accessible");
386 }
387 }
388