1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.server.endpoint.mapping;
18
19 import java.lang.reflect.Method;
20 import java.lang.reflect.Proxy;
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.springframework.aop.support.AopUtils;
28 import org.springframework.beans.BeansException;
29 import org.springframework.context.ApplicationContextException;
30 import org.springframework.core.BridgeMethodResolver;
31 import org.springframework.util.Assert;
32 import org.springframework.util.ClassUtils;
33 import org.springframework.util.ReflectionUtils;
34 import org.springframework.ws.context.MessageContext;
35 import org.springframework.ws.server.endpoint.MethodEndpoint;
36
37
38
39
40
41
42
43
44
45
46
47 public abstract class AbstractMethodEndpointMapping<T> extends AbstractEndpointMapping {
48
49 private final Map<T, MethodEndpoint> endpointMap = new HashMap<T, MethodEndpoint>();
50
51
52
53
54
55
56
57
58 @Override
59 protected Object getEndpointInternal(MessageContext messageContext) throws Exception {
60 T key = getLookupKeyForMessage(messageContext);
61 if (key == null) {
62 return null;
63 }
64 if (logger.isDebugEnabled()) {
65 logger.debug("Looking up endpoint for [" + key + "]");
66 }
67 return lookupEndpoint(key);
68 }
69
70
71
72
73
74
75 protected abstract T getLookupKeyForMessage(MessageContext messageContext) throws Exception;
76
77
78
79
80
81
82
83 protected MethodEndpoint lookupEndpoint(T key) {
84 return endpointMap.get(key);
85 }
86
87
88
89
90
91
92
93
94 protected void registerEndpoint(T key, MethodEndpoint endpoint) throws BeansException {
95 Object mappedEndpoint = endpointMap.get(key);
96 if (mappedEndpoint != null) {
97 throw new ApplicationContextException("Cannot map endpoint [" + endpoint + "] on registration key [" + key +
98 "]: there's already endpoint [" + mappedEndpoint + "] mapped");
99 }
100 if (endpoint == null) {
101 throw new ApplicationContextException("Could not find endpoint for key [" + key + "]");
102 }
103 endpointMap.put(key, endpoint);
104 if (logger.isDebugEnabled()) {
105 logger.debug("Mapped [" + key + "] onto endpoint [" + endpoint + "]");
106 }
107 }
108
109
110
111
112
113
114
115
116 protected void registerMethods(final Object endpoint) {
117 Assert.notNull(endpoint, "'endpoint' must not be null");
118 Class<?> endpointClass = getEndpointClass(endpoint);
119 ReflectionUtils.doWithMethods(endpointClass, new ReflectionUtils.MethodCallback() {
120
121 public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
122 T key = getLookupKeyForMethod(method);
123 if (key != null) {
124 registerEndpoint(key, new MethodEndpoint(endpoint, method));
125 }
126 }
127 });
128 }
129
130
131
132
133
134
135
136
137 protected void registerMethods(String beanName) {
138 Assert.hasText(beanName, "'beanName' must not be empty");
139 Class<?> endpointType = getApplicationContext().getType(beanName);
140 endpointType = ClassUtils.getUserClass(endpointType);
141
142 Set<Method> methods = findEndpointMethods(endpointType, new ReflectionUtils.MethodFilter() {
143 public boolean matches(Method method) {
144 return getLookupKeyForMethod(method) != null;
145 }
146 });
147
148 for (Method method : methods) {
149 T key = getLookupKeyForMethod(method);
150 registerEndpoint(key, new MethodEndpoint(beanName, getApplicationContext(), method));
151 }
152
153 }
154
155 private Set<Method> findEndpointMethods(Class<?> endpointType,
156 final ReflectionUtils.MethodFilter endpointMethodFilter) {
157 final Set<Method> endpointMethods = new LinkedHashSet<Method>();
158 Set<Class<?>> endpointTypes = new LinkedHashSet<Class<?>>();
159 Class<?> specificEndpointType = null;
160 if (!Proxy.isProxyClass(endpointType)) {
161 endpointTypes.add(endpointType);
162 specificEndpointType = endpointType;
163 }
164 endpointTypes.addAll(Arrays.asList(endpointType.getInterfaces()));
165 for (Class<?> currentEndpointType : endpointTypes) {
166 final Class<?> targetClass = (specificEndpointType != null ? specificEndpointType : currentEndpointType);
167 ReflectionUtils.doWithMethods(currentEndpointType, new ReflectionUtils.MethodCallback() {
168 public void doWith(Method method) {
169 Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
170 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
171 if (endpointMethodFilter.matches(specificMethod) &&
172 (bridgedMethod == specificMethod || !endpointMethodFilter.matches(bridgedMethod))) {
173 endpointMethods.add(specificMethod);
174 }
175 }
176 }, ReflectionUtils.USER_DECLARED_METHODS);
177 }
178 return endpointMethods;
179 }
180
181
182
183
184
185
186
187
188 protected T getLookupKeyForMethod(Method method) {
189 return null;
190 }
191
192
193
194
195
196
197
198
199
200 protected Class<?> getEndpointClass(Object endpoint) {
201 if (AopUtils.isJdkDynamicProxy(endpoint)) {
202 throw new IllegalArgumentException(ClassUtils.getShortName(getClass()) +
203 " does not work with JDK Dynamic Proxies. " +
204 "Please use CGLIB proxies, by setting proxy-target-class=\"true\" on the aop:aspectj-autoproxy " +
205 "or aop:config element.");
206 }
207 return AopUtils.getTargetClass(endpoint);
208 }
209 }