View Javadoc
1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.server.endpoint;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import javax.xml.namespace.NamespaceContext;
22  import javax.xml.stream.XMLEventReader;
23  import javax.xml.stream.XMLStreamException;
24  import javax.xml.stream.XMLStreamReader;
25  import javax.xml.stream.XMLStreamWriter;
26  import javax.xml.transform.Result;
27  import javax.xml.transform.Source;
28  import javax.xml.transform.TransformerException;
29  import javax.xml.transform.stream.StreamResult;
30  import javax.xml.transform.stream.StreamSource;
31  
32  import org.springframework.util.xml.StaxUtils;
33  import org.springframework.ws.WebServiceMessage;
34  import org.springframework.ws.context.MessageContext;
35  
36  /**
37   * Abstract base class for endpoints that handle the message payload with streaming StAX. Allows subclasses to read the
38   * request with a <code>XMLStreamReader</code>, and to create a response using a <code>XMLStreamWriter</code>.
39   *
40   * @author Arjen Poutsma
41   * @see #invokeInternal(javax.xml.stream.XMLStreamReader,javax.xml.stream.XMLStreamWriter)
42   * @see XMLStreamReader
43   * @see XMLStreamWriter
44   * @since 1.0.0
45   * @deprecated as of Spring Web Services 2.0, in favor of annotated endpoints
46   */
47  @Deprecated
48  @SuppressWarnings("Since15")
49  public abstract class AbstractStaxStreamPayloadEndpoint extends AbstractStaxPayloadEndpoint implements MessageEndpoint {
50  
51      public final void invoke(MessageContext messageContext) throws Exception {
52          XMLStreamReader streamReader = getStreamReader(messageContext.getRequest().getPayloadSource());
53          XMLStreamWriter streamWriter = new ResponseCreatingStreamWriter(messageContext);
54          invokeInternal(streamReader, streamWriter);
55          streamWriter.close();
56      }
57  
58      private XMLStreamReader getStreamReader(Source source) throws XMLStreamException, TransformerException {
59          if (source == null) {
60              return null;
61          }
62          XMLStreamReader streamReader = null;
63          if (StaxUtils.isStaxSource(source)) {
64              streamReader = StaxUtils.getXMLStreamReader(source);
65              if (streamReader == null) {
66                  XMLEventReader eventReader = StaxUtils.getXMLEventReader(source);
67                  if (eventReader != null) {
68                      try {
69                          streamReader = StaxUtils.createEventStreamReader(eventReader);
70                      }
71                      catch (XMLStreamException ex) {
72                          streamReader = null;
73                      }
74                  }
75              }
76  
77          }
78          if (streamReader == null) {
79              try {
80                  streamReader = getInputFactory().createXMLStreamReader(source);
81              }
82              catch (XMLStreamException ex) {
83                  streamReader = null;
84              }
85              catch (UnsupportedOperationException ex) {
86                  streamReader = null;
87              }
88          }
89          if (streamReader == null) {
90              // as a final resort, transform the source to a stream, and read from that
91              ByteArrayOutputStream os = new ByteArrayOutputStream();
92              transform(source, new StreamResult(os));
93              ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
94              streamReader = getInputFactory().createXMLStreamReader(is);
95          }
96          return streamReader;
97      }
98  
99      private XMLStreamWriter getStreamWriter(Result result) {
100         XMLStreamWriter streamWriter = null;
101         if (StaxUtils.isStaxResult(result)) {
102             streamWriter = StaxUtils.getXMLStreamWriter(result);
103         }
104         if (streamWriter == null) {
105             try {
106                 streamWriter = getOutputFactory().createXMLStreamWriter(result);
107             }
108             catch (XMLStreamException ex) {
109                 // ignore
110             }
111         }
112         return streamWriter;
113     }
114 
115     /**
116      * Template method. Subclasses must implement this. Offers the request payload as a <code>XMLStreamReader</code>,
117      * and a <code>XMLStreamWriter</code> to write the response payload to.
118      *
119      * @param streamReader the reader to read the payload from
120      * @param streamWriter the writer to write the payload to
121      */
122     protected abstract void invokeInternal(XMLStreamReader streamReader, XMLStreamWriter streamWriter) throws Exception;
123 
124     /**
125      * Implementation of the <code>XMLStreamWriter</code> interface that creates a response
126      * <code>WebServiceMessage</code> as soon as any method is called, thus lazily creating the response.
127      */
128     private class ResponseCreatingStreamWriter implements XMLStreamWriter {
129 
130         private MessageContext messageContext;
131 
132         private XMLStreamWriter streamWriter;
133 
134         private ByteArrayOutputStream os;
135 
136         private ResponseCreatingStreamWriter(MessageContext messageContext) {
137             this.messageContext = messageContext;
138         }
139 
140         public NamespaceContext getNamespaceContext() {
141             return streamWriter.getNamespaceContext();
142         }
143 
144         public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
145             createStreamWriter();
146             streamWriter.setNamespaceContext(context);
147         }
148 
149         public void close() throws XMLStreamException {
150             if (streamWriter != null) {
151                 streamWriter.close();
152                 if (os != null) {
153                     streamWriter.flush();
154                     // if we used an output stream cache, we have to transform it to the response again
155                     try {
156                         ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
157                         transform(new StreamSource(is), messageContext.getResponse().getPayloadResult());
158                         os = null;
159                     }
160                     catch (TransformerException ex) {
161                         throw new XMLStreamException(ex);
162                     }
163                 }
164                 streamWriter = null;
165             }
166 
167         }
168 
169         public void flush() throws XMLStreamException {
170             if (streamWriter != null) {
171                 streamWriter.flush();
172             }
173         }
174 
175         public String getPrefix(String uri) throws XMLStreamException {
176             createStreamWriter();
177             return streamWriter.getPrefix(uri);
178         }
179 
180         public Object getProperty(String name) throws IllegalArgumentException {
181             return streamWriter.getProperty(name);
182         }
183 
184         public void setDefaultNamespace(String uri) throws XMLStreamException {
185             createStreamWriter();
186             streamWriter.setDefaultNamespace(uri);
187         }
188 
189         public void setPrefix(String prefix, String uri) throws XMLStreamException {
190             createStreamWriter();
191             streamWriter.setPrefix(prefix, uri);
192         }
193 
194         public void writeAttribute(String localName, String value) throws XMLStreamException {
195             createStreamWriter();
196             streamWriter.writeAttribute(localName, value);
197         }
198 
199         public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
200             createStreamWriter();
201             streamWriter.writeAttribute(namespaceURI, localName, value);
202         }
203 
204         public void writeAttribute(String prefix, String namespaceURI, String localName, String value)
205                 throws XMLStreamException {
206             createStreamWriter();
207             streamWriter.writeAttribute(prefix, namespaceURI, localName, value);
208         }
209 
210         public void writeCData(String data) throws XMLStreamException {
211             createStreamWriter();
212             streamWriter.writeCData(data);
213         }
214 
215         public void writeCharacters(String text) throws XMLStreamException {
216             createStreamWriter();
217             streamWriter.writeCharacters(text);
218         }
219 
220         public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
221             createStreamWriter();
222             streamWriter.writeCharacters(text, start, len);
223         }
224 
225         public void writeComment(String data) throws XMLStreamException {
226             createStreamWriter();
227             streamWriter.writeComment(data);
228         }
229 
230         public void writeDTD(String dtd) throws XMLStreamException {
231             createStreamWriter();
232             streamWriter.writeDTD(dtd);
233         }
234 
235         public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
236             createStreamWriter();
237             streamWriter.writeDefaultNamespace(namespaceURI);
238         }
239 
240         public void writeEmptyElement(String localName) throws XMLStreamException {
241             createStreamWriter();
242             streamWriter.writeEmptyElement(localName);
243         }
244 
245         public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
246             createStreamWriter();
247             streamWriter.writeEmptyElement(namespaceURI, localName);
248         }
249 
250         public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
251             createStreamWriter();
252             streamWriter.writeEmptyElement(prefix, localName, namespaceURI);
253         }
254 
255         public void writeEndDocument() throws XMLStreamException {
256             createStreamWriter();
257             streamWriter.writeEndDocument();
258         }
259 
260         public void writeEndElement() throws XMLStreamException {
261             createStreamWriter();
262             streamWriter.writeEndElement();
263         }
264 
265         public void writeEntityRef(String name) throws XMLStreamException {
266             createStreamWriter();
267             streamWriter.writeEntityRef(name);
268         }
269 
270         public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
271             createStreamWriter();
272             streamWriter.writeNamespace(prefix, namespaceURI);
273         }
274 
275         public void writeProcessingInstruction(String target) throws XMLStreamException {
276             createStreamWriter();
277             streamWriter.writeProcessingInstruction(target);
278         }
279 
280         public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
281             createStreamWriter();
282             streamWriter.writeProcessingInstruction(target, data);
283         }
284 
285         public void writeStartDocument() throws XMLStreamException {
286             createStreamWriter();
287             streamWriter.writeStartDocument();
288         }
289 
290         public void writeStartDocument(String version) throws XMLStreamException {
291             createStreamWriter();
292             streamWriter.writeStartDocument(version);
293         }
294 
295         public void writeStartDocument(String encoding, String version) throws XMLStreamException {
296             createStreamWriter();
297             streamWriter.writeStartDocument(encoding, version);
298         }
299 
300         public void writeStartElement(String localName) throws XMLStreamException {
301             createStreamWriter();
302             streamWriter.writeStartElement(localName);
303         }
304 
305         public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
306             createStreamWriter();
307             streamWriter.writeStartElement(namespaceURI, localName);
308         }
309 
310         public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
311             createStreamWriter();
312             streamWriter.writeStartElement(prefix, localName, namespaceURI);
313         }
314 
315         private void createStreamWriter() throws XMLStreamException {
316             if (streamWriter == null) {
317                 WebServiceMessage response = messageContext.getResponse();
318                 streamWriter = getStreamWriter(response.getPayloadResult());
319                 if (streamWriter == null) {
320                     // as a final resort, use a stream, and transform that at endDocument()
321                     os = new ByteArrayOutputStream();
322                     streamWriter = getOutputFactory().createXMLStreamWriter(os);
323                 }
324             }
325         }
326     }
327 }