001: /*
002: * Copyright 2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.server.endpoint;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import javax.xml.namespace.NamespaceContext;
022: import javax.xml.stream.XMLStreamException;
023: import javax.xml.stream.XMLStreamReader;
024: import javax.xml.stream.XMLStreamWriter;
025: import javax.xml.transform.Result;
026: import javax.xml.transform.Source;
027: import javax.xml.transform.TransformerException;
028: import javax.xml.transform.stream.StreamResult;
029: import javax.xml.transform.stream.StreamSource;
030:
031: import org.springframework.ws.WebServiceMessage;
032: import org.springframework.ws.context.MessageContext;
033: import org.springframework.xml.stream.XmlEventStreamReader;
034: import org.springframework.xml.transform.StaxResult;
035: import org.springframework.xml.transform.StaxSource;
036:
037: /**
038: * Abstract base class for endpoints that handle the message payload with streaming StAX. Allows subclasses to read the
039: * request with a <code>XMLStreamReader</code>, and to create a response using a <code>XMLStreamWriter</code>.
040: *
041: * @author Arjen Poutsma
042: * @see #invokeInternal(javax.xml.stream.XMLStreamReader,javax.xml.stream.XMLStreamWriter)
043: * @see XMLStreamReader
044: * @see XMLStreamWriter
045: * @since 1.0.0
046: */
047: public abstract class AbstractStaxStreamPayloadEndpoint extends
048: AbstractStaxPayloadEndpoint implements MessageEndpoint {
049:
050: public final void invoke(MessageContext messageContext)
051: throws Exception {
052: XMLStreamReader streamReader = getStreamReader(messageContext
053: .getRequest().getPayloadSource());
054: XMLStreamWriter streamWriter = new ResponseCreatingStreamWriter(
055: messageContext);
056: invokeInternal(streamReader, streamWriter);
057: streamWriter.close();
058: }
059:
060: private XMLStreamReader getStreamReader(Source source)
061: throws XMLStreamException, TransformerException {
062: XMLStreamReader streamReader = null;
063: if (source instanceof StaxSource) {
064: streamReader = ((StaxSource) source).getXMLStreamReader();
065: StaxSource staxSource = (StaxSource) source;
066: streamReader = staxSource.getXMLStreamReader();
067: if (streamReader == null
068: && staxSource.getXMLEventReader() != null) {
069: try {
070: streamReader = new XmlEventStreamReader(staxSource
071: .getXMLEventReader());
072: } catch (XMLStreamException ex) {
073: // ignore
074: }
075: }
076:
077: }
078: if (streamReader == null) {
079: try {
080: streamReader = getInputFactory().createXMLStreamReader(
081: source);
082: } catch (XMLStreamException ex) {
083: // ignore
084: }
085: }
086: if (streamReader == null) {
087: // as a final resort, transform the source to a stream, and read from that
088: ByteArrayOutputStream os = new ByteArrayOutputStream();
089: transform(source, new StreamResult(os));
090: ByteArrayInputStream is = new ByteArrayInputStream(os
091: .toByteArray());
092: streamReader = getInputFactory().createXMLStreamReader(is);
093: }
094: return streamReader;
095: }
096:
097: private XMLStreamWriter getStreamWriter(Result result) {
098: XMLStreamWriter streamWriter = null;
099: if (result instanceof StaxResult) {
100: StaxResult staxResult = (StaxResult) result;
101: streamWriter = staxResult.getXMLStreamWriter();
102: }
103: if (streamWriter == null) {
104: try {
105: streamWriter = getOutputFactory()
106: .createXMLStreamWriter(result);
107: } catch (XMLStreamException ex) {
108: // ignore
109: }
110: }
111: return streamWriter;
112: }
113:
114: /**
115: * Template method. Subclasses must implement this. Offers the request payload as a <code>XMLStreamReader</code>,
116: * and a <code>XMLStreamWriter</code> to write the response payload to.
117: *
118: * @param streamReader the reader to read the payload from
119: * @param streamWriter the writer to write the payload to
120: */
121: protected abstract void invokeInternal(
122: XMLStreamReader streamReader, XMLStreamWriter streamWriter)
123: throws Exception;
124:
125: /**
126: * Implementation of the <code>XMLStreamWriter</code> interface that creates a response
127: * <code>WebServiceMessage</code> as soon as any method is called, thus lazily creating the response.
128: */
129: private class ResponseCreatingStreamWriter implements
130: XMLStreamWriter {
131:
132: private MessageContext messageContext;
133:
134: private XMLStreamWriter streamWriter;
135:
136: private ByteArrayOutputStream os;
137:
138: private ResponseCreatingStreamWriter(
139: MessageContext messageContext) {
140: this .messageContext = messageContext;
141: }
142:
143: public NamespaceContext getNamespaceContext() {
144: return streamWriter.getNamespaceContext();
145: }
146:
147: public void setNamespaceContext(NamespaceContext context)
148: throws XMLStreamException {
149: createStreamWriter();
150: streamWriter.setNamespaceContext(context);
151: }
152:
153: public void close() throws XMLStreamException {
154: if (streamWriter != null) {
155: streamWriter.close();
156: if (os != null) {
157: streamWriter.flush();
158: // if we used an output stream cache, we have to transform it to the response again
159: try {
160: ByteArrayInputStream is = new ByteArrayInputStream(
161: os.toByteArray());
162: transform(new StreamSource(is), messageContext
163: .getResponse().getPayloadResult());
164: os = null;
165: } catch (TransformerException ex) {
166: throw new XMLStreamException(ex);
167: }
168: }
169: streamWriter = null;
170: }
171:
172: }
173:
174: public void flush() throws XMLStreamException {
175: if (streamWriter != null) {
176: streamWriter.flush();
177: }
178: }
179:
180: public String getPrefix(String uri) throws XMLStreamException {
181: createStreamWriter();
182: return streamWriter.getPrefix(uri);
183: }
184:
185: public Object getProperty(String name)
186: throws IllegalArgumentException {
187: return streamWriter.getProperty(name);
188: }
189:
190: public void setDefaultNamespace(String uri)
191: throws XMLStreamException {
192: createStreamWriter();
193: streamWriter.setDefaultNamespace(uri);
194: }
195:
196: public void setPrefix(String prefix, String uri)
197: throws XMLStreamException {
198: createStreamWriter();
199: streamWriter.setPrefix(prefix, uri);
200: }
201:
202: public void writeAttribute(String localName, String value)
203: throws XMLStreamException {
204: createStreamWriter();
205: streamWriter.writeAttribute(localName, value);
206: }
207:
208: public void writeAttribute(String namespaceURI,
209: String localName, String value)
210: throws XMLStreamException {
211: createStreamWriter();
212: streamWriter.writeAttribute(namespaceURI, localName, value);
213: }
214:
215: public void writeAttribute(String prefix, String namespaceURI,
216: String localName, String value)
217: throws XMLStreamException {
218: createStreamWriter();
219: streamWriter.writeAttribute(prefix, namespaceURI,
220: localName, value);
221: }
222:
223: public void writeCData(String data) throws XMLStreamException {
224: createStreamWriter();
225: streamWriter.writeCData(data);
226: }
227:
228: public void writeCharacters(String text)
229: throws XMLStreamException {
230: createStreamWriter();
231: streamWriter.writeCharacters(text);
232: }
233:
234: public void writeCharacters(char[] text, int start, int len)
235: throws XMLStreamException {
236: createStreamWriter();
237: streamWriter.writeCharacters(text, start, len);
238: }
239:
240: public void writeComment(String data) throws XMLStreamException {
241: createStreamWriter();
242: streamWriter.writeComment(data);
243: }
244:
245: public void writeDTD(String dtd) throws XMLStreamException {
246: createStreamWriter();
247: streamWriter.writeDTD(dtd);
248: }
249:
250: public void writeDefaultNamespace(String namespaceURI)
251: throws XMLStreamException {
252: createStreamWriter();
253: streamWriter.writeDefaultNamespace(namespaceURI);
254: }
255:
256: public void writeEmptyElement(String localName)
257: throws XMLStreamException {
258: createStreamWriter();
259: streamWriter.writeEmptyElement(localName);
260: }
261:
262: public void writeEmptyElement(String namespaceURI,
263: String localName) throws XMLStreamException {
264: createStreamWriter();
265: streamWriter.writeEmptyElement(namespaceURI, localName);
266: }
267:
268: public void writeEmptyElement(String prefix, String localName,
269: String namespaceURI) throws XMLStreamException {
270: createStreamWriter();
271: streamWriter.writeEmptyElement(prefix, localName,
272: namespaceURI);
273: }
274:
275: public void writeEndDocument() throws XMLStreamException {
276: createStreamWriter();
277: streamWriter.writeEndDocument();
278: }
279:
280: public void writeEndElement() throws XMLStreamException {
281: createStreamWriter();
282: streamWriter.writeEndElement();
283: }
284:
285: public void writeEntityRef(String name)
286: throws XMLStreamException {
287: createStreamWriter();
288: streamWriter.writeEntityRef(name);
289: }
290:
291: public void writeNamespace(String prefix, String namespaceURI)
292: throws XMLStreamException {
293: createStreamWriter();
294: streamWriter.writeNamespace(prefix, namespaceURI);
295: }
296:
297: public void writeProcessingInstruction(String target)
298: throws XMLStreamException {
299: createStreamWriter();
300: streamWriter.writeProcessingInstruction(target);
301: }
302:
303: public void writeProcessingInstruction(String target,
304: String data) throws XMLStreamException {
305: createStreamWriter();
306: streamWriter.writeProcessingInstruction(target, data);
307: }
308:
309: public void writeStartDocument() throws XMLStreamException {
310: createStreamWriter();
311: streamWriter.writeStartDocument();
312: }
313:
314: public void writeStartDocument(String version)
315: throws XMLStreamException {
316: createStreamWriter();
317: streamWriter.writeStartDocument(version);
318: }
319:
320: public void writeStartDocument(String encoding, String version)
321: throws XMLStreamException {
322: createStreamWriter();
323: streamWriter.writeStartDocument(encoding, version);
324: }
325:
326: public void writeStartElement(String localName)
327: throws XMLStreamException {
328: createStreamWriter();
329: streamWriter.writeStartElement(localName);
330: }
331:
332: public void writeStartElement(String namespaceURI,
333: String localName) throws XMLStreamException {
334: createStreamWriter();
335: streamWriter.writeStartElement(namespaceURI, localName);
336: }
337:
338: public void writeStartElement(String prefix, String localName,
339: String namespaceURI) throws XMLStreamException {
340: createStreamWriter();
341: streamWriter.writeStartElement(prefix, localName,
342: namespaceURI);
343: }
344:
345: private void createStreamWriter() throws XMLStreamException {
346: if (streamWriter == null) {
347: WebServiceMessage response = messageContext
348: .getResponse();
349: streamWriter = getStreamWriter(response
350: .getPayloadResult());
351: if (streamWriter == null) {
352: // as a final resort, use a stream, and transform that at endDocument()
353: os = new ByteArrayOutputStream();
354: streamWriter = getOutputFactory()
355: .createXMLStreamWriter(os);
356: }
357: }
358: }
359: }
360: }
|