View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
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   * A Callable Method
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; // no call event method determined
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 }