1 16 package net.sf.cglib.reflect; 17 18 import java.lang.reflect.*; 19 import java.util.*; 20 import net.sf.cglib.core.*; 21 import org.objectweb.asm.ClassVisitor; 22 import org.objectweb.asm.MethodVisitor; 23 import org.objectweb.asm.Type; 24 25 abstract public class MulticastDelegate implements Cloneable { 26 protected Object [] targets = {}; 27 28 protected MulticastDelegate() { 29 } 30 31 public List getTargets() { 32 return new ArrayList(Arrays.asList(targets)); 33 } 34 35 abstract public MulticastDelegate add(Object target); 36 37 protected MulticastDelegate addHelper(Object target) { 38 MulticastDelegate copy = newInstance(); 39 copy.targets = new Object [targets.length + 1]; 40 System.arraycopy(targets, 0, copy.targets, 0, targets.length); 41 copy.targets[targets.length] = target; 42 return copy; 43 } 44 45 public MulticastDelegate remove(Object target) { 46 for (int i = targets.length - 1; i >= 0; i--) { 47 if (targets[i].equals(target)) { 48 MulticastDelegate copy = newInstance(); 49 copy.targets = new Object [targets.length - 1]; 50 System.arraycopy(targets, 0, copy.targets, 0, i); 51 System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1); 52 return copy; 53 } 54 } 55 return this; 56 } 57 58 abstract public MulticastDelegate newInstance(); 59 60 public static MulticastDelegate create(Class iface) { 61 Generator gen = new Generator(); 62 gen.setInterface(iface); 63 return gen.create(); 64 } 65 66 public static class Generator extends AbstractClassGenerator { 67 private static final Source SOURCE = new Source(MulticastDelegate.class.getName()); 68 private static final Type MULTICAST_DELEGATE = 69 TypeUtils.parseType("net.sf.cglib.reflect.MulticastDelegate"); 70 private static final Signature NEW_INSTANCE = 71 new Signature("newInstance", MULTICAST_DELEGATE, new Type[0]); 72 private static final Signature ADD_DELEGATE = 73 new Signature("add", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT }); 74 private static final Signature ADD_HELPER = 75 new Signature("addHelper", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT }); 76 77 private Class iface; 78 79 public Generator() { 80 super(SOURCE); 81 } 82 83 protected ClassLoader getDefaultClassLoader() { 84 return iface.getClassLoader(); 85 } 86 87 public void setInterface(Class iface) { 88 this.iface = iface; 89 } 90 91 public MulticastDelegate create() { 92 setNamePrefix(MulticastDelegate.class.getName()); 93 return (MulticastDelegate)super.create(iface.getName()); 94 } 95 96 public void generateClass(ClassVisitor cv) { 97 final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface)); 98 99 ClassEmitter ce = new ClassEmitter(cv); 100 ce.begin_class(Constants.V1_2, 101 Constants.ACC_PUBLIC, 102 getClassName(), 103 MULTICAST_DELEGATE, 104 new Type[]{ Type.getType(iface) }, 105 Constants.SOURCE_FILE); 106 EmitUtils.null_constructor(ce); 107 108 emitProxy(ce, method); 110 111 CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null); 113 e.new_instance_this(); 114 e.dup(); 115 e.invoke_constructor_this(); 116 e.return_value(); 117 e.end_method(); 118 119 e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null); 121 e.load_this(); 122 e.load_arg(0); 123 e.checkcast(Type.getType(iface)); 124 e.invoke_virtual_this(ADD_HELPER); 125 e.return_value(); 126 e.end_method(); 127 128 ce.end_class(); 129 } 130 131 private void emitProxy(ClassEmitter ce, final MethodInfo method) { 132 final CodeEmitter e = EmitUtils.begin_method(ce, method, Constants.ACC_PUBLIC); 133 Type returnType = method.getSignature().getReturnType(); 134 final boolean returns = returnType != Type.VOID_TYPE; 135 Local result = null; 136 if (returns) { 137 result = e.make_local(returnType); 138 e.zero_or_null(returnType); 139 e.store_local(result); 140 } 141 e.load_this(); 142 e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY); 143 final Local result2 = result; 144 EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() { 145 public void processElement(Type type) { 146 e.checkcast(Type.getType(iface)); 147 e.load_args(); 148 e.invoke(method); 149 if (returns) { 150 e.store_local(result2); 151 } 152 } 153 }); 154 if (returns) { 155 e.load_local(result); 156 } 157 e.return_value(); 158 e.end_method(); 159 } 160 161 protected Object firstInstance(Class type) { 162 return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance(); 164 } 165 166 protected Object nextInstance(Object instance) { 167 return ((MulticastDelegate)instance).newInstance(); 168 } 169 } 170 } 171 | Popular Tags |