1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.server.endpoint.adapter.method;
18
19 import javax.xml.namespace.QName;
20 import javax.xml.transform.Source;
21 import javax.xml.transform.TransformerException;
22 import javax.xml.transform.dom.DOMResult;
23 import javax.xml.xpath.XPath;
24 import javax.xml.xpath.XPathConstants;
25 import javax.xml.xpath.XPathExpressionException;
26 import javax.xml.xpath.XPathFactory;
27
28 import org.springframework.core.MethodParameter;
29 import org.springframework.core.convert.ConversionService;
30 import org.springframework.core.convert.support.ConversionServiceFactory;
31 import org.springframework.ws.context.MessageContext;
32 import org.springframework.ws.server.endpoint.annotation.XPathParam;
33 import org.springframework.ws.server.endpoint.support.NamespaceUtils;
34 import org.springframework.xml.transform.TransformerHelper;
35
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.Node;
39 import org.w3c.dom.NodeList;
40
41
42
43
44
45
46
47
48
49
50
51
52 public class XPathParamMethodArgumentResolver implements MethodArgumentResolver {
53
54 private final XPathFactory xpathFactory = createXPathFactory();
55
56 private TransformerHelper transformerHelper = new TransformerHelper();
57
58 private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
59
60
61
62
63
64
65
66 public void setConversionService(ConversionService conversionService) {
67 this.conversionService = conversionService;
68 }
69
70 public void setTransformerHelper(TransformerHelper transformerHelper) {
71 this.transformerHelper = transformerHelper;
72 }
73
74 public boolean supportsParameter(MethodParameter parameter) {
75 if (parameter.getParameterAnnotation(XPathParam.class) == null) {
76 return false;
77 }
78 Class<?> parameterType = parameter.getParameterType();
79 if (Boolean.class.equals(parameterType) || Boolean.TYPE.equals(parameterType) ||
80 Double.class.equals(parameterType) || Double.TYPE.equals(parameterType) ||
81 Node.class.isAssignableFrom(parameterType) || NodeList.class.isAssignableFrom(parameterType) ||
82 String.class.isAssignableFrom(parameterType)) {
83 return true;
84 }
85 else {
86 return conversionService.canConvert(String.class, parameterType);
87 }
88 }
89
90 public Object resolveArgument(MessageContext messageContext, MethodParameter parameter)
91 throws TransformerException, XPathExpressionException {
92 Class<?> parameterType = parameter.getParameterType();
93 QName evaluationReturnType = getReturnType(parameterType);
94 boolean useConversionService = false;
95 if (evaluationReturnType == null) {
96 evaluationReturnType = XPathConstants.STRING;
97 useConversionService = true;
98 }
99
100 XPath xpath = createXPath();
101 xpath.setNamespaceContext(NamespaceUtils.getNamespaceContext(parameter.getMethod()));
102
103 Element rootElement = getRootElement(messageContext.getRequest().getPayloadSource());
104 String expression = parameter.getParameterAnnotation(XPathParam.class).value();
105 Object result = xpath.evaluate(expression, rootElement, evaluationReturnType);
106 return useConversionService ? conversionService.convert(result, parameterType) : result;
107 }
108
109 private QName getReturnType(Class<?> parameterType) {
110 if (Boolean.class.equals(parameterType) || Boolean.TYPE.equals(parameterType)) {
111 return XPathConstants.BOOLEAN;
112 }
113 else if (Double.class.equals(parameterType) || Double.TYPE.equals(parameterType)) {
114 return XPathConstants.NUMBER;
115 }
116 else if (Node.class.equals(parameterType)) {
117 return XPathConstants.NODE;
118 }
119 else if (NodeList.class.equals(parameterType)) {
120 return XPathConstants.NODESET;
121 }
122 else if (String.class.equals(parameterType)) {
123 return XPathConstants.STRING;
124 }
125 else {
126 return null;
127 }
128 }
129
130 private XPath createXPath() {
131 synchronized (xpathFactory) {
132 return xpathFactory.newXPath();
133 }
134 }
135
136 private Element getRootElement(Source source) throws TransformerException {
137 DOMResult domResult = new DOMResult();
138 transformerHelper.transform(source, domResult);
139 Document document = (Document) domResult.getNode();
140 return document.getDocumentElement();
141 }
142
143
144
145
146
147
148
149
150
151 protected XPathFactory createXPathFactory() {
152 return XPathFactory.newInstance();
153 }
154
155
156 }