package org.etk.model.apt;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.etk.model.apt.Invoker;
import org.etk.model.apt.TypeHierarchyVisitor;
import org.etk.model.plugins.instrument.MethodHandler;
public final class Invoker {
/**
* Finds the method base on the given MethodName and ParameterTypes
*
* @author thanh_vucong
*/
private static class MethodFinder extends TypeHierarchyVisitor {
/** . */
private final String methodName;
/** . */
private final Class[] parameterTypes;
/** . */
private Method method;
private MethodFinder(String methodName, Class[] parameterTypes) {
this.methodName = methodName;
this.parameterTypes = parameterTypes;
}
protected boolean enter(Class type) {
try {
method = type.getDeclaredMethod(methodName, parameterTypes);
return false;
} catch (NoSuchMethodException e) {
return true;
}
}
}
/**
* Gets the method via a given ClassType, methodName and list of
* parameterTypes.
*
* @param clazz
* @param methodName
* @param parameterTypes
* @return
*/
public static Invoker getDeclaredMethod(Class<?> clazz,
final String methodName,
final Class<?>... parameterTypes) {
MethodFinder visitor = new MethodFinder(methodName, parameterTypes);
visitor.accept(clazz);
//
if (visitor.method == null) {
StringBuilder sb = new StringBuilder(methodName).append('(');
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(parameterTypes[i].getName());
}
sb.append(')');
throw new AssertionError("Could not find method " + sb + " on class " + clazz);
}
//
return new Invoker(visitor.method);
}
/** . */
public final Method method;
public Invoker(Method method) {
this.method = method;
}
public Method getMethod() {
return method;
}
/**
* Invokes the underlying method represented by this {@link MethodHandler}
* on specified Object.
*
* @param methodInvoker
* @param obj
* @return
*/
public Object invoke(MethodHandler methodInvoker, Object obj) {
try {
return methodInvoker.invoke(obj, method);
} catch (Throwable e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if (e instanceof Error) {
throw (Error) e;
}
throw new UndeclaredThrowableException(e);
}
}
public Object invoke(MethodHandler methodInvoker, Object obj, Object arg) {
try {
return methodInvoker.invoke(obj, method, arg);
} catch (Throwable e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if (e instanceof Error) {
throw (Error) e;
}
throw new UndeclaredThrowableException(e);
}
}
public Object invoke(MethodHandler methodInvoker, Object obj, Object[] args) {
try {
return methodInvoker.invoke(obj, method, args);
} catch (Throwable e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if (e instanceof Error) {
throw (Error) e;
}
throw new UndeclaredThrowableException(e);
}
}
}