1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/* 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright 2002,2003,2004 The Apache Software Foundation 3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Licensed under the Apache License, Version 2.0 (the "License"); 5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * you may not use this file except in compliance with the License. 6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You may obtain a copy of the License at 7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * http://www.apache.org/licenses/LICENSE-2.0 9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Unless required by applicable law or agreed to in writing, software 11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * distributed under the License is distributed on an "AS IS" BASIS, 12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * See the License for the specific language governing permissions and 14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * limitations under the License. 15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.cglib.proxy; 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.lang.reflect.InvocationTargetException; 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.lang.reflect.Method; 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.*; 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.ClassVisitor; 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Label; 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type; 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.*; 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/** 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Generates dynamic subclasses to enable method interception. This 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * class started as a substitute for the standard Dynamic Proxy support 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * included with JDK 1.3, but one that allowed the proxies to extend a 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * concrete base class, in addition to implementing interfaces. The dynamically 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * generated subclasses override the non-final methods of the superclass and 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * have hooks which callback to user-defined interceptor 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * implementations. 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The original and most general callback type is the {@link MethodInterceptor}, which 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * in AOP terms enables "around advice"--that is, you can invoke custom code both before 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * and after the invocation of the "super" method. In addition you can modify the 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * arguments before calling the super method, or not call it at all. 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Although <code>MethodInterceptor</code> is generic enough to meet any 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * interception need, it is often overkill. For simplicity and performance, additional 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * specialized callback types, such as {@link LazyLoader} are also available. 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Often a single callback will be used per enhanced class, but you can control 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * which callback is used on a per-method basis with a {@link CallbackFilter}. 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The most common uses of this class are embodied in the static helper methods. For 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * advanced needs, such as customizing the <code>ClassLoader</code> to use, you should create 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * a new instance of <code>Enhancer</code>. Other classes within CGLIB follow a similar pattern. 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * used to explicitly disable this feature. The <code>Factory</code> interface provides an API 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to change the callbacks of an existing object, as well as a faster and easier way to create 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * new instances of the same type. 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * For an almost drop-in replacement for 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>java.lang.reflect.Proxy</code>, see the {@link Proxy} class. 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class Enhancer extends AbstractClassGenerator 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen{ 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final CallbackFilter ALL_ZERO = new CallbackFilter(){ 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public int accept(Method method, List<Method> allMethods) { 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return 0; 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }; 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Source SOURCE = new Source(Enhancer.class.getName()); 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final EnhancerKey KEY_FACTORY = 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen (EnhancerKey)KeyFactory.create(EnhancerKey.class); 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final String BOUND_FIELD = "CGLIB$BOUND"; 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final String THREAD_CALLBACKS_FIELD = "CGLIB$THREAD_CALLBACKS"; 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final String STATIC_CALLBACKS_FIELD = "CGLIB$STATIC_CALLBACKS"; 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS"; 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final String SET_STATIC_CALLBACKS_NAME = "CGLIB$SET_STATIC_CALLBACKS"; 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED"; 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type FACTORY = 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseType("org.mockito.cglib.proxy.Factory"); 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type ILLEGAL_STATE_EXCEPTION = 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseType("IllegalStateException"); 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type ILLEGAL_ARGUMENT_EXCEPTION = 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseType("IllegalArgumentException"); 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type THREAD_LOCAL = 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseType("ThreadLocal"); 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type CALLBACK = 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseType("org.mockito.cglib.proxy.Callback"); 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type CALLBACK_ARRAY = 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type.getType(Callback[].class); 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature CSTRUCT_NULL = 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseConstructor(""); 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature SET_THREAD_CALLBACKS = 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature(SET_THREAD_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY }); 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature SET_STATIC_CALLBACKS = 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature(SET_STATIC_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY }); 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature NEW_INSTANCE = 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK_ARRAY }); 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature MULTIARG_NEW_INSTANCE = 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.TYPE_CLASS_ARRAY, 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.TYPE_OBJECT_ARRAY, 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CALLBACK_ARRAY, 103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature SINGLE_NEW_INSTANCE = 105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK }); 106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature SET_CALLBACK = 107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("setCallback", Type.VOID_TYPE, new Type[]{ Type.INT_TYPE, CALLBACK }); 108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature GET_CALLBACK = 109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("getCallback", CALLBACK, new Type[]{ Type.INT_TYPE }); 110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature SET_CALLBACKS = 111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("setCallbacks", Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY }); 112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature GET_CALLBACKS = 113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("getCallbacks", CALLBACK_ARRAY, new Type[0]); 114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature THREAD_LOCAL_GET = 115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("Object get()"); 116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature THREAD_LOCAL_SET = 117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("void set(Object)"); 118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature BIND_CALLBACKS = 119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("void CGLIB$BIND_CALLBACKS(Object)"); 120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** Internal interface, only public due to ClassLoader issues. */ 122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public interface EnhancerKey { 123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object newInstance(String type, 124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String[] interfaces, 125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CallbackFilter filter, 126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] callbackTypes, 127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean useFactory, 128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean interceptDuringConstruction, 129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Long serialVersionUID); 130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Class[] interfaces; 133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private CallbackFilter filter; 134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Callback[] callbacks; 135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Type[] callbackTypes; 136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private boolean classOnly; 137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Class superclass; 138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Class[] argumentTypes; 139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Object[] arguments; 140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private boolean useFactory = true; 141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Long serialVersionUID; 142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private boolean interceptDuringConstruction = true; 143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Create a new <code>Enhancer</code>. A new <code>Enhancer</code> 146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * object should be used for each generated object, and should not 147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * be shared across threads. To create additional instances of a 148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * generated class, use the <code>Factory</code> interface. 149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see Factory 150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Enhancer() { 152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen super(SOURCE); 153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the class which the generated class will extend. As a convenience, 157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * if the supplied superclass is actually an interface, <code>setInterfaces</code> 158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * will be called with the appropriate argument instead. 159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A non-interface argument must not be declared as final, and must have an 160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * accessible constructor. 161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param superclass class to extend or interface to implement 162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setInterfaces(Class[]) 163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setSuperclass(Class superclass) { 165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (superclass != null && superclass.isInterface()) { 166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setInterfaces(new Class[]{ superclass }); 167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (superclass != null && superclass.equals(Object.class)) { 168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // affects choice of ClassLoader 169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.superclass = null; 170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.superclass = superclass; 172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the interfaces to implement. The <code>Factory</code> interface will 177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * always be implemented regardless of what is specified here. 178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param interfaces array of interfaces to implement, or null 179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see Factory 180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setInterfaces(Class[] interfaces) { 182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.interfaces = interfaces; 183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the {@link CallbackFilter} used to map the generated class' methods 187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to a particular callback index. 188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * New object instances will always use the same mapping, but may use different 189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * actual callback objects. 190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param filter the callback filter to use when generating a new class 191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setCallbacks 192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setCallbackFilter(CallbackFilter filter) { 194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.filter = filter; 195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the single {@link Callback} to use. 200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Ignored if you use {@link #createClass}. 201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callback the callback to use for all methods 202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setCallbacks 203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setCallback(final Callback callback) { 205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setCallbacks(new Callback[]{ callback }); 206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the array of callbacks to use. 210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Ignored if you use {@link #createClass}. 211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You must use a {@link CallbackFilter} to specify the index into this 212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * array for each method in the proxied class. 213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callbacks the callback array 214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setCallbackFilter 215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setCallback 216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setCallbacks(Callback[] callbacks) { 218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (callbacks != null && callbacks.length == 0) { 219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Array cannot be empty"); 220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.callbacks = callbacks; 222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set whether the enhanced object instances should implement 226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the {@link Factory} interface. 227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This was added for tools that need for proxies to be more 228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * indistinguishable from their targets. Also, in some cases it may 229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * be necessary to disable the <code>Factory</code> interface to 230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * prevent code from changing the underlying callbacks. 231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param useFactory whether to implement <code>Factory</code>; default is <code>true</code> 232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setUseFactory(boolean useFactory) { 234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.useFactory = useFactory; 235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set whether methods called from within the proxy's constructer 239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * will be intercepted. The default value is true. Unintercepted methods 240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * will call the method of the proxy's base class, if it exists. 241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param interceptDuringConstruction whether to intercept methods called from the constructor 242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setInterceptDuringConstruction(boolean interceptDuringConstruction) { 244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.interceptDuringConstruction = interceptDuringConstruction; 245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the single type of {@link Callback} to use. 249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This may be used instead of {@link #setCallback} when calling 250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link #createClass}, since it may not be possible to have 251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * an array of actual callback instances. 252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callbackType the type of callback to use for all methods 253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setCallbackTypes 254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setCallbackType(Class callbackType) { 256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setCallbackTypes(new Class[]{ callbackType }); 257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Set the array of callback types to use. 261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This may be used instead of {@link #setCallbacks} when calling 262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link #createClass}, since it may not be possible to have 263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * an array of actual callback instances. 264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You must use a {@link CallbackFilter} to specify the index into this 265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * array for each method in the proxied class. 266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callbackTypes the array of callback types 267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setCallbackTypes(Class[] callbackTypes) { 269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (callbackTypes != null && callbackTypes.length == 0) { 270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Array cannot be empty"); 271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.callbackTypes = CallbackInfo.determineTypes(callbackTypes); 273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Generate a new class if necessary and uses the specified 277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * callbacks (if any) to create a new object instance. 278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Uses the no-arg constructor of the superclass. 279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return a new instance 280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object create() { 282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen classOnly = false; 283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen argumentTypes = null; 284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return createHelper(); 285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Generate a new class if necessary and uses the specified 289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * callbacks (if any) to create a new object instance. 290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Uses the constructor of the superclass matching the <code>argumentTypes</code> 291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * parameter, with the given arguments. 292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param argumentTypes constructor signature 293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param arguments compatible wrapped arguments to pass to constructor 294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return a new instance 295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object create(Class[] argumentTypes, Object[] arguments) { 297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen classOnly = false; 298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) { 299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Arguments must be non-null and of equal length"); 300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.argumentTypes = argumentTypes; 302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.arguments = arguments; 303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return createHelper(); 304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Generate a new class if necessary and return it without creating a new instance. 308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This ignores any callbacks that have been set. 309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * To create a new instance you will have to use reflection, and methods 310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * called during the constructor will not be intercepted. To avoid this problem, 311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * use the multi-arg <code>create</code> method. 312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #create(Class[], Object[]) 313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Class createClass() { 315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen classOnly = true; 316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return (Class)createHelper(); 317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Insert a static serialVersionUID field into the generated class. 321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param sUID the field value, or null to avoid generating field. 322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setSerialVersionUID(Long sUID) { 324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen serialVersionUID = sUID; 325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void validate() { 328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classOnly ^ (callbacks == null)) { 329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classOnly) { 330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("createClass does not accept callbacks"); 331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Callbacks are required"); 333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classOnly && (callbackTypes == null)) { 336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Callback types are required"); 337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (callbacks != null && callbackTypes != null) { 339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (callbacks.length != callbackTypes.length) { 340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Lengths of callback and callback types array must be the same"); 341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] check = CallbackInfo.determineTypes(callbacks); 343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < check.length; i++) { 344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!check[i].equals(callbackTypes[i])) { 345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Callback " + check[i] + " is not assignable to " + callbackTypes[i]); 346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (callbacks != null) { 349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callbackTypes = CallbackInfo.determineTypes(callbacks); 350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (filter == null) { 352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (callbackTypes.length > 1) { 353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Multiple callback types possible but no filter specified"); 354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen filter = ALL_ZERO; 356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (interfaces != null) { 358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < interfaces.length; i++) { 359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (interfaces[i] == null) { 360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Interfaces cannot be null"); 361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!interfaces[i].isInterface()) { 363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException(interfaces[i] + " is not an interface"); 364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Object createHelper() { 370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen validate(); 371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (superclass != null) { 372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setNamePrefix(superclass.getName()); 373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (interfaces != null) { 374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); 375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, 377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ReflectUtils.getNames(interfaces), 378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen filter, 379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callbackTypes, 380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen useFactory, 381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen interceptDuringConstruction, 382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen serialVersionUID)); 383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected ClassLoader getDefaultClassLoader() { 386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (superclass != null) { 387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return superclass.getClassLoader(); 388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (interfaces != null) { 389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return interfaces[0].getClassLoader(); 390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return null; 392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Signature rename(Signature sig, int index) { 396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Signature("CGLIB$" + sig.getName() + "$" + index, 397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen sig.getDescriptor()); 398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Finds all of the methods that will be extended by an 402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Enhancer-generated class using the specified superclass and 403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * interfaces. This can be useful in building a list of Callback 404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * objects. The methods are added to the end of the given list. Due 405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to the subclassing nature of the classes generated by Enhancer, 406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the methods are guaranteed to be non-static, non-final, and 407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * non-private. Each method signature will only occur once, even if 408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * it occurs in multiple classes. 409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param superclass the class that will be extended, or null 410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param interfaces the list of interfaces that will be implemented, or null 411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param methods the list into which to copy the applicable methods 412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void getMethods(Class superclass, Class[] interfaces, List methods) 414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getMethods(superclass, interfaces, methods, null, null); 416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) 419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ReflectUtils.addAllMethods(superclass, methods); 421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List target = (interfaceMethods != null) ? interfaceMethods : methods; 422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (interfaces != null) { 423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < interfaces.length; i++) { 424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (interfaces[i] != Factory.class) { 425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ReflectUtils.addAllMethods(interfaces[i], target); 426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (interfaceMethods != null) { 430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (forcePublic != null) { 431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen forcePublic.addAll(MethodWrapper.createSet(interfaceMethods)); 432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen methods.addAll(interfaceMethods); 434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_STATIC)); 436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)); 437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CollectionUtils.filter(methods, new DuplicatesPredicate()); 438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_FINAL)); 439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void generateClass(ClassVisitor v) throws Exception { 442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Class sc = (superclass == null) ? Object.class : superclass; 443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isFinal(sc.getModifiers())) 445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Cannot subclass final class " + sc); 446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors())); 447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen filterConstructors(sc, constructors); 448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Order is very important: must add superclass, then 450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // its superclass chain, then each interface and 451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // its superinterfaces. 452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List actualMethods = new ArrayList(); 453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List interfaceMethods = new ArrayList(); 454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Set forcePublic = new HashSet(); 455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic); 456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List methods = CollectionUtils.transform(actualMethods, new Transformer() { 458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Method method = (Method)value; 460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int modifiers = Constants.ACC_FINAL 461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen | (method.getModifiers() 462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen & ~Constants.ACC_ABSTRACT 463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen & ~Constants.ACC_NATIVE 464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen & ~Constants.ACC_SYNCHRONIZED); 465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (forcePublic.contains(MethodWrapper.create(method))) { 466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC; 467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ReflectUtils.getMethodInfo(method, modifiers); 469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ClassEmitter e = new ClassEmitter(v); 473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.begin_class(Constants.V1_2, 474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.ACC_PUBLIC, 475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getClassName(), 476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type.getType(sc), 477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen (useFactory ? 478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : 479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.getTypes(interfaces)), 480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.SOURCE_FILE); 481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance()); 482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null); 484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!interceptDuringConstruction) { 485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null); 486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null); 488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null); 489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (serialVersionUID != null) { 490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID); 491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < callbackTypes.length; i++) { 494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null); 495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitMethods(e, methods, actualMethods); 498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitConstructors(e, constructorInfo); 499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitSetThreadCallbacks(e); 500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitSetStaticCallbacks(e); 501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitBindCallbacks(e); 502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (useFactory) { 504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] keys = getCallbackKeys(); 505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitNewInstanceCallbacks(e); 506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitNewInstanceCallback(e); 507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitNewInstanceMultiarg(e, constructorInfo); 508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitGetCallback(e, keys); 509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitSetCallback(e, keys); 510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitGetCallbacks(e); 511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitSetCallbacks(e); 512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_class(); 515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Filter the list of constructors from the superclass. The 519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * constructors which remain will be included in the generated 520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * class. The default implementation is to filter out all private 521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * constructors, but subclasses may extend Enhancer to override this 522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * behavior. 523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param sc the superclass 524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param constructors the list of all declared constructors from the superclass 525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @throws IllegalArgumentException if there are no non-private constructors 526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected void filterConstructors(Class sc, List constructors) { 528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CollectionUtils.filter(constructors, new VisibilityPredicate(sc, true)); 529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (constructors.size() == 0) 530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("No visible constructors in " + sc); 531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Object firstInstance(Class type) throws Exception { 534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classOnly) { 535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return type; 536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return createUsingReflection(type); 538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Object nextInstance(Object instance) { 542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); 543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (classOnly) { 544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return protoclass; 545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (instance instanceof Factory) { 546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (argumentTypes != null) { 547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((Factory)instance).newInstance(argumentTypes, arguments, callbacks); 548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((Factory)instance).newInstance(callbacks); 550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return createUsingReflection(protoclass); 553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Call this method to register the {@link Callback} array to use before 558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * creating a new instance of the generated class via reflection. If you are using 559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * an instance of <code>Enhancer</code> or the {@link Factory} interface to create 560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * new instances, this method is unnecessary. Its primary use is for when you want to 561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * cache and reuse a generated class yourself, and the generated class does 562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <i>not</i> implement the {@link Factory} interface. 563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Note that this method only registers the callbacks on the current thread. 565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * If you want to register callbacks for instances created by multiple threads, 566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * use {@link #registerStaticCallbacks}. 567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The registered callbacks are overwritten and subsequently cleared 569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * when calling any of the <code>create</code> methods (such as 570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link #create}), or any {@link Factory} <code>newInstance</code> method. 571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Otherwise they are <i>not</i> cleared, and you should be careful to set them 572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * back to <code>null</code> after creating new instances via reflection if 573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * memory leakage is a concern. 574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param generatedClass a class previously created by {@link Enhancer} 575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callbacks the array of callbacks to use when instances of the generated 576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * class are created 577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #setUseFactory 578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void registerCallbacks(Class generatedClass, Callback[] callbacks) { 580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setThreadCallbacks(generatedClass, callbacks); 581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Similar to {@link #registerCallbacks}, but suitable for use 585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * when multiple threads will be creating instances of the generated class. 586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The thread-level callbacks will always override the static callbacks. 587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Static callbacks are never cleared. 588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param generatedClass a class previously created by {@link Enhancer} 589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callbacks the array of callbacks to use when instances of the generated 590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * class are created 591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void registerStaticCallbacks(Class generatedClass, Callback[] callbacks) { 593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setCallbacksHelper(generatedClass, callbacks, SET_STATIC_CALLBACKS_NAME); 594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Determine if a class was generated using <code>Enhancer</code>. 598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param type any class 599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return whether the class was generated using <code>Enhancer</code> 600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static boolean isEnhanced(Class type) { 602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getCallbacksSetter(type, SET_THREAD_CALLBACKS_NAME); 604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return true; 605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (NoSuchMethodException e) { 606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return false; 607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void setThreadCallbacks(Class type, Callback[] callbacks) { 611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME); 612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName) { 615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // TODO: optimize 616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Method setter = getCallbacksSetter(type, methodName); 618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setter.invoke(null, new Object[]{ callbacks }); 619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (NoSuchMethodException e) { 620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException(type + " is not an enhanced class"); 621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (IllegalAccessException e) { 622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new CodeGenerationException(e); 623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (InvocationTargetException e) { 624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new CodeGenerationException(e); 625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException { 629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return type.getDeclaredMethod(methodName, new Class[]{ Callback[].class }); 630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Object createUsingReflection(Class type) { 633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setThreadCallbacks(type, callbacks); 634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try{ 635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (argumentTypes != null) { 637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ReflectUtils.newInstance(type, argumentTypes, arguments); 639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ReflectUtils.newInstance(type); 643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }finally{ 646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // clear thread callbacks to allow them to be gc'd 647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setThreadCallbacks(type, null); 648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Helper method to create an intercepted object. 653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * For finer control over the generated instance, use a new instance of <code>Enhancer</code> 654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instead of this static method. 655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param type class to extend or interface to implement 656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callback the callback to use for all methods 657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static Object create(Class type, Callback callback) { 659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Enhancer e = new Enhancer(); 660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setSuperclass(type); 661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setCallback(callback); 662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return e.create(); 663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Helper method to create an intercepted object. 667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * For finer control over the generated instance, use a new instance of <code>Enhancer</code> 668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instead of this static method. 669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param type class to extend or interface to implement 670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param interfaces array of interfaces to implement, or null 671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callback the callback to use for all methods 672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static Object create(Class superclass, Class interfaces[], Callback callback) { 674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Enhancer e = new Enhancer(); 675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setSuperclass(superclass); 676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setInterfaces(interfaces); 677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setCallback(callback); 678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return e.create(); 679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Helper method to create an intercepted object. 683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * For finer control over the generated instance, use a new instance of <code>Enhancer</code> 684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instead of this static method. 685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param type class to extend or interface to implement 686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param interfaces array of interfaces to implement, or null 687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param filter the callback filter to use when generating a new class 688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callbacks callback implementations to use for the enhanced object 689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) { 691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Enhancer e = new Enhancer(); 692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setSuperclass(superclass); 693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setInterfaces(interfaces); 694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setCallbackFilter(filter); 695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setCallbacks(callbacks); 696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return e.create(); 697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitConstructors(ClassEmitter ce, List constructors) { 700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean seenNull = false; 701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (Iterator it = constructors.iterator(); it.hasNext();) { 702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen MethodInfo constructor = (MethodInfo)it.next(); 703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC); 704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_args(); 707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Signature sig = constructor.getSignature(); 708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen seenNull = seenNull || sig.getDescriptor().equals("()V"); 709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.super_invoke_constructor(sig); 710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(BIND_CALLBACKS); 711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!interceptDuringConstruction) { 712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(1); 714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(CONSTRUCTED_FIELD); 715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!classOnly && !seenNull && arguments == null) 720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Superclass has no null constructors but no arguments were given"); 721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int[] getCallbackKeys() { 724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] keys = new int[callbackTypes.length]; 725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < callbackTypes.length; i++) { 726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen keys[i] = i; 727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return keys; 729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitGetCallback(ClassEmitter ce, int[] keys) { 732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACK, null); 733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(BIND_CALLBACKS); 735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.process_switch(keys, new ProcessSwitchCallback() { 738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(int key, Label end) { 739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(getCallbackField(key)); 740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() { 743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); // stack height 744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aconst_null(); 745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitSetCallback(ClassEmitter ce, int[] keys) { 752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null); 753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.process_switch(keys, new ProcessSwitchCallback() { 755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(int key, Label end) { 756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(1); 758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.checkcast(callbackTypes[key]); 759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(getCallbackField(key)); 760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() { 763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // TODO: error? 764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitSetCallbacks(ClassEmitter ce) { 771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACKS, null); 772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < callbackTypes.length; i++) { 775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup2(); 776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aaload(i); 777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.checkcast(callbackTypes[i]); 778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(getCallbackField(i)); 779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitGetCallbacks(ClassEmitter ce) { 785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACKS, null); 786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(BIND_CALLBACKS); 788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(callbackTypes.length); 790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.newarray(CALLBACK); 791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < callbackTypes.length; i++) { 792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(i); 794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(getCallbackField(i)); 796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aastore(); 797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitNewInstanceCallbacks(ClassEmitter ce) { 803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null); 804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(SET_THREAD_CALLBACKS); 806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitCommonNewInstance(e); 807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitCommonNewInstance(CodeEmitter e) { 810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance_this(); 811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor_this(); 813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aconst_null(); 814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(SET_THREAD_CALLBACKS); 815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitNewInstanceCallback(ClassEmitter ce) { 820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SINGLE_NEW_INSTANCE, null); 821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (callbackTypes.length) { 822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 0: 823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // TODO: make sure Callback is null 824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case 1: 826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // for now just make a new array; TODO: optimize 827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(1); 828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.newarray(CALLBACK); 829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(0); 831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aastore(); 833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(SET_THREAD_CALLBACKS); 834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.throw_exception(ILLEGAL_STATE_EXCEPTION, "More than one callback object required"); 837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitCommonNewInstance(e); 839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitNewInstanceMultiarg(ClassEmitter ce, List constructors) { 842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null); 843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(2); 844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(SET_THREAD_CALLBACKS); 845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance_this(); 846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() { 849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(Object key, Label end) { 850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen MethodInfo constructor = (MethodInfo)key; 851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type types[] = constructor.getSignature().getArgumentTypes(); 852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < types.length; i++) { 853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(1); 854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(i); 855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aaload(); 856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.unbox(types[i]); 857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor_this(constructor.getSignature()); 859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() { 862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found"); 863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aconst_null(); 866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(SET_THREAD_CALLBACKS); 867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) { 872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes); 873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Map groups = new HashMap(); 875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map indexes = new HashMap(); 876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map originalModifiers = new HashMap(); 877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map positions = CollectionUtils.getIndexMap(methods); 878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Iterator it1 = methods.iterator(); 880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null; 881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (it1.hasNext()) { 883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen MethodInfo method = (MethodInfo)it1.next(); 884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Method actualMethod = (it2 != null) ? (Method)it2.next() : null; 885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int index = filter.accept(actualMethod, actualMethods); 886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (index >= callbackTypes.length) { 887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index); 888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen originalModifiers.put(method, new Integer((actualMethod != null) ? actualMethod.getModifiers() : method.getModifiers())); 890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen indexes.put(method, new Integer(index)); 891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List group = (List)groups.get(generators[index]); 892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (group == null) { 893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen groups.put(generators[index], group = new ArrayList(methods.size())); 894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen group.add(method); 896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Set seenGen = new HashSet(); 899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter se = ce.getStaticHook(); 900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen se.new_instance(THREAD_LOCAL); 901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen se.dup(); 902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL); 903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen se.putfield(THREAD_CALLBACKS_FIELD); 904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Object[] state = new Object[1]; 906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CallbackGenerator.Context context = new CallbackGenerator.Context() { 907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public ClassLoader getClassLoader() { 908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return Enhancer.this.getClassLoader(); 909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public int getOriginalModifiers(MethodInfo method) { 911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((Integer)originalModifiers.get(method)).intValue(); 912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public int getIndex(MethodInfo method) { 914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((Integer)indexes.get(method)).intValue(); 915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void emitCallback(CodeEmitter e, int index) { 917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen emitCurrentCallback(e, index); 918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 919674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Signature getImplSignature(MethodInfo method) { 920674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return rename(method.getSignature(), ((Integer)positions.get(method)).intValue()); 921674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 922674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) { 923674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = EmitUtils.begin_method(ce, method); 924674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!interceptDuringConstruction && 925674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen !TypeUtils.isAbstract(method.getModifiers())) { 926674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label constructed = e.make_label(); 927674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 928674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(CONSTRUCTED_FIELD); 929674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_jump(e.NE, constructed); 930674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 931674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_args(); 932674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.super_invoke(); 933674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 934674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(constructed); 935674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 936674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return e; 937674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 938674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }; 939674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < callbackTypes.length; i++) { 940674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CallbackGenerator gen = generators[i]; 941674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!seenGen.contains(gen)) { 942674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen seenGen.add(gen); 943674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final List fmethods = (List)groups.get(gen); 944674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (fmethods != null) { 945674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 946674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen gen.generate(ce, context, fmethods); 947674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen gen.generateStatic(se, context, fmethods); 948674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (RuntimeException x) { 949674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw x; 950674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Exception x) { 951674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new CodeGenerationException(x); 952674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 953674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 954674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 955674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 956674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen se.return_value(); 957674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen se.end_method(); 958674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 959674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 960674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitSetThreadCallbacks(ClassEmitter ce) { 961674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 962674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen SET_THREAD_CALLBACKS, 963674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen null); 964674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(THREAD_CALLBACKS_FIELD); 965674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 966674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); 967674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 968674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 969674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 970674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 971674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitSetStaticCallbacks(ClassEmitter ce) { 972674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, 973674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen SET_STATIC_CALLBACKS, 974674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen null); 975674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 976674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(STATIC_CALLBACKS_FIELD); 977674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 978674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 979674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 980674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 981674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitCurrentCallback(CodeEmitter e, int index) { 982674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 983674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(getCallbackField(index)); 984674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 985674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 986674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnonnull(end); 987674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); // stack height 988674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 989674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static_this(BIND_CALLBACKS); 990674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 991674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(getCallbackField(index)); 992674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 993674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 994674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 995674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void emitBindCallbacks(ClassEmitter ce) { 996674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.PRIVATE_FINAL_STATIC, 997674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen BIND_CALLBACKS, 998674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen null); 999674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Local me = e.make_local(); 1000674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 1001674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.checkcast_this(); 1002674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.store_local(me); 1003674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1004674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 1005674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(me); 1006674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(BOUND_FIELD); 1007674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_jump(e.NE, end); 1008674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(me); 1009674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(1); 1010674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(BOUND_FIELD); 1011674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1012674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(THREAD_CALLBACKS_FIELD); 1013674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET); 1014674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 1015674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label found_callback = e.make_label(); 1016674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnonnull(found_callback); 1017674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 1018674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1019674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(STATIC_CALLBACKS_FIELD); 1020674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 1021674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnonnull(found_callback); 1022674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 1023674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 1024674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1025674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(found_callback); 1026674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.checkcast(CALLBACK_ARRAY); 1027674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(me); 1028674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 1029674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = callbackTypes.length - 1; i >= 0; i--) { 1030674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (i != 0) { 1031674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup2(); 1032674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1033674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aaload(i); 1034674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.checkcast(callbackTypes[i]); 1035674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(getCallbackField(i)); 1036674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1037674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1038674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 1039674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 1040674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 1041674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1042674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 1043674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static String getCallbackField(int index) { 1044674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return "CGLIB$CALLBACK_" + index; 1045674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 1046674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 1047