1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.common.events.annotated;
20
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.util.Objects;
24
25 import org.eclipse.jetty.util.log.Log;
26 import org.eclipse.jetty.util.log.Logger;
27 import org.eclipse.jetty.websocket.common.util.ReflectUtils;
28
29
30
31
32 public class CallableMethod
33 {
34 private static final Logger LOG = Log.getLogger(CallableMethod.class);
35 protected final Class<?> pojo;
36 protected final Method method;
37 protected Class<?>[] paramTypes;
38
39 public CallableMethod(Class<?> pojo, Method method)
40 {
41 Objects.requireNonNull(pojo, "Pojo cannot be null");
42 Objects.requireNonNull(method, "Method cannot be null");
43 this.pojo = pojo;
44 this.method = method;
45 this.paramTypes = method.getParameterTypes();
46 }
47
48 public Object call(Object obj, Object... args)
49 {
50 if ((this.pojo == null) || (this.method == null))
51 {
52 LOG.warn("Cannot execute call: pojo={}, method={}",pojo,method);
53 return null;
54 }
55
56 if (obj == null)
57 {
58 LOG.warn("Cannot call {} on null object",this.method);
59 return null;
60 }
61
62 if (args.length < paramTypes.length)
63 {
64 throw new IllegalArgumentException("Call arguments length [" + args.length + "] must always be greater than or equal to captured args length ["
65 + paramTypes.length + "]");
66 }
67
68 try
69 {
70 return this.method.invoke(obj,args);
71 }
72 catch (Throwable t)
73 {
74 String err = formatMethodCallError(args);
75 throw unwrapRuntimeException(err,t);
76 }
77 }
78
79 private RuntimeException unwrapRuntimeException(String err, final Throwable t)
80 {
81 Throwable ret = t;
82
83 while (ret instanceof InvocationTargetException)
84 {
85 ret = ((InvocationTargetException)ret).getCause();
86 }
87
88 if (ret instanceof RuntimeException)
89 {
90 return (RuntimeException)ret;
91 }
92
93 return new RuntimeException(err,ret);
94 }
95
96 public String formatMethodCallError(Object... args)
97 {
98 StringBuilder err = new StringBuilder();
99 err.append("Cannot call method ");
100 err.append(ReflectUtils.toString(pojo,method));
101 err.append(" with args: [");
102
103 boolean delim = false;
104 for (Object arg : args)
105 {
106 if (delim)
107 {
108 err.append(", ");
109 }
110 if (arg == null)
111 {
112 err.append("<null>");
113 }
114 else
115 {
116 err.append(arg.getClass().getName());
117 }
118 delim = true;
119 }
120 err.append("]");
121 return err.toString();
122 }
123
124 public Method getMethod()
125 {
126 return method;
127 }
128
129 public Class<?>[] getParamTypes()
130 {
131 return paramTypes;
132 }
133
134 public Class<?> getPojo()
135 {
136 return pojo;
137 }
138
139 @Override
140 public String toString()
141 {
142 return String.format("%s[%s]",this.getClass().getSimpleName(),method.toGenericString());
143 }
144 }