package net.sourceforge.javautil.interceptor.asm;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.interceptor.Interceptor;
import javax.interceptor.InterceptorBinding;
import javax.interceptor.Interceptors;
import net.sourceforge.javautil.common.reflection.ReflectionContext;
import net.sourceforge.javautil.common.reflection.cache.ClassCache;
import net.sourceforge.javautil.common.reflection.cache.ClassDescriptor;
import net.sourceforge.javautil.common.reflection.cache.ClassMethod;
import net.sourceforge.javautil.interceptor.InterceptorCompiler;
import net.sourceforge.javautil.interceptor.IInterceptorLink;
import net.sourceforge.javautil.interceptor.InterceptorLinkTarget;
import net.sourceforge.javautil.interceptor.InterceptorLinkWrapper;
import net.sourceforge.javautil.interceptor.InterceptorInvocationContext;
import net.sourceforge.javautil.interceptor.InterceptorInvocationException;
import net.sourceforge.javautil.interceptor.type.InterceptorInvocationHandler;
import net.sourceforge.javautil.interceptor.type.cjc.InterceptorProxyConstructor;
import net.sourceforge.javautil.interceptor.type.cjc.InterceptorProxyMethod;
import org.objectweb.asm.Type;
/**
* Help methods for the generated bytecode of the {@link Interceptor} proxy classes.
*
* @author elponderador
* @author $Author$
* @version $Id$
*
* @see InterceptorCompiler
* @see InterceptorProxyConstructor
* @see InterceptorProxyMethod
* @see InterceptorInvocationHandler
*/
public class InterceptorHelper {
/**
* This will parse the descriptor via {@link Type}.
*
* @see #findMethod(Class, String, String, Class...)
*/
public static Method findMethod (Class clazz, String name, Map<String, Method> cache, String descriptor) throws Throwable {
String key = name + ":" + descriptor;
if (cache.containsKey(key)) return cache.get(key);
Method method = findMethod(clazz, name, descriptor, Type.getArgumentTypes(descriptor));
cache.put(key, method);
return method;
}
/**
* This will do runtime loading of the actual {@link Class}'s.
*
* @see #findMethod(Class, String, String, Class...)
*/
public static Method findMethod (Class clazz, String name, String descriptor, Type... types) throws Throwable {
Class[] classes = new Class[types.length];
for (int t=0; t<types.length; t++) {
String className = types[t].getClassName();
if ("int".equals(className)) classes[t] = int.class;
else if ("byte".equals(className)) classes[t] = byte.class;
else if ("short".equals(className)) classes[t] = short.class;
else if ("long".equals(className)) classes[t] = long.class;
else if ("double".equals(className)) classes[t] = double.class;
else if ("float".equals(className)) classes[t] = float.class;
else if ("char".equals(className)) classes[t] = char.class;
else if ("boolean".equals(className)) classes[t] = boolean.class;
else if (types[t].getSort() == Type.ARRAY) {
int indices = 0;
Type type = types[t];
while (type.getSort() == Type.ARRAY) {
indices ++;
type = type.getElementType();
}
int[] dimensions = new int[indices];
classes[t] = Array.newInstance(Class.forName(type.getClassName()), dimensions).getClass();
}
else classes[t] = Class.forName(types[t].getClassName());
}
return findMethod(clazz, name, descriptor, classes);
}
/**
* This will lookup in the declared methods for the class and its super classes a method
* that exactly matches the classes passed.
*
* @param clazz The class in question
* @param name The name of the method
* @param descriptor The JVM internal method signature
* @param classes The classes extracted from the passed signature
* @return The matching method
*
* @throws Throwable Could be access related or simply that no method was found
*/
public static Method findMethod (Class clazz, String name, String descriptor, Class... classes) throws Throwable {
ClassMethod method = ClassCache.getFor(clazz).findMethod(name, classes);
if (method != null) return method.getJavaMember();
throw new InterceptorInvocationException("Could not find method: " + name + " (" + descriptor + ") for: " + clazz.getName());
}
}