1 16 package net.sf.cglib.reflect; 17 18 import java.lang.reflect.*; 19 import net.sf.cglib.*; 20 import net.sf.cglib.core.*; 21 import org.objectweb.asm.ClassVisitor; 22 import org.objectweb.asm.Type; 23 24 26 107 abstract public class MethodDelegate { 108 private static final MethodDelegateKey KEY_FACTORY = 109 (MethodDelegateKey)KeyFactory.create(MethodDelegateKey.class, KeyFactory.CLASS_BY_NAME); 110 111 protected Object target; 112 protected String eqMethod; 113 114 interface MethodDelegateKey { 115 Object newInstance(Class delegateClass, String methodName, Class iface); 116 } 117 118 public static MethodDelegate createStatic(Class targetClass, String methodName, Class iface) { 119 Generator gen = new Generator(); 120 gen.setTargetClass(targetClass); 121 gen.setMethodName(methodName); 122 gen.setInterface(iface); 123 return gen.create(); 124 } 125 126 public static MethodDelegate create(Object target, String methodName, Class iface) { 127 Generator gen = new Generator(); 128 gen.setTarget(target); 129 gen.setMethodName(methodName); 130 gen.setInterface(iface); 131 return gen.create(); 132 } 133 134 public boolean equals(Object obj) { 135 MethodDelegate other = (MethodDelegate)obj; 136 return target == other.target && eqMethod.equals(other.eqMethod); 137 } 138 139 public int hashCode() { 140 return target.hashCode() ^ eqMethod.hashCode(); 141 } 142 143 public Object getTarget() { 144 return target; 145 } 146 147 abstract public MethodDelegate newInstance(Object target); 148 149 public static class Generator extends AbstractClassGenerator { 150 private static final Source SOURCE = new Source(MethodDelegate.class.getName()); 151 private static final Type METHOD_DELEGATE = 152 TypeUtils.parseType("net.sf.cglib.reflect.MethodDelegate"); 153 private static final Signature NEW_INSTANCE = 154 new Signature("newInstance", METHOD_DELEGATE, new Type[]{ Constants.TYPE_OBJECT }); 155 156 private Object target; 157 private Class targetClass; 158 private String methodName; 159 private Class iface; 160 161 public Generator() { 162 super(SOURCE); 163 } 164 165 public void setTarget(Object target) { 166 this.target = target; 167 this.targetClass = target.getClass(); 168 } 169 170 public void setTargetClass(Class targetClass) { 171 this.targetClass = targetClass; 172 } 173 174 public void setMethodName(String methodName) { 175 this.methodName = methodName; 176 } 177 178 public void setInterface(Class iface) { 179 this.iface = iface; 180 } 181 182 protected ClassLoader getDefaultClassLoader() { 183 return targetClass.getClassLoader(); 184 } 185 186 public MethodDelegate create() { 187 setNamePrefix(targetClass.getName()); 188 Object key = KEY_FACTORY.newInstance(targetClass, methodName, iface); 189 return (MethodDelegate)super.create(key); 190 } 191 192 protected Object firstInstance(Class type) { 193 return ((MethodDelegate)ReflectUtils.newInstance(type)).newInstance(target); 194 } 195 196 protected Object nextInstance(Object instance) { 197 return ((MethodDelegate)instance).newInstance(target); 198 } 199 200 public void generateClass(ClassVisitor v) throws NoSuchMethodException { 201 Method proxy = ReflectUtils.findInterfaceMethod(iface); 202 final Method method = targetClass.getMethod(methodName, proxy.getParameterTypes()); 203 if (!proxy.getReturnType().isAssignableFrom(method.getReturnType())) { 204 throw new IllegalArgumentException ("incompatible return types"); 205 } 206 207 MethodInfo methodInfo = ReflectUtils.getMethodInfo(method); 208 209 boolean isStatic = TypeUtils.isStatic(methodInfo.getModifiers()); 210 if ((target == null) ^ isStatic) { 211 throw new IllegalArgumentException ("Static method " + (isStatic ? "not " : "") + "expected"); 212 } 213 214 ClassEmitter ce = new ClassEmitter(v); 215 CodeEmitter e; 216 ce.begin_class(Constants.V1_2, 217 Constants.ACC_PUBLIC, 218 getClassName(), 219 METHOD_DELEGATE, 220 new Type[]{ Type.getType(iface) }, 221 Constants.SOURCE_FILE); 222 ce.declare_field(Constants.PRIVATE_FINAL_STATIC, "eqMethod", Constants.TYPE_STRING, null); 223 EmitUtils.null_constructor(ce); 224 225 MethodInfo proxied = ReflectUtils.getMethodInfo(iface.getDeclaredMethods()[0]); 227 e = EmitUtils.begin_method(ce, proxied, Constants.ACC_PUBLIC); 228 e.load_this(); 229 e.super_getfield("target", Constants.TYPE_OBJECT); 230 e.checkcast(methodInfo.getClassInfo().getType()); 231 e.load_args(); 232 e.invoke(methodInfo); 233 e.return_value(); 234 e.end_method(); 235 236 e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null); 238 e.new_instance_this(); 239 e.dup(); 240 e.dup2(); 241 e.invoke_constructor_this(); 242 e.getfield("eqMethod"); 243 e.super_putfield("eqMethod", Constants.TYPE_STRING); 244 e.load_arg(0); 245 e.super_putfield("target", Constants.TYPE_OBJECT); 246 e.return_value(); 247 e.end_method(); 248 249 e = ce.begin_static(); 251 e.push(methodInfo.getSignature().toString()); 252 e.putfield("eqMethod"); 253 e.return_value(); 254 e.end_method(); 255 256 ce.end_class(); 257 } 258 } 259 } 260 | Popular Tags |