1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.batch.item.adapter;
18
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24
25 import org.springframework.beans.factory.InitializingBean;
26 import org.springframework.util.Assert;
27 import org.springframework.util.MethodInvoker;
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public abstract class AbstractMethodInvokingDelegator<T> implements InitializingBean {
42
43 private Object targetObject;
44
45 private String targetMethod;
46
47 private Object[] arguments;
48
49
50
51
52
53
54
55
56 protected T invokeDelegateMethod() throws Exception {
57 MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
58 invoker.setArguments(arguments);
59 return doInvoke(invoker);
60 }
61
62
63
64
65
66
67
68
69 protected T invokeDelegateMethodWithArgument(Object object) throws Exception {
70 MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
71 invoker.setArguments(new Object[] { object });
72 return doInvoke(invoker);
73 }
74
75
76
77
78
79
80
81
82 protected T invokeDelegateMethodWithArguments(Object[] args) throws Exception {
83 MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
84 invoker.setArguments(args);
85 return doInvoke(invoker);
86 }
87
88
89
90
91 private MethodInvoker createMethodInvoker(Object targetObject, String targetMethod) {
92 HippyMethodInvoker invoker = new HippyMethodInvoker();
93 invoker.setTargetObject(targetObject);
94 invoker.setTargetMethod(targetMethod);
95 invoker.setArguments(arguments);
96 return invoker;
97 }
98
99
100
101
102
103
104 @SuppressWarnings("unchecked")
105 private T doInvoke(MethodInvoker invoker) throws Exception {
106 try {
107 invoker.prepare();
108 }
109 catch (ClassNotFoundException e) {
110 throw new DynamicMethodInvocationException(e);
111 }
112 catch (NoSuchMethodException e) {
113 throw new DynamicMethodInvocationException(e);
114 }
115
116 try {
117 return (T) invoker.invoke();
118 }
119 catch (InvocationTargetException e) {
120 if (e.getCause() instanceof Exception) {
121 throw (Exception) e.getCause();
122 }
123 else {
124 throw new InvocationTargetThrowableWrapper(e.getCause());
125 }
126 }
127 catch (IllegalAccessException e) {
128 throw new DynamicMethodInvocationException(e);
129 }
130 }
131
132 @Override
133 public void afterPropertiesSet() throws Exception {
134 Assert.notNull(targetObject);
135 Assert.hasLength(targetMethod);
136 Assert.state(targetClassDeclaresTargetMethod(),
137 "target class must declare a method with matching name and parameter types");
138 }
139
140
141
142
143
144 private boolean targetClassDeclaresTargetMethod() {
145 MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
146
147 Method[] memberMethods = invoker.getTargetClass().getMethods();
148 Method[] declaredMethods = invoker.getTargetClass().getDeclaredMethods();
149
150 List<Method> allMethods = new ArrayList<Method>();
151 allMethods.addAll(Arrays.asList(memberMethods));
152 allMethods.addAll(Arrays.asList(declaredMethods));
153
154 String targetMethodName = invoker.getTargetMethod();
155
156 for (Method method : allMethods) {
157 if (method.getName().equals(targetMethodName)) {
158 Class<?>[] params = method.getParameterTypes();
159 if (arguments == null) {
160
161
162 return true;
163 }
164 if (arguments.length == params.length) {
165 boolean argumentsMatchParameters = true;
166 for (int j = 0; j < params.length; j++) {
167 if (arguments[j] == null) {
168 continue;
169 }
170 if (!(params[j].isAssignableFrom(arguments[j].getClass()))) {
171 argumentsMatchParameters = false;
172 }
173 }
174 if (argumentsMatchParameters) {
175 return true;
176 }
177 }
178 }
179 }
180
181 return false;
182 }
183
184
185
186
187
188 public void setTargetObject(Object targetObject) {
189 this.targetObject = targetObject;
190 }
191
192
193
194
195
196 public void setTargetMethod(String targetMethod) {
197 this.targetMethod = targetMethod;
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211 public void setArguments(Object[] arguments) {
212 this.arguments = arguments == null ? null : Arrays.asList(arguments).toArray();
213 }
214
215
216
217
218
219
220
221 public static class InvocationTargetThrowableWrapper extends RuntimeException {
222
223 public InvocationTargetThrowableWrapper(Throwable cause) {
224 super(cause);
225 }
226
227 }
228 }