1
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.w3c.dom.Document;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32
33 import org.springframework.core.MethodParameter;
34 import org.springframework.core.convert.ConversionService;
35 import org.springframework.core.convert.support.ConversionServiceFactory;
36 import org.springframework.core.convert.support.DefaultConversionService;
37 import org.springframework.ws.context.MessageContext;
38 import org.springframework.ws.server.endpoint.annotation.XPathParam;
39 import org.springframework.ws.server.endpoint.support.NamespaceUtils;
40 import org.springframework.xml.transform.TransformerHelper;
41
42
53 public class XPathParamMethodArgumentResolver implements MethodArgumentResolver {
54
55 private final XPathFactory xpathFactory = createXPathFactory();
56
57 private TransformerHelper transformerHelper = new TransformerHelper();
58
59 private ConversionService conversionService = new DefaultConversionService();
60
61
67 public void setConversionService(ConversionService conversionService) {
68 this.conversionService = conversionService;
69 }
70
71 public void setTransformerHelper(TransformerHelper transformerHelper) {
72 this.transformerHelper = transformerHelper;
73 }
74
75 @Override
76 public boolean supportsParameter(MethodParameter parameter) {
77 if (parameter.getParameterAnnotation(XPathParam.class) == null) {
78 return false;
79 }
80 Class<?> parameterType = parameter.getParameterType();
81 if (Boolean.class.equals(parameterType) || Boolean.TYPE.equals(parameterType) ||
82 Double.class.equals(parameterType) || Double.TYPE.equals(parameterType) ||
83 Node.class.isAssignableFrom(parameterType) || NodeList.class.isAssignableFrom(parameterType) ||
84 String.class.isAssignableFrom(parameterType)) {
85 return true;
86 }
87 else {
88 return conversionService.canConvert(String.class, parameterType);
89 }
90 }
91
92 @Override
93 public Object resolveArgument(MessageContext messageContext, MethodParameter parameter)
94 throws TransformerException, XPathExpressionException {
95 Class<?> parameterType = parameter.getParameterType();
96 QName evaluationReturnType = getReturnType(parameterType);
97 boolean useConversionService = false;
98 if (evaluationReturnType == null) {
99 evaluationReturnType = XPathConstants.STRING;
100 useConversionService = true;
101 }
102
103 XPath xpath = createXPath();
104 xpath.setNamespaceContext(NamespaceUtils.getNamespaceContext(parameter.getMethod()));
105
106 Element rootElement = getRootElement(messageContext.getRequest().getPayloadSource());
107 String expression = parameter.getParameterAnnotation(XPathParam.class).value();
108 Object result = xpath.evaluate(expression, rootElement, evaluationReturnType);
109 return useConversionService ? conversionService.convert(result, parameterType) : result;
110 }
111
112 private QName getReturnType(Class<?> parameterType) {
113 if (Boolean.class.equals(parameterType) || Boolean.TYPE.equals(parameterType)) {
114 return XPathConstants.BOOLEAN;
115 }
116 else if (Double.class.equals(parameterType) || Double.TYPE.equals(parameterType)) {
117 return XPathConstants.NUMBER;
118 }
119 else if (Node.class.equals(parameterType)) {
120 return XPathConstants.NODE;
121 }
122 else if (NodeList.class.equals(parameterType)) {
123 return XPathConstants.NODESET;
124 }
125 else if (String.class.equals(parameterType)) {
126 return XPathConstants.STRING;
127 }
128 else {
129 return null;
130 }
131 }
132
133 private XPath createXPath() {
134 synchronized (xpathFactory) {
135 return xpathFactory.newXPath();
136 }
137 }
138
139 private Element getRootElement(Source source) throws TransformerException {
140 DOMResult domResult = new DOMResult();
141 transformerHelper.transform(source, domResult);
142 Document document = (Document) domResult.getNode();
143 return document.getDocumentElement();
144 }
145
146
154 protected XPathFactory createXPathFactory() {
155 return XPathFactory.newInstance();
156 }
157
158
159 }
160