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.adapter.method;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import javax.xml.stream.XMLEventReader;
22  import javax.xml.stream.XMLInputFactory;
23  import javax.xml.stream.XMLStreamException;
24  import javax.xml.stream.XMLStreamReader;
25  import javax.xml.transform.Source;
26  import javax.xml.transform.TransformerException;
27  import javax.xml.transform.stream.StreamResult;
28  
29  import org.springframework.core.MethodParameter;
30  import org.springframework.util.xml.StaxUtils;
31  import org.springframework.ws.context.MessageContext;
32  import org.springframework.ws.server.endpoint.annotation.RequestPayload;
33  import org.springframework.xml.transform.TransformerObjectSupport;
34  
35  /**
36   * Implementation of {@link MethodArgumentResolver} that supports StAX {@link XMLStreamReader} and {@link
37   * XMLEventReader} arguments.
38   *
39   * @author Arjen Poutsma
40   * @since 2.0
41   */
42  public class StaxPayloadMethodArgumentResolver extends TransformerObjectSupport implements MethodArgumentResolver {
43  
44      private final XMLInputFactory inputFactory = createXmlInputFactory();
45  
46      public boolean supportsParameter(MethodParameter parameter) {
47          if (parameter.getParameterAnnotation(RequestPayload.class) == null) {
48              return false;
49          }
50          else {
51              Class<?> parameterType = parameter.getParameterType();
52              return XMLStreamReader.class.equals(parameterType) || XMLEventReader.class.equals(parameterType);
53          }
54      }
55  
56      public Object resolveArgument(MessageContext messageContext, MethodParameter parameter)
57              throws TransformerException, XMLStreamException {
58          Source source = messageContext.getRequest().getPayloadSource();
59          if (source == null) {
60              return null;
61          }
62          Class<?> parameterType = parameter.getParameterType();
63          if (XMLStreamReader.class.equals(parameterType)) {
64              return resolveStreamReader(source);
65          }
66          else if (XMLEventReader.class.equals(parameterType)) {
67              return resolveEventReader(source);
68          }
69          throw new UnsupportedOperationException();
70      }
71  
72      private XMLStreamReader resolveStreamReader(Source requestSource) throws TransformerException, XMLStreamException {
73          XMLStreamReader streamReader = null;
74          if (StaxUtils.isStaxSource(requestSource)) {
75              streamReader = StaxUtils.getXMLStreamReader(requestSource);
76              if (streamReader == null) {
77                  XMLEventReader eventReader = StaxUtils.getXMLEventReader(requestSource);
78                  if (eventReader != null) {
79                      try {
80                          streamReader = StaxUtils.createEventStreamReader(eventReader);
81                      }
82                      catch (XMLStreamException ex) {
83                          streamReader = null;
84                      }
85                  }
86              }
87          }
88          if (streamReader == null) {
89              try {
90                  streamReader = inputFactory.createXMLStreamReader(requestSource);
91              }
92              catch (XMLStreamException ex) {
93                  streamReader = null;
94              }
95              catch (UnsupportedOperationException ex) {
96                  streamReader = null;
97              }
98          }
99          if (streamReader == null) {
100             // as a final resort, transform the source to a stream, and read from that
101             ByteArrayInputStream bis = convertToByteArrayInputStream(requestSource);
102             streamReader = inputFactory.createXMLStreamReader(bis);
103         }
104         return streamReader;
105     }
106 
107     private XMLEventReader resolveEventReader(Source requestSource) throws TransformerException, XMLStreamException {
108         XMLEventReader eventReader = null;
109         if (StaxUtils.isStaxSource(requestSource)) {
110             eventReader = StaxUtils.getXMLEventReader(requestSource);
111             if (eventReader == null) {
112                 XMLStreamReader streamReader = StaxUtils.getXMLStreamReader(requestSource);
113                 if (streamReader != null) {
114                     try {
115                         eventReader = inputFactory.createXMLEventReader(streamReader);
116                     }
117                     catch (XMLStreamException ex) {
118                         eventReader = null;
119                     }
120                 }
121 
122             }
123         }
124         if (eventReader == null) {
125             try {
126                 eventReader = inputFactory.createXMLEventReader(requestSource);
127             }
128             catch (XMLStreamException ex) {
129                 eventReader = null;
130             }
131             catch (UnsupportedOperationException ex) {
132                 eventReader = null;
133             }
134         }
135         if (eventReader == null) {
136             // as a final resort, transform the source to a stream, and read from that
137             ByteArrayInputStream bis = convertToByteArrayInputStream(requestSource);
138             eventReader = inputFactory.createXMLEventReader(bis);
139         }
140         return eventReader;
141     }
142 
143     /**
144      * Create a {@code XMLInputFactory} that this resolver will use to create {@link XMLStreamReader} and {@link
145      * XMLEventReader} objects.
146      * <p/>
147      * Can be overridden in subclasses, adding further initialization of the factory. The resulting factory is cached,
148      * so this method will only be called once.
149      *
150      * @return the created factory
151      */
152     protected XMLInputFactory createXmlInputFactory() {
153         return XMLInputFactory.newInstance();
154     }
155 
156     private ByteArrayInputStream convertToByteArrayInputStream(Source source) throws TransformerException {
157         ByteArrayOutputStream bos = new ByteArrayOutputStream();
158         transform(source, new StreamResult(bos));
159         return new ByteArrayInputStream(bos.toByteArray());
160     }
161 
162 
163 
164 }