1 /*
2  * Copyright 2005-2014 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.soap.server.endpoint.adapter.method;
18
19 import java.lang.reflect.ParameterizedType;
20 import java.lang.reflect.Type;
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24 import javax.xml.namespace.QName;
25
26 import org.springframework.core.MethodParameter;
27 import org.springframework.util.Assert;
28 import org.springframework.ws.context.MessageContext;
29 import org.springframework.ws.server.endpoint.adapter.method.MethodArgumentResolver;
30 import org.springframework.ws.soap.SoapHeaderElement;
31 import org.springframework.ws.soap.SoapMessage;
32 import org.springframework.ws.soap.server.endpoint.annotation.SoapHeader;
33 import org.springframework.xml.namespace.QNameUtils;
34
35 /**
36  * Implementation of {@link MethodArgumentResolver} that supports resolving {@link SoapHeaderElement} parameters. Target
37  * method parameters must be annotated with {@link SoapHeader} to indicate the SOAP header to resolve. This resolver
38  * supports simple {@link SoapHeaderElement} parameters and {@link List} parameters for elements that appear multiple
39  * times in the same SOAP header. </p> The following snippet shows an example of supported declarations.
40  * <pre><code>
41  * public void soapHeaderElement(@SoapHeader("{http://springframework.org/ws}header") SoapHeaderElement element)
42  *
43  * public void soapHeaderElementList(@SoapHeader("{http://springframework.org/ws}header") List&lt;SoapHeaderElement&gt; elements)
44  * </code></pre>
45  *
46  * @author Tareq Abedrabbo
47  * @author Arjen Poutsma
48  * @see SoapHeader
49  * @since 2.0
50  */

51 public class SoapHeaderElementMethodArgumentResolver implements MethodArgumentResolver {
52
53     @Override
54     public boolean supportsParameter(MethodParameter parameter) {
55         SoapHeader soapHeader = parameter.getParameterAnnotation(SoapHeader.class);
56         if (soapHeader == null) {
57             return false;
58         }
59
60         Class<?> parameterType = parameter.getParameterType();
61
62         // Simple SoapHeaderElement parameter
63         if (SoapHeaderElement.class.equals(parameterType)) {
64             return true;
65         }
66
67         // List<SoapHeaderElement> parameter
68         if (List.class.equals(parameterType)) {
69             Type genericType = parameter.getGenericParameterType();
70             if (genericType instanceof ParameterizedType) {
71                 ParameterizedType parameterizedType = (ParameterizedType) genericType;
72                 Type[] typeArguments = parameterizedType.getActualTypeArguments();
73                 if (typeArguments.length == 1 && SoapHeaderElement.class.equals(typeArguments[0])) {
74                     return true;
75                 }
76             }
77         }
78         return false;
79     }
80
81     @Override
82     public Object resolveArgument(MessageContext messageContext, MethodParameter parameter) throws Exception {
83         Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest());
84         SoapMessage request = (SoapMessage) messageContext.getRequest();
85         org.springframework.ws.soap.SoapHeader soapHeader = request.getSoapHeader();
86
87         String paramValue = parameter.getParameterAnnotation(SoapHeader.class).value();
88
89         Assert.isTrue(QNameUtils.validateQName(paramValue), "Invalid header qualified name [" + paramValue + "]. " +
90                 "QName must be of the form '{namespace}localPart'.");
91
92         QName qname = QName.valueOf(paramValue);
93
94         Class<?> parameterType = parameter.getParameterType();
95
96         if (SoapHeaderElement.class.equals(parameterType)) {
97             return extractSoapHeader(qname, soapHeader);
98         }
99         else if (List.class.equals(parameterType)) {
100             return extractSoapHeaderList(qname, soapHeader);
101         }
102         // should not happen
103         throw new UnsupportedOperationException();
104     }
105
106     private SoapHeaderElement extractSoapHeader(QName qname, org.springframework.ws.soap.SoapHeader soapHeader) {
107         Iterator<SoapHeaderElement> elements = soapHeader.examineAllHeaderElements();
108         while (elements.hasNext()) {
109             SoapHeaderElement e = elements.next();
110             if (e.getName().equals(qname)) {
111                 return e;
112             }
113         }
114         return null;
115     }
116
117     private List<SoapHeaderElement> extractSoapHeaderList(QName qname,
118                                                           org.springframework.ws.soap.SoapHeader soapHeader) {
119         List<SoapHeaderElement> result = new ArrayList<SoapHeaderElement>();
120         Iterator<SoapHeaderElement> elements = soapHeader.examineAllHeaderElements();
121         while (elements.hasNext()) {
122             SoapHeaderElement e = elements.next();
123             if (e.getName().equals(qname)) {
124                 result.add(e);
125             }
126         }
127         return result;
128     }
129 }
130