| // |
| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.websocket.common.events.annotated; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.Objects; |
| |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.log.Logger; |
| import org.eclipse.jetty.websocket.common.util.ReflectUtils; |
| |
| /** |
| * A Callable Method |
| */ |
| public class CallableMethod |
| { |
| private static final Logger LOG = Log.getLogger(CallableMethod.class); |
| protected final Class<?> pojo; |
| protected final Method method; |
| protected Class<?>[] paramTypes; |
| |
| public CallableMethod(Class<?> pojo, Method method) |
| { |
| Objects.requireNonNull(pojo, "Pojo cannot be null"); |
| Objects.requireNonNull(method, "Method cannot be null"); |
| this.pojo = pojo; |
| this.method = method; |
| this.paramTypes = method.getParameterTypes(); |
| } |
| |
| public Object call(Object obj, Object... args) |
| { |
| if ((this.pojo == null) || (this.method == null)) |
| { |
| LOG.warn("Cannot execute call: pojo={}, method={}",pojo,method); |
| return null; // no call event method determined |
| } |
| |
| if (obj == null) |
| { |
| String err = String.format("Cannot call %s on null object", this.method); |
| LOG.warn(new RuntimeException(err)); |
| return null; |
| } |
| |
| if (args.length < paramTypes.length) |
| { |
| throw new IllegalArgumentException("Call arguments length [" + args.length + "] must always be greater than or equal to captured args length [" |
| + paramTypes.length + "]"); |
| } |
| |
| try |
| { |
| return this.method.invoke(obj,args); |
| } |
| catch (Throwable t) |
| { |
| String err = formatMethodCallError(args); |
| throw unwrapRuntimeException(err,t); |
| } |
| } |
| |
| private RuntimeException unwrapRuntimeException(String err, final Throwable t) |
| { |
| Throwable ret = t; |
| |
| while (ret instanceof InvocationTargetException) |
| { |
| ret = ((InvocationTargetException)ret).getCause(); |
| } |
| |
| if (ret instanceof RuntimeException) |
| { |
| return (RuntimeException)ret; |
| } |
| |
| return new RuntimeException(err,ret); |
| } |
| |
| public String formatMethodCallError(Object... args) |
| { |
| StringBuilder err = new StringBuilder(); |
| err.append("Cannot call method "); |
| err.append(ReflectUtils.toString(pojo,method)); |
| err.append(" with args: ["); |
| |
| boolean delim = false; |
| for (Object arg : args) |
| { |
| if (delim) |
| { |
| err.append(", "); |
| } |
| if (arg == null) |
| { |
| err.append("<null>"); |
| } |
| else |
| { |
| err.append(arg.getClass().getName()); |
| } |
| delim = true; |
| } |
| err.append("]"); |
| return err.toString(); |
| } |
| |
| public Method getMethod() |
| { |
| return method; |
| } |
| |
| public Class<?>[] getParamTypes() |
| { |
| return paramTypes; |
| } |
| |
| public Class<?> getPojo() |
| { |
| return pojo; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return String.format("%s[%s]",this.getClass().getSimpleName(),method.toGenericString()); |
| } |
| } |