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 String err = String.format("Cannot call %s on null object", this.method);
59 LOG.warn(new RuntimeException(err));
60 return null;
61 }
62
63 if (args.length < paramTypes.length)
64 {
65 throw new IllegalArgumentException("Call arguments length [" + args.length + "] must always be greater than or equal to captured args length ["
66 + paramTypes.length + "]");
67 }
68
69 try
70 {
71 return this.method.invoke(obj,args);
72 }
73 catch (Throwable t)
74 {
75 String err = formatMethodCallError(args);
76 throw unwrapRuntimeException(err,t);
77 }
78 }
79
80 private RuntimeException unwrapRuntimeException(String err, final Throwable t)
81 {
82 Throwable ret = t;
83
84 while (ret instanceof InvocationTargetException)
85 {
86 ret = ((InvocationTargetException)ret).getCause();
87 }
88
89 if (ret instanceof RuntimeException)
90 {
91 return (RuntimeException)ret;
92 }
93
94 return new RuntimeException(err,ret);
95 }
96
97 public String formatMethodCallError(Object... args)
98 {
99 StringBuilder err = new StringBuilder();
100 err.append("Cannot call method ");
101 err.append(ReflectUtils.toString(pojo,method));
102 err.append(" with args: [");
103
104 boolean delim = false;
105 for (Object arg : args)
106 {
107 if (delim)
108 {
109 err.append(", ");
110 }
111 if (arg == null)
112 {
113 err.append("<null>");
114 }
115 else
116 {
117 err.append(arg.getClass().getName());
118 }
119 delim = true;
120 }
121 err.append("]");
122 return err.toString();
123 }
124
125 public Method getMethod()
126 {
127 return method;
128 }
129
130 public Class<?>[] getParamTypes()
131 {
132 return paramTypes;
133 }
134
135 public Class<?> getPojo()
136 {
137 return pojo;
138 }
139
140 @Override
141 public String toString()
142 {
143 return String.format("%s[%s]",this.getClass().getSimpleName(),method.toGenericString());
144 }
145 }