1 16 17 package net.sf.cglib.core; 18 19 import java.lang.reflect.Method ; 20 import org.objectweb.asm.ClassVisitor; 21 import org.objectweb.asm.Label; 22 import org.objectweb.asm.Type; 23 24 53 abstract public class KeyFactory { 54 private static final Signature GET_NAME = 55 TypeUtils.parseSignature("String getName()"); 56 private static final Signature GET_CLASS = 57 TypeUtils.parseSignature("Class getClass()"); 58 private static final Signature HASH_CODE = 59 TypeUtils.parseSignature("int hashCode()"); 60 private static final Signature EQUALS = 61 TypeUtils.parseSignature("boolean equals(Object)"); 62 private static final Signature TO_STRING = 63 TypeUtils.parseSignature("String toString()"); 64 private static final Signature APPEND_STRING = 65 TypeUtils.parseSignature("StringBuffer append(String)"); 66 private static final Type KEY_FACTORY = 67 TypeUtils.parseType("net.sf.cglib.core.KeyFactory"); 68 69 private final static int PRIMES[] = { 71 11, 73, 179, 331, 72 521, 787, 1213, 1823, 73 2609, 3691, 5189, 7247, 74 10037, 13931, 19289, 26627, 75 36683, 50441, 69403, 95401, 76 131129, 180179, 247501, 340057, 77 467063, 641371, 880603, 1209107, 78 1660097, 2279161, 3129011, 4295723, 79 5897291, 8095873, 11114263, 15257791, 80 20946017, 28754629, 39474179, 54189869, 81 74391461, 102123817, 140194277, 192456917, 82 264202273, 362693231, 497900099, 683510293, 83 938313161, 1288102441, 1768288259 }; 84 85 86 public static final Customizer CLASS_BY_NAME = new Customizer() { 87 public void customize(CodeEmitter e, Type type) { 88 if (type.equals(Constants.TYPE_CLASS)) { 89 e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); 90 } 91 } 92 }; 93 94 public static final Customizer OBJECT_BY_CLASS = new Customizer() { 95 public void customize(CodeEmitter e, Type type) { 96 e.invoke_virtual(Constants.TYPE_OBJECT, GET_CLASS); 97 } 98 }; 99 100 protected KeyFactory() { 101 } 102 103 public static KeyFactory create(Class keyInterface) { 104 return create(keyInterface, null); 105 } 106 107 public static KeyFactory create(Class keyInterface, Customizer customizer) { 108 return create(keyInterface.getClassLoader(), keyInterface, customizer); 109 } 110 111 public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) { 112 Generator gen = new Generator(); 113 gen.setInterface(keyInterface); 114 gen.setCustomizer(customizer); 115 gen.setClassLoader(loader); 116 return gen.create(); 117 } 118 119 public static class Generator extends AbstractClassGenerator { 120 private static final Source SOURCE = new Source(KeyFactory.class.getName()); 121 private Class keyInterface; 122 private Customizer customizer; 123 private int constant; 124 private int multiplier; 125 126 public Generator() { 127 super(SOURCE); 128 } 129 130 protected ClassLoader getDefaultClassLoader() { 131 return keyInterface.getClassLoader(); 132 } 133 134 public void setCustomizer(Customizer customizer) { 135 this.customizer = customizer; 136 } 137 138 public void setInterface(Class keyInterface) { 139 this.keyInterface = keyInterface; 140 } 141 142 public KeyFactory create() { 143 setNamePrefix(keyInterface.getName()); 144 return (KeyFactory)super.create(keyInterface.getName()); 145 } 146 147 public void setHashConstant(int constant) { 148 this.constant = constant; 149 } 150 151 public void setHashMultiplier(int multiplier) { 152 this.multiplier = multiplier; 153 } 154 155 protected Object firstInstance(Class type) { 156 return ReflectUtils.newInstance(type); 157 } 158 159 protected Object nextInstance(Object instance) { 160 return instance; 161 } 162 163 public void generateClass(ClassVisitor v) { 164 ClassEmitter ce = new ClassEmitter(v); 165 166 Method newInstance = ReflectUtils.findNewInstance(keyInterface); 167 if (!newInstance.getReturnType().equals(Object .class)) { 168 throw new IllegalArgumentException ("newInstance method must return Object"); 169 } 170 171 Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes()); 172 ce.begin_class(Constants.V1_2, 173 Constants.ACC_PUBLIC, 174 getClassName(), 175 KEY_FACTORY, 176 new Type[]{ Type.getType(keyInterface) }, 177 Constants.SOURCE_FILE); 178 EmitUtils.null_constructor(ce); 179 EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance)); 180 181 int seed = 0; 182 CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, 183 TypeUtils.parseConstructor(parameterTypes), 184 null); 185 e.load_this(); 186 e.super_invoke_constructor(); 187 e.load_this(); 188 for (int i = 0; i < parameterTypes.length; i++) { 189 seed += parameterTypes[i].hashCode(); 190 ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL, 191 getFieldName(i), 192 parameterTypes[i], 193 null); 194 e.dup(); 195 e.load_arg(i); 196 e.putfield(getFieldName(i)); 197 } 198 e.return_value(); 199 e.end_method(); 200 201 e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null); 203 int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)]; 204 int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)]; 205 e.push(hc); 206 for (int i = 0; i < parameterTypes.length; i++) { 207 e.load_this(); 208 e.getfield(getFieldName(i)); 209 EmitUtils.hash_code(e, parameterTypes[i], hm, customizer); 210 } 211 e.return_value(); 212 e.end_method(); 213 214 e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null); 216 Label fail = e.make_label(); 217 e.load_arg(0); 218 e.instance_of_this(); 219 e.if_jump(e.EQ, fail); 220 for (int i = 0; i < parameterTypes.length; i++) { 221 e.load_this(); 222 e.getfield(getFieldName(i)); 223 e.load_arg(0); 224 e.checkcast_this(); 225 e.getfield(getFieldName(i)); 226 EmitUtils.not_equals(e, parameterTypes[i], fail, customizer); 227 } 228 e.push(1); 229 e.return_value(); 230 e.mark(fail); 231 e.push(0); 232 e.return_value(); 233 e.end_method(); 234 235 e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null); 237 e.new_instance(Constants.TYPE_STRING_BUFFER); 238 e.dup(); 239 e.invoke_constructor(Constants.TYPE_STRING_BUFFER); 240 for (int i = 0; i < parameterTypes.length; i++) { 241 if (i > 0) { 242 e.push(", "); 243 e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); 244 } 245 e.load_this(); 246 e.getfield(getFieldName(i)); 247 EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizer); 248 } 249 e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING); 250 e.return_value(); 251 e.end_method(); 252 253 ce.end_class(); 254 } 255 256 private String getFieldName(int arg) { 257 return "FIELD_" + arg; 258 } 259 } 260 } 261 | Popular Tags |