1 54 package org.logicalcobwebs.cglib.proxy; 55 56 import org.logicalcobwebs.cglib.core.*; 57 import java.lang.reflect.Method ; 58 import java.util.*; 59 import org.logicalcobwebs.asm.ClassVisitor; 60 61 93 public class Enhancer extends AbstractClassGenerator 94 { 95 private static final Source SOURCE = new Source(Enhancer.class.getName()); 96 private static final EnhancerKey KEY_FACTORY = 97 (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.CLASS_BY_NAME); 98 99 interface EnhancerKey { 100 public Object newInstance(Class type, 101 Class [] interfaces, 102 CallbackFilter filter, 103 Class [] callbackTypes, 104 boolean useFactory); 105 } 106 107 private Class [] interfaces; 108 private CallbackFilter filter; 109 private Callback[] callbacks; 110 private Class [] callbackTypes; 111 private boolean classOnly; 112 private Class superclass; 113 private Class [] argumentTypes; 114 private Object [] arguments; 115 private boolean useFactory = true; 116 117 124 public Enhancer() { 125 super(SOURCE); 126 } 127 128 137 public void setSuperclass(Class superclass) { 138 if (superclass != null && superclass.isInterface()) { 139 setInterfaces(new Class []{ superclass }); 140 } else if (superclass != null && superclass.equals(Object .class)) { 141 this.superclass = null; 143 } else { 144 this.superclass = superclass; 145 } 146 } 147 148 154 public void setInterfaces(Class [] interfaces) { 155 this.interfaces = interfaces; 156 } 157 158 166 public void setCallbackFilter(CallbackFilter filter) { 167 this.filter = filter; 168 } 169 170 176 public void setCallback(final Callback callback) { 177 setCallbacks(new Callback[]{ callback }); 178 } 179 180 189 public void setCallbacks(Callback[] callbacks) { 190 if (callbacks != null && callbacks.length == 0) { 191 throw new IllegalArgumentException ("Array cannot be empty"); 192 } 193 this.callbacks = callbacks; 194 } 195 196 205 public void setUseFactory(boolean useFactory) { 206 this.useFactory = useFactory; 207 } 208 209 217 public void setCallbackType(Class callbackType) { 218 setCallbackTypes(new Class []{ callbackType }); 219 } 220 221 230 public void setCallbackTypes(Class [] callbackTypes) { 231 if (callbackTypes != null && callbackTypes.length == 0) { 232 throw new IllegalArgumentException ("Array cannot be empty"); 233 } 234 this.callbackTypes = callbackTypes; 235 } 236 237 243 public Object create() { 244 classOnly = false; 245 argumentTypes = null; 246 return createHelper(); 247 } 248 249 258 public Object create(Class [] argumentTypes, Object [] arguments) { 259 classOnly = false; 260 if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) { 261 throw new IllegalArgumentException ("Arguments must be non-null and of equal length"); 262 } 263 this.argumentTypes = argumentTypes; 264 this.arguments = arguments; 265 return createHelper(); 266 } 267 268 276 public Class createClass() { 277 classOnly = true; 278 return (Class )createHelper(); 279 } 280 281 private Object createHelper() { 282 if (classOnly ^ (callbacks == null)) { 283 if (classOnly) { 284 throw new IllegalStateException ("createClass does not accept callbacks"); 285 } else { 286 throw new IllegalStateException ("callbacks are required unless using createClass"); 287 } 288 } 289 if (callbacks == null && callbackTypes == null) { 290 throw new IllegalStateException ("Either callbacks or callback types are always required"); 291 } 292 if (callbacks != null && callbackTypes != null) { 293 if (callbacks.length != callbackTypes.length) { 294 throw new IllegalStateException ("Lengths of callback and callback types array must be the same"); 295 } 296 for (int i = 0; i < callbacks.length; i++) { 297 CallbackUtils.getGenerator(callbackTypes[i]); 299 if (callbacks[i] == null) { 300 throw new IllegalStateException ("Callback cannot be null"); 301 } 302 if (!callbackTypes[i].isAssignableFrom(callbacks[i].getClass())) { 303 throw new IllegalStateException ("Callback " + callbacks[i] + " is not assignable to " + callbackTypes[i]); 304 } 305 } 306 } else if (callbacks != null) { 307 callbackTypes = new Class [callbacks.length]; 308 for (int i = 0; i < callbacks.length; i++) { 309 callbackTypes[i] = CallbackUtils.determineType(callbacks[i]); 310 } 311 } else { 312 for (int i = 0; i < callbackTypes.length; i++) { 313 CallbackUtils.getGenerator(callbackTypes[i]); 315 } 316 } 317 if (filter == null) { 318 if (callbackTypes.length > 1) { 319 throw new IllegalStateException ("Multiple callback types possible but no filter specified"); 320 } 321 filter = CallbackFilter.ALL_ZERO; 322 } 323 324 if (superclass != null) { 325 setNamePrefix(superclass.getName()); 326 } else if (interfaces != null) { 327 setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); 328 } 329 Object key = KEY_FACTORY.newInstance(superclass, interfaces, filter, callbackTypes, useFactory); 330 return super.create(key); 331 } 332 333 protected ClassLoader getDefaultClassLoader() { 334 if (superclass != null) { 335 return superclass.getClassLoader(); 336 } else if (interfaces != null) { 337 return interfaces[0].getClassLoader(); 338 } else { 339 return null; 340 } 341 } 342 343 public void generateClass(ClassVisitor v) throws Exception { 344 new EnhancerEmitter(v, getClassName(), superclass, interfaces, filter, callbackTypes, useFactory); 345 } 346 347 protected Object firstInstance(Class type) throws Exception { 348 if (classOnly) { 349 return type; 350 } else { 351 return createUsingReflection(type); 352 } 353 } 354 355 protected Object nextInstance(Object instance) { 356 Class protoclass = (instance instanceof Class ) ? (Class )instance : instance.getClass(); 357 if (classOnly) { 358 return protoclass; 359 } else if (instance instanceof Factory) { 360 if (argumentTypes != null) { 361 return ((Factory)instance).newInstance(argumentTypes, arguments, callbacks); 362 } else { 363 return ((Factory)instance).newInstance(callbacks); 364 } 365 } else { 366 return createUsingReflection(protoclass); 367 } 368 } 369 370 private Object createUsingReflection(Class type) { 371 EnhancerEmitter.setThreadCallbacks(type, callbacks); 372 if (argumentTypes != null) { 373 return ReflectUtils.newInstance(type, argumentTypes, arguments); 374 } else { 375 return ReflectUtils.newInstance(type); 376 } 377 } 378 379 386 public static Object create(Class type, Callback callback) { 387 Enhancer e = new Enhancer(); 388 e.setSuperclass(type); 389 e.setCallback(callback); 390 return e.create(); 391 } 392 393 401 public static Object create(Class superclass, Class interfaces[], Callback callback) { 402 Enhancer e = new Enhancer(); 403 e.setSuperclass(superclass); 404 e.setInterfaces(interfaces); 405 e.setCallback(callback); 406 return e.create(); 407 } 408 409 418 public static Object create(Class superclass, Class [] interfaces, CallbackFilter filter, Callback[] callbacks) { 419 Enhancer e = new Enhancer(); 420 e.setSuperclass(superclass); 421 e.setInterfaces(interfaces); 422 e.setCallbackFilter(filter); 423 e.setCallbacks(callbacks); 424 return e.create(); 425 } 426 } 427 | Popular Tags |