1 54 package org.logicalcobwebs.cglib.proxy; 55 56 import java.lang.reflect.*; 57 import java.util.*; 58 import org.logicalcobwebs.cglib.core.*; 59 import org.logicalcobwebs.asm.Label; 60 import org.logicalcobwebs.asm.Type; 61 62 class MethodInterceptorGenerator 63 implements CallbackGenerator 64 { 65 public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator(); 66 67 static final String FIND_PROXY_NAME = "CGLIB$findMethodProxy"; 68 static final Class [] FIND_PROXY_TYPES = { Signature.class }; 69 70 private static final Signature FIND_PROXY = 71 new Signature(FIND_PROXY_NAME, 72 TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.MethodProxy"), 73 TypeUtils.getTypes(FIND_PROXY_TYPES)); 74 75 private static final Type ABSTRACT_METHOD_ERROR = 76 TypeUtils.parseType("AbstractMethodError"); 77 private static final Type METHOD = 78 TypeUtils.parseType("java.lang.reflect.Method"); 79 private static final Type METHOD_PROXY = 80 TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.MethodProxy"); 81 private static final Type METHOD_INTERCEPTOR = 82 TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.MethodInterceptor"); 83 private static final Signature GET_DECLARING_CLASS = 84 TypeUtils.parseSignature("Class getDeclaringClass()"); 85 private static final Signature GET_CLASS_LOADER = 86 TypeUtils.parseSignature("ClassLoader getClassLoader()"); 87 private static final Signature MAKE_PROXY = 88 TypeUtils.parseSignature("org.logicalcobwebs.cglib.proxy.MethodProxy create(ClassLoader, Class, Class, String, String, String)"); 89 private static final Signature INTERCEPT = 90 TypeUtils.parseSignature("Object intercept(Object, java.lang.reflect.Method, Object[], org.logicalcobwebs.cglib.proxy.MethodProxy)"); 91 private static final Signature TO_STRING = 92 TypeUtils.parseSignature("String toString()"); 93 94 public void generate(ClassEmitter ce, Context context) { 95 Map sigMap = new HashMap(); 96 for (Iterator it = context.getMethods(); it.hasNext();) { 97 Method method = (Method)it.next(); 98 String accessName = getAccessName(context, method); 99 String fieldName = getFieldName(context, method); 100 sigMap.put(ReflectUtils.getSignature(method).toString(), accessName); 101 102 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, METHOD, null, null); 103 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, accessName, METHOD_PROXY, null, null); 104 CodeEmitter e; 105 106 e = ce.begin_method(Constants.ACC_FINAL, 108 new Signature(getAccessName(context, method), 109 ReflectUtils.getSignature(method).getDescriptor()), 110 ReflectUtils.getExceptionTypes(method), 111 null); 112 if (Modifier.isAbstract(method.getModifiers())) { 113 e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" ); 114 } else { 115 e.load_this(); 116 e.load_args(); 117 e.super_invoke(ReflectUtils.getSignature(method)); 118 } 119 e.return_value(); 120 e.end_method(); 121 122 e = ce.begin_method(context.getModifiers(method), 124 ReflectUtils.getSignature(method), 125 ReflectUtils.getExceptionTypes(method), 126 null); 127 Label nullInterceptor = e.make_label(); 128 context.emitCallback(e, context.getIndex(method)); 129 e.dup(); 130 e.ifnull(nullInterceptor); 131 132 e.load_this(); 133 e.getfield(fieldName); 134 e.create_arg_array(); 135 e.getfield(accessName); 136 e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT); 137 e.unbox_or_zero(Type.getType(method.getReturnType())); 138 e.return_value(); 139 140 e.mark(nullInterceptor); 141 e.load_this(); 142 e.load_args(); 143 e.super_invoke(ReflectUtils.getSignature(method)); 144 e.return_value(); 145 e.end_method(); 146 } 147 generateFindProxy(ce, sigMap); 148 } 149 150 private String getFieldName(Context context, Method method) { 151 return "CGLIB$$METHOD_" + context.getUniqueName(method); 152 } 153 154 private String getAccessName(Context context, Method method) { 155 return "CGLIB$$ACCESS_" + context.getUniqueName(method); 156 } 157 158 public void generateStatic(CodeEmitter e, final Context context) { 159 168 169 Local thisclass = e.make_local(); 170 EmitUtils.load_class_this(e); 171 e.dup(); 172 e.store_local(thisclass); 173 e.invoke_virtual(Constants.TYPE_CLASS, GET_CLASS_LOADER); 174 175 for (Iterator it = context.getMethods(); it.hasNext();) { 176 e.dup(); 177 Method method = (Method)it.next(); 178 EmitUtils.load_method(e, method); 179 e.dup(); 180 e.putfield(getFieldName(context, method)); 181 182 String accessName = getAccessName(context, method); 183 Signature sig = ReflectUtils.getSignature(method); 184 e.invoke_virtual(METHOD, GET_DECLARING_CLASS); 185 e.load_local(thisclass); 186 e.push(sig.getDescriptor()); 187 e.push(sig.getName()); 188 e.push(accessName); 189 e.invoke_static(METHOD_PROXY, MAKE_PROXY); 190 e.putfield(accessName); 191 } 192 } 193 194 public void generateFindProxy(ClassEmitter ce, final Map sigMap) { 195 final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 196 FIND_PROXY, 197 null, 198 null); 199 e.load_arg(0); 200 e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); 201 ObjectSwitchCallback callback = new ObjectSwitchCallback() { 202 public void processCase(Object key, Label end) { 203 e.getfield((String )sigMap.get(key)); 204 e.return_value(); 205 } 206 public void processDefault() { 207 e.aconst_null(); 208 e.return_value(); 209 } 210 }; 211 EmitUtils.string_switch(e, 212 (String [])sigMap.keySet().toArray(new String [0]), 213 Constants.SWITCH_STYLE_HASH, 214 callback); 215 e.end_method(); 216 } 217 } 218 | Popular Tags |