1 16 package net.sf.cglib.proxy; 17 18 import java.lang.reflect.Constructor ; 19 import java.lang.reflect.Modifier ; 20 import java.util.*; 21 import net.sf.cglib.core.*; 22 import org.objectweb.asm.ClassVisitor; 23 24 25 26 34 abstract public class Mixin { 35 private static final MixinKey KEY_FACTORY = 36 (MixinKey)KeyFactory.create(MixinKey.class, KeyFactory.CLASS_BY_NAME); 37 private static final Map ROUTE_CACHE = Collections.synchronizedMap(new HashMap()); 38 39 public static final int STYLE_INTERFACES = 0; 40 public static final int STYLE_BEANS = 1; 41 public static final int STYLE_EVERYTHING = 2; 42 43 interface MixinKey { 44 public Object newInstance(int style, String [] classes, int[] route); 45 } 46 47 abstract public Mixin newInstance(Object [] delegates); 48 49 55 public static Mixin create(Object [] delegates) { 56 Generator gen = new Generator(); 57 gen.setDelegates(delegates); 58 return gen.create(); 59 } 60 61 67 public static Mixin create(Class [] interfaces, Object [] delegates) { 68 Generator gen = new Generator(); 69 gen.setClasses(interfaces); 70 gen.setDelegates(delegates); 71 return gen.create(); 72 } 73 74 75 public static Mixin createBean(Object [] beans) { 76 77 return createBean(null, beans); 78 79 } 80 86 public static Mixin createBean(ClassLoader loader,Object [] beans) { 87 Generator gen = new Generator(); 88 gen.setStyle(STYLE_BEANS); 89 gen.setDelegates(beans); 90 gen.setClassLoader(loader); 91 return gen.create(); 92 } 93 94 public static class Generator extends AbstractClassGenerator { 95 private static final Source SOURCE = new Source(Mixin.class.getName()); 96 97 private Class [] classes; 98 private Object [] delegates; 99 private int style = STYLE_INTERFACES; 100 101 private int[] route; 102 103 public Generator() { 104 super(SOURCE); 105 } 106 107 protected ClassLoader getDefaultClassLoader() { 108 return classes[0].getClassLoader(); } 110 111 public void setStyle(int style) { 112 switch (style) { 113 case STYLE_INTERFACES: 114 case STYLE_BEANS: 115 case STYLE_EVERYTHING: 116 this.style = style; 117 break; 118 default: 119 throw new IllegalArgumentException ("Unknown mixin style: " + style); 120 } 121 } 122 123 public void setClasses(Class [] classes) { 124 this.classes = classes; 125 } 126 127 public void setDelegates(Object [] delegates) { 128 this.delegates = delegates; 129 } 130 131 public Mixin create() { 132 if (classes == null && delegates == null) { 133 throw new IllegalStateException ("Either classes or delegates must be set"); 134 } 135 switch (style) { 136 case STYLE_INTERFACES: 137 if (classes == null) { 138 Route r = route(delegates); 139 classes = r.classes; 140 route = r.route; 141 } 142 break; 143 case STYLE_BEANS: 144 case STYLE_EVERYTHING: 146 if (classes == null) { 147 classes = ReflectUtils.getClasses(delegates); 148 } else { 149 if (delegates != null) { 150 Class [] temp = ReflectUtils.getClasses(delegates); 151 if (classes.length != temp.length) { 152 throw new IllegalStateException ("Specified classes are incompatible with delegates"); 153 } 154 for (int i = 0; i < classes.length; i++) { 155 if (!classes[i].isAssignableFrom(temp[i])) { 156 throw new IllegalStateException ("Specified class " + classes[i] + " is incompatible with delegate class " + temp[i] + " (index " + i + ")"); 157 } 158 } 159 } 160 } 161 } 162 setNamePrefix(classes[ReflectUtils.findPackageProtected(classes)].getName()); 163 164 return (Mixin)super.create(KEY_FACTORY.newInstance(style, ReflectUtils.getNames( classes ), route)); 165 } 166 167 public void generateClass(ClassVisitor v) { 168 switch (style) { 169 case STYLE_INTERFACES: 170 new MixinEmitter(v, getClassName(), classes, route); 171 break; 172 case STYLE_BEANS: 173 new MixinBeanEmitter(v, getClassName(), classes); 174 break; 175 case STYLE_EVERYTHING: 176 new MixinEverythingEmitter(v, getClassName(), classes); 177 break; 178 } 179 } 180 181 protected Object firstInstance(Class type) { 182 return ((Mixin)ReflectUtils.newInstance(type)).newInstance(delegates); 183 } 184 185 protected Object nextInstance(Object instance) { 186 return ((Mixin)instance).newInstance(delegates); 187 } 188 } 189 190 public static Class [] getClasses(Object [] delegates) { 191 return (Class [])route(delegates).classes.clone(); 192 } 193 194 198 private static Route route(Object [] delegates) { 199 Object key = ClassesKey.create(delegates); 200 Route route = (Route)ROUTE_CACHE.get(key); 201 if (route == null) { 202 ROUTE_CACHE.put(key, route = new Route(delegates)); 203 } 204 return route; 205 } 206 207 private static class Route 208 { 209 private Class [] classes; 210 private int[] route; 211 212 Route(Object [] delegates) { 213 Map map = new HashMap(); 214 ArrayList collect = new ArrayList(); 215 for (int i = 0; i < delegates.length; i++) { 216 Class delegate = delegates[i].getClass(); 217 collect.clear(); 218 ReflectUtils.addAllInterfaces(delegate, collect); 219 for (Iterator it = collect.iterator(); it.hasNext();) { 220 Class iface = (Class )it.next(); 221 if (!map.containsKey(iface)) { 222 map.put(iface, new Integer (i)); 223 } 224 } 225 } 226 classes = new Class [map.size()]; 227 route = new int[map.size()]; 228 int index = 0; 229 for (Iterator it = map.keySet().iterator(); it.hasNext();) { 230 Class key = (Class )it.next(); 231 classes[index] = key; 232 route[index] = ((Integer )map.get(key)).intValue(); 233 index++; 234 } 235 } 236 } 237 } 238 | Popular Tags |