1 16 package net.sf.cglib.proxy; 17 18 import java.lang.reflect.Method ; 19 import java.util.*; 20 import net.sf.cglib.core.*; 21 import org.objectweb.asm.Label; 22 import org.objectweb.asm.Type; 23 24 class MethodInterceptorGenerator 25 implements CallbackGenerator 26 { 27 public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator(); 28 29 static final String EMPTY_ARGS_NAME = "CGLIB$emptyArgs"; 30 static final String FIND_PROXY_NAME = "CGLIB$findMethodProxy"; 31 static final Class [] FIND_PROXY_TYPES = { Signature.class }; 32 33 private static final Type ABSTRACT_METHOD_ERROR = 34 TypeUtils.parseType("AbstractMethodError"); 35 private static final Type METHOD = 36 TypeUtils.parseType("java.lang.reflect.Method"); 37 private static final Type REFLECT_UTILS = 38 TypeUtils.parseType("net.sf.cglib.core.ReflectUtils"); 39 private static final Type METHOD_PROXY = 40 TypeUtils.parseType("net.sf.cglib.proxy.MethodProxy"); 41 private static final Type METHOD_INTERCEPTOR = 42 TypeUtils.parseType("net.sf.cglib.proxy.MethodInterceptor"); 43 private static final Signature GET_DECLARED_METHODS = 44 TypeUtils.parseSignature("java.lang.reflect.Method[] getDeclaredMethods()"); 45 private static final Signature GET_DECLARING_CLASS = 46 TypeUtils.parseSignature("Class getDeclaringClass()"); 47 private static final Signature FIND_METHODS = 48 TypeUtils.parseSignature("java.lang.reflect.Method[] findMethods(String[], java.lang.reflect.Method[])"); 49 private static final Signature MAKE_PROXY = 50 new Signature("create", METHOD_PROXY, new Type[]{ 51 Constants.TYPE_CLASS, 52 Constants.TYPE_CLASS, 53 Constants.TYPE_STRING, 54 Constants.TYPE_STRING, 55 Constants.TYPE_STRING 56 }); 57 private static final Signature INTERCEPT = 58 new Signature("intercept", Constants.TYPE_OBJECT, new Type[]{ 59 Constants.TYPE_OBJECT, 60 METHOD, 61 Constants.TYPE_OBJECT_ARRAY, 62 METHOD_PROXY 63 }); 64 private static final Signature FIND_PROXY = 65 new Signature(FIND_PROXY_NAME, METHOD_PROXY, new Type[]{ Constants.TYPE_SIGNATURE }); 66 private static final Signature TO_STRING = 67 TypeUtils.parseSignature("String toString()"); 68 private static final Transformer METHOD_TO_CLASS = new Transformer(){ 69 public Object transform(Object value) { 70 return ((MethodInfo)value).getClassInfo(); 71 } 72 }; 73 private static final Signature CSTRUCT_SIGNATURE = 74 TypeUtils.parseConstructor("String, String"); 75 76 private String getMethodField(Signature impl) { 77 return impl.getName() + "$Method"; 78 } 79 private String getMethodProxyField(Signature impl) { 80 return impl.getName() + "$Proxy"; 81 } 82 83 public void generate(ClassEmitter ce, Context context, List methods) { 84 Map sigMap = new HashMap(); 85 for (Iterator it = methods.iterator(); it.hasNext();) { 86 MethodInfo method = (MethodInfo)it.next(); 87 Signature sig = method.getSignature(); 88 Signature impl = context.getImplSignature(method); 89 90 String methodField = getMethodField(impl); 91 String methodProxyField = getMethodProxyField(impl); 92 93 sigMap.put(sig.toString(), methodProxyField); 94 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodField, METHOD, null); 95 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodProxyField, METHOD_PROXY, null); 96 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, EMPTY_ARGS_NAME, Constants.TYPE_OBJECT_ARRAY, null); 97 CodeEmitter e; 98 99 e = ce.begin_method(Constants.ACC_FINAL, 101 impl, 102 method.getExceptionTypes()); 103 superHelper(e, method); 104 e.return_value(); 105 e.end_method(); 106 107 e = context.beginMethod(ce, method); 109 Label nullInterceptor = e.make_label(); 110 context.emitCallback(e, context.getIndex(method)); 111 e.dup(); 112 e.ifnull(nullInterceptor); 113 114 e.load_this(); 115 e.getfield(methodField); 116 117 if (sig.getArgumentTypes().length == 0) { 118 e.getfield(EMPTY_ARGS_NAME); 119 } else { 120 e.create_arg_array(); 121 } 122 123 e.getfield(methodProxyField); 124 e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT); 125 e.unbox_or_zero(sig.getReturnType()); 126 e.return_value(); 127 128 e.mark(nullInterceptor); 129 superHelper(e, method); 130 e.return_value(); 131 e.end_method(); 132 } 133 generateFindProxy(ce, sigMap); 134 } 135 136 private static void superHelper(CodeEmitter e, MethodInfo method) 137 { 138 if (TypeUtils.isAbstract(method.getModifiers())) { 139 e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" ); 140 } else { 141 e.load_this(); 142 e.load_args(); 143 e.super_invoke(method.getSignature()); 144 } 145 } 146 147 public void generateStatic(CodeEmitter e, Context context, List methods) throws Exception { 148 160 161 e.push(0); 162 e.newarray(); 163 e.putfield(EMPTY_ARGS_NAME); 164 165 Local thisclass = e.make_local(); 166 Local declaringclass = e.make_local(); 167 EmitUtils.load_class_this(e); 168 e.store_local(thisclass); 169 170 Map methodsByClass = CollectionUtils.bucket(methods, METHOD_TO_CLASS); 171 for (Iterator i = methodsByClass.keySet().iterator(); i.hasNext();) { 172 ClassInfo classInfo = (ClassInfo)i.next(); 173 174 List classMethods = (List)methodsByClass.get(classInfo); 175 e.push(2 * classMethods.size()); 176 e.newarray(Constants.TYPE_STRING); 177 for (int index = 0; index < classMethods.size(); index++) { 178 MethodInfo method = (MethodInfo)classMethods.get(index); 179 Signature sig = method.getSignature(); 180 e.dup(); 181 e.push(2 * index); 182 e.push(sig.getName()); 183 e.aastore(); 184 e.dup(); 185 e.push(2 * index + 1); 186 e.push(sig.getDescriptor()); 187 e.aastore(); 188 } 189 190 EmitUtils.load_class(e, classInfo.getType()); 191 e.dup(); 192 e.store_local(declaringclass); 193 e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHODS); 194 e.invoke_static(REFLECT_UTILS, FIND_METHODS); 195 196 for (int index = 0; index < classMethods.size(); index++) { 197 MethodInfo method = (MethodInfo)classMethods.get(index); 198 Signature sig = method.getSignature(); 199 Signature impl = context.getImplSignature(method); 200 e.dup(); 201 e.push(index); 202 e.array_load(METHOD); 203 e.putfield(getMethodField(impl)); 204 205 e.load_local(declaringclass); 206 e.load_local(thisclass); 207 e.push(sig.getDescriptor()); 208 e.push(sig.getName()); 209 e.push(impl.getName()); 210 e.invoke_static(METHOD_PROXY, MAKE_PROXY); 211 e.putfield(getMethodProxyField(impl)); 212 } 213 e.pop(); 214 } 215 } 216 217 public void generateFindProxy(ClassEmitter ce, final Map sigMap) { 218 final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 219 FIND_PROXY, 220 null); 221 e.load_arg(0); 222 e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); 223 ObjectSwitchCallback callback = new ObjectSwitchCallback() { 224 public void processCase(Object key, Label end) { 225 e.getfield((String )sigMap.get(key)); 226 e.return_value(); 227 } 228 public void processDefault() { 229 e.aconst_null(); 230 e.return_value(); 231 } 232 }; 233 EmitUtils.string_switch(e, 234 (String [])sigMap.keySet().toArray(new String [0]), 235 Constants.SWITCH_STYLE_HASH, 236 callback); 237 e.end_method(); 238 } 239 } 240 | Popular Tags |