1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.server.endpoint.adapter;
18
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Method;
21 import java.util.Map;
22 import javax.xml.namespace.QName;
23 import javax.xml.transform.Source;
24 import javax.xml.transform.TransformerException;
25 import javax.xml.transform.dom.DOMResult;
26 import javax.xml.xpath.XPath;
27 import javax.xml.xpath.XPathConstants;
28 import javax.xml.xpath.XPathExpressionException;
29 import javax.xml.xpath.XPathFactory;
30
31 import org.springframework.beans.factory.InitializingBean;
32 import org.springframework.ws.WebServiceMessage;
33 import org.springframework.ws.context.MessageContext;
34 import org.springframework.ws.server.endpoint.MethodEndpoint;
35 import org.springframework.ws.server.endpoint.annotation.XPathParam;
36 import org.springframework.xml.namespace.SimpleNamespaceContext;
37
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Element;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.NodeList;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 @Deprecated
65 public class XPathParamAnnotationMethodEndpointAdapter extends AbstractMethodEndpointAdapter
66 implements InitializingBean {
67
68 private XPathFactory xpathFactory;
69
70 private Map<String, String> namespaces;
71
72
73 public void setNamespaces(Map<String, String> namespaces) {
74 this.namespaces = namespaces;
75 }
76
77 public void afterPropertiesSet() throws Exception {
78 xpathFactory = XPathFactory.newInstance();
79 }
80
81
82 @Override
83 protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
84 Method method = methodEndpoint.getMethod();
85 if (!(Source.class.isAssignableFrom(method.getReturnType()) || Void.TYPE.equals(method.getReturnType()))) {
86 return false;
87 }
88 Class<?>[] parameterTypes = method.getParameterTypes();
89 for (int i = 0; i < parameterTypes.length; i++) {
90 if (getXPathParamAnnotation(method, i) == null || !isSupportedType(parameterTypes[i])) {
91 return false;
92 }
93 }
94 return true;
95 }
96
97 private XPathParam getXPathParamAnnotation(Method method, int paramIdx) {
98 Annotation[][] paramAnnotations = method.getParameterAnnotations();
99 for (int annIdx = 0; annIdx < paramAnnotations[paramIdx].length; annIdx++) {
100 if (paramAnnotations[paramIdx][annIdx].annotationType().equals(XPathParam.class)) {
101 return (XPathParam) paramAnnotations[paramIdx][annIdx];
102 }
103 }
104 return null;
105 }
106
107 private boolean isSupportedType(Class<?> clazz) {
108 return Boolean.class.isAssignableFrom(clazz) || Boolean.TYPE.isAssignableFrom(clazz) ||
109 Double.class.isAssignableFrom(clazz) || Double.TYPE.isAssignableFrom(clazz) ||
110 Node.class.isAssignableFrom(clazz) || NodeList.class.isAssignableFrom(clazz) ||
111 String.class.isAssignableFrom(clazz);
112 }
113
114 @Override
115 protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception {
116 Element payloadElement = getRootElement(messageContext.getRequest().getPayloadSource());
117 Object[] args = getMethodArguments(payloadElement, methodEndpoint.getMethod());
118 Object result = methodEndpoint.invoke(args);
119 if (result != null && result instanceof Source) {
120 Source responseSource = (Source) result;
121 WebServiceMessage response = messageContext.getResponse();
122 transform(responseSource, response.getPayloadResult());
123 }
124 }
125
126 private Object[] getMethodArguments(Element payloadElement, Method method) throws XPathExpressionException {
127 Class<?>[] parameterTypes = method.getParameterTypes();
128 XPath xpath = createXPath();
129 Object[] args = new Object[parameterTypes.length];
130 for (int i = 0; i < parameterTypes.length; i++) {
131 String expression = getXPathParamAnnotation(method, i).value();
132 QName conversionType;
133 if (Boolean.class.isAssignableFrom(parameterTypes[i]) || Boolean.TYPE.isAssignableFrom(parameterTypes[i])) {
134 conversionType = XPathConstants.BOOLEAN;
135 }
136 else
137 if (Double.class.isAssignableFrom(parameterTypes[i]) || Double.TYPE.isAssignableFrom(parameterTypes[i])) {
138 conversionType = XPathConstants.NUMBER;
139 }
140 else if (Node.class.isAssignableFrom(parameterTypes[i])) {
141 conversionType = XPathConstants.NODE;
142 }
143 else if (NodeList.class.isAssignableFrom(parameterTypes[i])) {
144 conversionType = XPathConstants.NODESET;
145 }
146 else if (String.class.isAssignableFrom(parameterTypes[i])) {
147 conversionType = XPathConstants.STRING;
148 }
149 else {
150 throw new IllegalArgumentException("Invalid parameter type [" + parameterTypes[i] + "]. " +
151 "Supported are: Boolean, Double, Node, NodeList, and String.");
152 }
153 args[i] = xpath.evaluate(expression, payloadElement, conversionType);
154 }
155 return args;
156 }
157
158 private synchronized XPath createXPath() {
159 XPath xpath = xpathFactory.newXPath();
160 if (namespaces != null) {
161 SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
162 namespaceContext.setBindings(namespaces);
163 xpath.setNamespaceContext(namespaceContext);
164 }
165 return xpath;
166 }
167
168
169
170
171
172
173
174 private Element getRootElement(Source source) throws TransformerException {
175 DOMResult domResult = new DOMResult();
176 transform(source, domResult);
177 Document document = (Document) domResult.getNode();
178 return document.getDocumentElement();
179 }
180
181
182 }