1 54 package org.logicalcobwebs.cglib.proxy; 55 56 import java.lang.reflect.Constructor ; 57 import java.lang.reflect.Modifier ; 58 import java.util.*; 59 import org.logicalcobwebs.cglib.core.*; 60 import org.logicalcobwebs.asm.ClassVisitor; 61 62 70 abstract public class Mixin { 71 private static final MixinKey KEY_FACTORY = 72 (MixinKey)KeyFactory.create(MixinKey.class, KeyFactory.CLASS_BY_NAME); 73 private static final Map ROUTE_CACHE = Collections.synchronizedMap(new HashMap()); 74 75 interface MixinKey { 76 public Object newInstance(Class [] classes, int[] route); 77 } 78 79 abstract public Mixin newInstance(Object [] delegates); 80 81 87 public static Mixin create(Object [] delegates) { 88 Generator gen = new Generator(); 89 gen.setDelegates(delegates); 90 return gen.create(); 91 } 92 93 99 public static Mixin create(Class [] interfaces, Object [] delegates) { 100 Generator gen = new Generator(); 101 gen.setClasses(interfaces); 102 gen.setDelegates(delegates); 103 return gen.create(); 104 } 105 106 112 public static Mixin createBean(Object [] beans) { 113 Generator gen = new Generator(); 114 gen.setAsBeans(true); 115 gen.setDelegates(beans); 116 return gen.create(); 117 } 118 119 public static class Generator extends AbstractClassGenerator { 120 private static final Source SOURCE = new Source(Mixin.class.getName()); 121 122 private Class [] classes; 123 private Object [] delegates; 124 private int[] route; 125 private boolean asBeans; 126 127 public Generator() { 128 super(SOURCE); 129 } 130 131 protected ClassLoader getDefaultClassLoader() { 132 return delegates[0].getClass().getClassLoader(); } 134 135 public void setAsBeans(boolean asBeans) { 136 this.asBeans = asBeans; 137 } 138 139 public void setClasses(Class [] classes) { 140 this.classes = classes; 141 } 142 143 public void setDelegates(Object [] delegates) { 144 this.delegates = delegates; 145 } 146 147 public void setRoute(int[] route) { 148 this.route = route; 149 } 150 151 public Mixin create() { 152 if (classes == null) { 153 if (asBeans) { 154 classes = ReflectUtils.getClasses(delegates); 155 route = null; 156 } else { 157 Route r = route(delegates); 158 classes = r.classes; 159 route = r.route; 160 } 161 } 162 setNamePrefix(classes[ReflectUtils.findPackageProtected(classes)].getName()); 163 return (Mixin)super.create(KEY_FACTORY.newInstance(classes, route)); 164 } 165 166 public void generateClass(ClassVisitor v) { 167 if (asBeans) { 168 new MixinBeanEmitter(v, getClassName(), classes); 169 } else { 170 new MixinEmitter(v, getClassName(), classes, route); 171 } 172 } 173 174 protected Object firstInstance(Class type) { 175 return ((Mixin)ReflectUtils.newInstance(type)).newInstance(delegates); 176 } 177 178 protected Object nextInstance(Object instance) { 179 return ((Mixin)instance).newInstance(delegates); 180 } 181 } 182 183 public static Class [] getClasses(Object [] delegates) { 184 return (Class [])route(delegates).classes.clone(); 185 } 186 187 public static int[] getRoute(Object [] delegates) { 188 return (int[])route(delegates).route.clone(); 189 } 190 191 private static Route route(Object [] delegates) { 192 Object key = ClassesKey.create(delegates); 193 Route route = (Route)ROUTE_CACHE.get(key); 194 if (route == null) { 195 ROUTE_CACHE.put(key, route = new Route(delegates)); 196 } 197 return route; 198 } 199 200 private static class Route 201 { 202 private Class [] classes; 203 private int[] route; 204 205 Route(Object [] delegates) { 206 Map map = new HashMap(); 207 ArrayList collect = new ArrayList(); 208 for (int i = 0; i < delegates.length; i++) { 209 Class delegate = delegates[i].getClass(); 210 collect.clear(); 211 collectAllInterfaces(delegate, collect); 212 for (Iterator it = collect.iterator(); it.hasNext();) { 213 Class iface = (Class )it.next(); 214 if (!map.containsKey(iface)) { 215 map.put(iface, new Integer (i)); 216 } 217 } 218 } 219 classes = new Class [map.size()]; 220 route = new int[map.size()]; 221 int index = 0; 222 for (Iterator it = map.keySet().iterator(); it.hasNext();) { 223 Class key = (Class )it.next(); 224 classes[index] = key; 225 route[index] = ((Integer )map.get(key)).intValue(); 226 index++; 227 } 228 } 229 } 230 231 private static void collectAllInterfaces(Class type, List list) { 232 if (!type.equals(Object .class)) { 233 list.addAll(Arrays.asList(type.getInterfaces())); 234 collectAllInterfaces(type.getSuperclass(), list); 235 } 236 } 237 } 238 | Popular Tags |