1 54 package org.logicalcobwebs.cglib.reflect; 55 56 import java.lang.reflect.*; 57 import org.logicalcobwebs.cglib.*; 58 import org.logicalcobwebs.cglib.core.*; 59 import org.logicalcobwebs.asm.ClassVisitor; 60 import org.logicalcobwebs.asm.Type; 61 62 64 145 abstract public class MethodDelegate { 146 private static final MethodDelegateKey KEY_FACTORY = 147 (MethodDelegateKey)KeyFactory.create(MethodDelegateKey.class, KeyFactory.CLASS_BY_NAME); 148 149 protected Object target; 150 protected String eqMethod; 151 152 interface MethodDelegateKey { 153 Object newInstance(Class delegateClass, String methodName, Class iface); 154 } 155 156 public static MethodDelegate createStatic(Class targetClass, String methodName, Class iface) { 157 Generator gen = new Generator(); 158 gen.setTargetClass(targetClass); 159 gen.setMethodName(methodName); 160 gen.setInterface(iface); 161 return gen.create(); 162 } 163 164 public static MethodDelegate create(Object target, String methodName, Class iface) { 165 Generator gen = new Generator(); 166 gen.setTarget(target); 167 gen.setMethodName(methodName); 168 gen.setInterface(iface); 169 return gen.create(); 170 } 171 172 public boolean equals(Object obj) { 173 MethodDelegate other = (MethodDelegate)obj; 174 return target == other.target && eqMethod.equals(other.eqMethod); 175 } 176 177 public int hashCode() { 178 return target.hashCode() ^ eqMethod.hashCode(); 179 } 180 181 public Object getTarget() { 182 return target; 183 } 184 185 abstract public MethodDelegate newInstance(Object target); 186 187 public static class Generator extends AbstractClassGenerator { 188 private static final Source SOURCE = new Source(MethodDelegate.class.getName()); 189 private static final Signature NEW_INSTANCE = 190 TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MethodDelegate newInstance(Object)"); 191 private static final Type METHOD_DELEGATE = 192 TypeUtils.parseType("org.logicalcobwebs.cglib.reflect.MethodDelegate"); 193 194 private Object target; 195 private Class targetClass; 196 private String methodName; 197 private Class iface; 198 199 public Generator() { 200 super(SOURCE); 201 } 202 203 public void setTarget(Object target) { 204 this.target = target; 205 this.targetClass = target.getClass(); 206 } 207 208 public void setTargetClass(Class targetClass) { 209 this.targetClass = targetClass; 210 } 211 212 public void setMethodName(String methodName) { 213 this.methodName = methodName; 214 } 215 216 public void setInterface(Class iface) { 217 this.iface = iface; 218 } 219 220 protected ClassLoader getDefaultClassLoader() { 221 return targetClass.getClassLoader(); 222 } 223 224 public MethodDelegate create() { 225 setNamePrefix(targetClass.getName()); 226 Object key = KEY_FACTORY.newInstance(targetClass, methodName, iface); 227 return (MethodDelegate)super.create(key); 228 } 229 230 protected Object firstInstance(Class type) { 231 return ((MethodDelegate)ReflectUtils.newInstance(type)).newInstance(target); 232 } 233 234 protected Object nextInstance(Object instance) { 235 return ((MethodDelegate)instance).newInstance(target); 236 } 237 238 public void generateClass(ClassVisitor v) throws NoSuchMethodException { 239 Method proxy = ReflectUtils.findInterfaceMethod(iface); 240 final Method method = targetClass.getMethod(methodName, proxy.getParameterTypes()); 241 if (!proxy.getReturnType().isAssignableFrom(method.getReturnType())) { 242 throw new IllegalArgumentException ("incompatible return types"); 243 } 244 245 boolean isStatic = Modifier.isStatic(method.getModifiers()); 246 if ((target == null) ^ isStatic) { 247 throw new IllegalArgumentException ("Static method " + (isStatic ? "not " : "") + "expected"); 248 } 249 250 ClassEmitter ce = new ClassEmitter(v); 251 CodeEmitter e; 252 ce.begin_class(Constants.ACC_PUBLIC, 253 getClassName(), 254 METHOD_DELEGATE, 255 new Type[]{ Type.getType(iface) }, 256 Constants.SOURCE_FILE); 257 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, "eqMethod", Constants.TYPE_STRING, null, null); 258 EmitUtils.null_constructor(ce); 259 260 Method proxied = iface.getDeclaredMethods()[0]; 262 e = ce.begin_method(Constants.ACC_PUBLIC, 263 ReflectUtils.getSignature(proxied), 264 ReflectUtils.getExceptionTypes(proxied), 265 null); 266 e.load_this(); 267 e.super_getfield("target", Constants.TYPE_OBJECT); 268 e.checkcast(Type.getType(method.getDeclaringClass())); 269 e.load_args(); 270 e.invoke(method); 271 e.return_value(); 272 e.end_method(); 273 274 e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null, null); 276 e.new_instance_this(); 277 e.dup(); 278 e.dup2(); 279 e.invoke_constructor_this(); 280 e.getfield("eqMethod"); 281 e.super_putfield("eqMethod", Constants.TYPE_STRING); 282 e.load_arg(0); 283 e.super_putfield("target", Constants.TYPE_OBJECT); 284 e.return_value(); 285 e.end_method(); 286 287 e = ce.begin_static(); 289 Signature sig = ReflectUtils.getSignature(method); 290 e.push(sig.getName() + sig.getDescriptor()); 291 e.putfield("eqMethod"); 292 e.return_value(); 293 e.end_method(); 294 295 ce.end_class(); 296 } 297 } 298 } 299 | Popular Tags |