1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath.functions;
19
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Modifier;
23
24 import org.apache.commons.jxpath.ExpressionContext;
25 import org.apache.commons.jxpath.Function;
26 import org.apache.commons.jxpath.JXPathInvalidAccessException;
27 import org.apache.commons.jxpath.util.TypeUtils;
28 import org.apache.commons.jxpath.util.ValueUtils;
29
30
31
32
33 public class MethodFunction implements Function {
34
35 private static final Object[] EMPTY_ARRAY = {};
36 private final Method method;
37
38
39
40
41
42
43 public MethodFunction(final Method method) {
44 this.method = ValueUtils.getAccessibleMethod(method);
45 }
46
47 @Override
48 public Object invoke(final ExpressionContext context, Object[] parameters) {
49 try {
50 Object target;
51 Object[] args;
52 if (Modifier.isStatic(method.getModifiers())) {
53 target = null;
54 if (parameters == null) {
55 parameters = EMPTY_ARRAY;
56 }
57 int pi = 0;
58 final Class[] types = method.getParameterTypes();
59 if (types.length >= 1 && ExpressionContext.class.isAssignableFrom(types[0])) {
60 pi = 1;
61 }
62 args = new Object[parameters.length + pi];
63 if (pi == 1) {
64 args[0] = context;
65 }
66 for (int i = 0; i < parameters.length; i++) {
67 args[i + pi] = TypeUtils.convert(parameters[i], types[i + pi]);
68 }
69 } else {
70 int pi = 0;
71 final Class[] types = method.getParameterTypes();
72 if (types.length >= 1 && ExpressionContext.class.isAssignableFrom(types[0])) {
73 pi = 1;
74 }
75 target = TypeUtils.convert(parameters[0], method.getDeclaringClass());
76 args = new Object[parameters.length - 1 + pi];
77 if (pi == 1) {
78 args[0] = context;
79 }
80 for (int i = 1; i < parameters.length; i++) {
81 args[pi + i - 1] = TypeUtils.convert(parameters[i], types[i + pi - 1]);
82 }
83 }
84 return method.invoke(target, args);
85 } catch (Throwable ex) {
86 if (ex instanceof InvocationTargetException) {
87 ex = ((InvocationTargetException) ex).getTargetException();
88 }
89 throw new JXPathInvalidAccessException("Cannot invoke " + method, ex);
90 }
91 }
92
93 @Override
94 public String toString() {
95 return method.toString();
96 }
97 }