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