[Proxool-cvs] proxool/src/java/org/logicalcobwebs/cglib/proxy Callback.java,NONE,1.1 CallbackFilter.
UNMAINTAINED!
Brought to you by:
billhorsman
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/proxy In directory sc8-pr-cvs1:/tmp/cvs-serv25673/src/java/org/logicalcobwebs/cglib/proxy Added Files: Callback.java CallbackFilter.java CallbackGenerator.java CallbackUtils.java Dispatcher.java DispatcherGenerator.java Enhancer.java EnhancerEmitter.java Factory.java FixedValue.java FixedValueGenerator.java InvocationHandler.java InvocationHandlerGenerator.java LazyLoader.java LazyLoaderGenerator.java MethodInterceptor.java MethodInterceptorGenerator.java MethodProxy.java Mixin.java MixinBeanEmitter.java MixinEmitter.java NoOp.java NoOpGenerator.java Proxy.java UndeclaredThrowableException.java Log Message: Repackaged Cglib project --- NEW FILE: Callback.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; /** * All callback interfaces used by {@link Enhancer} extend this interface. * @see MethodInterceptor * @see NoOp * @see LazyLoader * @see Dispatcher * @see InvocationHandler * @see FixedValue */ public interface Callback { } --- NEW FILE: CallbackFilter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.lang.reflect.Method; /** * Map methods of subclasses generated by {@link Enhancer} to a particular * callback. The type of the callbacks chosen for each method affects * the bytecode generated for that method in the subclass, and cannot * change for the life of the class. */ public interface CallbackFilter { static final CallbackFilter ALL_ZERO = new CallbackFilter() { public int accept(Method method) { return 0; } public String toString() { return "ALL_ZERO"; } public int hashCode() { return 999; } }; /** * Map a method to a callback. * @param method the intercepted method * @return the index into the array of callbacks (as specified by {@link Enhancer#setCallbacks}) to use for the method, */ int accept(Method method); /** * The <code>CallbackFilter</code> in use affects which cached class * the <code>Enhancer</code> will use, so this is a reminder that * you should correctly implement <code>equals</code> and * <code>hashCode</code> for custom <code>CallbackFilter</code> * implementations in order to improve performance. */ boolean equals(Object o); } --- NEW FILE: CallbackGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.lang.reflect.Method; import java.util.Iterator; import org.logicalcobwebs.cglib.core.ClassEmitter; import org.logicalcobwebs.cglib.core.CodeEmitter; interface CallbackGenerator { void generate(ClassEmitter e, Context context) throws Exception; void generateStatic(CodeEmitter e, Context context) throws Exception; interface Context { Iterator getMethods(); int getIndex(Method method); void emitCallback(CodeEmitter e, int index); int getModifiers(Method method); String getUniqueName(Method method); } } --- NEW FILE: CallbackUtils.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import org.logicalcobwebs.asm.Type; class CallbackUtils { private CallbackUtils() { } static Class determineType(Callback callback) { Class test = typeHelper(callback, null, NoOp.class); test = typeHelper(callback, test, MethodInterceptor.class); test = typeHelper(callback, test, InvocationHandler.class); test = typeHelper(callback, test, LazyLoader.class); test = typeHelper(callback, test, Dispatcher.class); test = typeHelper(callback, test, FixedValue.class); if (test == null) { throw new IllegalStateException("Unknown callback " + callback.getClass()); } return test; } private static Class typeHelper(Callback callback, Class cur, Class callbackType) { if (callback == null) { throw new IllegalStateException("Callback is null"); } if (callbackType.isAssignableFrom(callback.getClass())) { if (cur != null) { throw new IllegalStateException("Callback implements both " + cur + " and " + callbackType + "; use setCallbackTypes to distinguish"); } return callbackType; } else { return cur; } } static CallbackGenerator getGenerator(Class type) { if (type.equals(NoOp.class)) { return NoOpGenerator.INSTANCE; } else if (type.equals(MethodInterceptor.class)) { return MethodInterceptorGenerator.INSTANCE; } else if (type.equals(InvocationHandler.class)) { return InvocationHandlerGenerator.INSTANCE; } else if (type.equals(LazyLoader.class)) { return LazyLoaderGenerator.INSTANCE; } else if (type.equals(Dispatcher.class)) { return DispatcherGenerator.INSTANCE; } else if (type.equals(FixedValue.class)) { return FixedValueGenerator.INSTANCE; } else { throw new IllegalStateException("Unknown callback " + type); } } } --- NEW FILE: Dispatcher.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; /** * Dispatching {@link Enhancer} callback. This is identical to the * {@link LazyLoader} interface but needs to be separate so that <code>Enhancer</code> * knows which type of code to generate. */ public interface Dispatcher extends Callback { /** * Return the object which the original method invocation should * be dispatched. This method is called for <b>every</b> method invocation. * @return an object that can invoke the method */ Object loadObject() throws Exception; } --- NEW FILE: DispatcherGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.Type; class DispatcherGenerator implements CallbackGenerator { public static final DispatcherGenerator INSTANCE = new DispatcherGenerator(); private static final Type DISPATCHER = TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.Dispatcher"); private static final Signature LOAD_OBJECT = TypeUtils.parseSignature("Object loadObject()"); public void generate(ClassEmitter ce, final Context context) { for (Iterator it = context.getMethods(); it.hasNext();) { Method method = (Method)it.next(); if (Modifier.isProtected(method.getModifiers())) { // ignore protected methods } else { CodeEmitter e = ce.begin_method(context.getModifiers(method), ReflectUtils.getSignature(method), ReflectUtils.getExceptionTypes(method), null); context.emitCallback(e, context.getIndex(method)); e.invoke_interface(DISPATCHER, LOAD_OBJECT); e.checkcast(Type.getType(method.getDeclaringClass())); e.load_args(); e.invoke(method); e.return_value(); e.end_method(); } } } public void generateStatic(CodeEmitter e, Context context) { } } --- NEW FILE: Enhancer.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import org.logicalcobwebs.cglib.core.*; import java.lang.reflect.Method; import java.util.*; import org.logicalcobwebs.asm.ClassVisitor; /** * Generates dynamic subclasses to enable method interception. This * class started as a substitute for the standard Dynamic Proxy support * included with JDK 1.3, but one that allowed the proxies to extend a * concrete base class, in addition to implementing interfaces. The dynamically * generated subclasses override the non-final methods of the superclass and * have hooks which callback to user-defined interceptor * implementations. * <p> * The original and most general callback type is the {@link MethodInterceptor}, which * in AOP terms enables "around advice"--that is, you can invoke custom code both before * and after the invocation of the "super" method. In addition you can modify the * arguments before calling the super method, or not call it at all. * <p> * Although <code>MethodInterceptor</code> is generic enough to meet any * interception need, it is often overkill. For simplicity and performance, additional * specialized callback types, such as {@link LazyLoader} are also available. * Often a single callback will be used per enhanced class, but you can control * which callback is used on a per-method basis with a {@link CallbackFilter}. * <p> * The most common uses of this class are embodied in the static helper methods. For * advanced needs, such as customizing the <code>ClassLoader</code> to use, you should create * a new instance of <code>Enhancer</code>. Other classes within CGLIB follow a similar pattern. * <p> * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is * used to explicitly disable this feature. The <code>Factory</code> interface provides an API * to change the callbacks of an existing object, as well as a faster and easier way to create * new instances of the same type. * <p> * For an almost drop-in replacement for * <code>java.lang.reflect.Proxy</code>, see the {@link Proxy} class. */ public class Enhancer extends AbstractClassGenerator { private static final Source SOURCE = new Source(Enhancer.class.getName()); private static final EnhancerKey KEY_FACTORY = (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.CLASS_BY_NAME); interface EnhancerKey { public Object newInstance(Class type, Class[] interfaces, CallbackFilter filter, Class[] callbackTypes, boolean useFactory); } private Class[] interfaces; private CallbackFilter filter; private Callback[] callbacks; private Class[] callbackTypes; private boolean classOnly; private Class superclass; private Class[] argumentTypes; private Object[] arguments; private boolean useFactory = true; /** * Create a new <code>Enhancer</code>. A new <code>Enhancer</code> * object should be used for each generated object, and should not * be shared across threads. To create additional instances of a * generated class, use the <code>Factory</code> interface. * @see Factory */ public Enhancer() { super(SOURCE); } /** * Set the class which the generated class will extend. As a convenience, * if the supplied superclass is actually an interface, <code>setInterfaces</code> * will be called with the appropriate argument instead. * A non-interface argument must not be declared as final, and must have an * accessible constructor. * @param superclass class to extend or interface to implement * @see #setInterfaces(Class[]) */ public void setSuperclass(Class superclass) { if (superclass != null && superclass.isInterface()) { setInterfaces(new Class[]{ superclass }); } else if (superclass != null && superclass.equals(Object.class)) { // affects choice of ClassLoader this.superclass = null; } else { this.superclass = superclass; } } /** * Set the interfaces to implement. The <code>Factory</code> interface will * always be implemented regardless of what is specified here. * @param interfaces array of interfaces to implement, or null * @see Factory */ public void setInterfaces(Class[] interfaces) { this.interfaces = interfaces; } /** * Set the {@link CallbackFilter} used to map the generated class' methods * to a particular callback index. * New object instances will always use the same mapping, but may use different * actual callback objects. * @param filter the callback filter to use when generating a new class * @see #setCallbacks */ public void setCallbackFilter(CallbackFilter filter) { this.filter = filter; } /** * Set the single {@link Callback} to use. * Ignored if you use {@link #createClass}. * @param callback the callback to use for all methods * @see #setCallbacks */ public void setCallback(final Callback callback) { setCallbacks(new Callback[]{ callback }); } /** * Set the array of callbacks to use. * Ignored if you use {@link #createClass}. * You must use a {@link CallbackFilter} to specify the index into this * array for each method in the proxied class. * @param callbacks the callback array * @see #setCallbackFilter * @see #setCallback */ public void setCallbacks(Callback[] callbacks) { if (callbacks != null && callbacks.length == 0) { throw new IllegalArgumentException("Array cannot be empty"); } this.callbacks = callbacks; } /** * Set whether the enhanced object instances should implement * the {@link Factory} interface. * This was added for tools that need for proxies to be more * indistinguishable from their targets. Also, in some cases it may * be necessary to disable the <code>Factory</code> interface to * prevent code from changing the underlying callbacks. * @param useFactory whether to implement <code>Factory</code>; default is <code>true</code> */ public void setUseFactory(boolean useFactory) { this.useFactory = useFactory; } /** * Set the single type of {@link Callback} to use. * This may be used instead of {@link #setCallback} when calling * {@link #createClass}, since it may not be possible to have * an array of actual callback instances. * @param callbackType the type of callback to use for all methods * @see #setCallbackTypes */ public void setCallbackType(Class callbackType) { setCallbackTypes(new Class[]{ callbackType }); } /** * Set the array of callback types to use. * This may be used instead of {@link #setCallbacks} when calling * {@link #createClass}, since it may not be possible to have * an array of actual callback instances. * You must use a {@link CallbackFilter} to specify the index into this * array for each method in the proxied class. * @param callbackTypes the array of callback types */ public void setCallbackTypes(Class[] callbackTypes) { if (callbackTypes != null && callbackTypes.length == 0) { throw new IllegalArgumentException("Array cannot be empty"); } this.callbackTypes = callbackTypes; } /** * Generate a new class if necessary and uses the specified * callbacks (if any) to create a new object instance. * Uses the no-arg constructor of the superclass. * @return a new instance */ public Object create() { classOnly = false; argumentTypes = null; return createHelper(); } /** * Generate a new class if necessary and uses the specified * callbacks (if any) to create a new object instance. * Uses the constructor of the superclass matching the <code>argumentTypes</code> * parameter, with the given arguments. * @param argumentTypes constructor signature * @param arguments compatible wrapped arguments to pass to constructor * @return a new instance */ public Object create(Class[] argumentTypes, Object[] arguments) { classOnly = false; if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) { throw new IllegalArgumentException("Arguments must be non-null and of equal length"); } this.argumentTypes = argumentTypes; this.arguments = arguments; return createHelper(); } /** * Generate a new class if necessary and return it without creating a new instance. * This ignores any callbacks that have been set. * To create a new instance you will have to use reflection, and methods * called during the constructor will not be intercepted. To avoid this problem, * use the multi-arg <code>create</code> method. * @see #create(Class[], Object[]) */ public Class createClass() { classOnly = true; return (Class)createHelper(); } private Object createHelper() { if (classOnly ^ (callbacks == null)) { if (classOnly) { throw new IllegalStateException("createClass does not accept callbacks"); } else { throw new IllegalStateException("callbacks are required unless using createClass"); } } if (callbacks == null && callbackTypes == null) { throw new IllegalStateException("Either callbacks or callback types are always required"); } if (callbacks != null && callbackTypes != null) { if (callbacks.length != callbackTypes.length) { throw new IllegalStateException("Lengths of callback and callback types array must be the same"); } for (int i = 0; i < callbacks.length; i++) { // make sure all classes are callbacks CallbackUtils.getGenerator(callbackTypes[i]); if (callbacks[i] == null) { throw new IllegalStateException("Callback cannot be null"); } if (!callbackTypes[i].isAssignableFrom(callbacks[i].getClass())) { throw new IllegalStateException("Callback " + callbacks[i] + " is not assignable to " + callbackTypes[i]); } } } else if (callbacks != null) { callbackTypes = new Class[callbacks.length]; for (int i = 0; i < callbacks.length; i++) { callbackTypes[i] = CallbackUtils.determineType(callbacks[i]); } } else { for (int i = 0; i < callbackTypes.length; i++) { // make sure all classes are callbacks CallbackUtils.getGenerator(callbackTypes[i]); } } if (filter == null) { if (callbackTypes.length > 1) { throw new IllegalStateException("Multiple callback types possible but no filter specified"); } filter = CallbackFilter.ALL_ZERO; } if (superclass != null) { setNamePrefix(superclass.getName()); } else if (interfaces != null) { setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); } Object key = KEY_FACTORY.newInstance(superclass, interfaces, filter, callbackTypes, useFactory); return super.create(key); } protected ClassLoader getDefaultClassLoader() { if (superclass != null) { return superclass.getClassLoader(); } else if (interfaces != null) { return interfaces[0].getClassLoader(); } else { return null; } } public void generateClass(ClassVisitor v) throws Exception { new EnhancerEmitter(v, getClassName(), superclass, interfaces, filter, callbackTypes, useFactory); } protected Object firstInstance(Class type) throws Exception { if (classOnly) { return type; } else { return createUsingReflection(type); } } protected Object nextInstance(Object instance) { Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); if (classOnly) { return protoclass; } else if (instance instanceof Factory) { if (argumentTypes != null) { return ((Factory)instance).newInstance(argumentTypes, arguments, callbacks); } else { return ((Factory)instance).newInstance(callbacks); } } else { return createUsingReflection(protoclass); } } private Object createUsingReflection(Class type) { EnhancerEmitter.setThreadCallbacks(type, callbacks); if (argumentTypes != null) { return ReflectUtils.newInstance(type, argumentTypes, arguments); } else { return ReflectUtils.newInstance(type); } } /** * Helper method to create an intercepted object. * For finer control over the generated instance, use a new instance of <code>Enhancer</code> * instead of this static method. * @param type class to extend or interface to implement * @param callback the callback to use for all methods */ public static Object create(Class type, Callback callback) { Enhancer e = new Enhancer(); e.setSuperclass(type); e.setCallback(callback); return e.create(); } /** * Helper method to create an intercepted object. * For finer control over the generated instance, use a new instance of <code>Enhancer</code> * instead of this static method. * @param type class to extend or interface to implement * @param interfaces array of interfaces to implement, or null * @param callback the callback to use for all methods */ public static Object create(Class superclass, Class interfaces[], Callback callback) { Enhancer e = new Enhancer(); e.setSuperclass(superclass); e.setInterfaces(interfaces); e.setCallback(callback); return e.create(); } /** * Helper method to create an intercepted object. * For finer control over the generated instance, use a new instance of <code>Enhancer</code> * instead of this static method. * @param type class to extend or interface to implement * @param interfaces array of interfaces to implement, or null * @param filter the callback filter to use when generating a new class * @param callbacks callback implementations to use for the enhanced object */ public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) { Enhancer e = new Enhancer(); e.setSuperclass(superclass); e.setInterfaces(interfaces); e.setCallbackFilter(filter); e.setCallbacks(callbacks); return e.create(); } } --- NEW FILE: EnhancerEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.proxy; import java.io.ObjectStreamException; import java.lang.reflect.*; import java.util.*; import org.logicalcobwebs.cglib.core.*; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.Label; import org.logicalcobwebs.asm.Type; class EnhancerEmitter extends ClassEmitter { private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED"; private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS"; private static final Type ILLEGAL_STATE_EXCEPTION = TypeUtils.parseType("IllegalStateException"); private static final Type ILLEGAL_ARGUMENT_EXCEPTION = TypeUtils.parseType("IllegalArgumentException"); private static final Type THREAD_LOCAL = TypeUtils.parseType("ThreadLocal"); private static final Type FACTORY = TypeUtils.parseType("org.logicalcobwebs.cglib.proxy.Factory"); private static final Signature CSTRUCT_NULL = TypeUtils.parseConstructor(""); private static final Signature SET_THREAD_CALLBACKS = TypeUtils.parseSignature("void " + SET_THREAD_CALLBACKS_NAME + "(org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature MULTIARG_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(Class[], Object[], org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature SINGLE_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(org.logicalcobwebs.cglib.proxy.Callback)"); private static final Signature COPY_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance()"); private static final Signature COPY_MULTIARG_NEW_INSTANCE = TypeUtils.parseSignature("Object newInstance(Class[], Object[])"); private static final Signature SET_CALLBACK = TypeUtils.parseSignature("void setCallback(int, org.logicalcobwebs.cglib.proxy.Callback)"); private static final Signature GET_CALLBACK = TypeUtils.parseSignature("org.logicalcobwebs.cglib.proxy.Callback getCallback(int)"); private static final Signature SET_CALLBACKS = TypeUtils.parseSignature("void setCallbacks(org.logicalcobwebs.cglib.proxy.Callback[])"); private static final Signature THREAD_LOCAL_GET = TypeUtils.parseSignature("Object get()"); private static final Signature THREAD_LOCAL_SET = TypeUtils.parseSignature("void set(Object)"); private Class[] callbackTypes; public EnhancerEmitter(ClassVisitor v, String className, Class superclass, Class[] interfaces, CallbackFilter filter, Class[] callbackTypes, boolean useFactory) throws Exception { super(v); if (superclass == null) { superclass = Object.class; } this.callbackTypes = callbackTypes; begin_class(Constants.ACC_PUBLIC, className, Type.getType(superclass), (useFactory ? TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : TypeUtils.getTypes(interfaces)), Constants.SOURCE_FILE); List clist = new ArrayList(Arrays.asList(superclass.getDeclaredConstructors())); CollectionUtils.filter(clist, new VisibilityPredicate(superclass, true)); if (clist.size() == 0) { throw new IllegalArgumentException("No visible constructors in " + superclass); } Constructor[] constructors = (Constructor[])clist.toArray(new Constructor[clist.size()]); // Order is very important: must add superclass, then // its superclass chain, then each interface and // its superinterfaces. List methods = new ArrayList(); ReflectUtils.addAllMethods(superclass, methods); List interfaceMethods = new ArrayList(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (interfaces[i] != Factory.class) { ReflectUtils.addAllMethods(interfaces[i], interfaceMethods); } } } Set forcePublic = MethodWrapper.createSet(interfaceMethods); methods.addAll(interfaceMethods); CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)); CollectionUtils.filter(methods, new DuplicatesPredicate()); removeFinal(methods); Map groups = new HashMap(); Map indexes = new HashMap(); for (Iterator it = methods.iterator(); it.hasNext();) { Method method = (Method)it.next(); int index = filter.accept(method); if (index >= callbackTypes.length) { throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index); } indexes.put(method, new Integer(index)); Object gen = CallbackUtils.getGenerator(callbackTypes[index]); List group = (List)groups.get(gen); if (group == null) { groups.put(gen, group = new ArrayList(methods.size())); } group.add(method); } declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null, null); emitMethods(groups, indexes, forcePublic); emitConstructors(constructors); emitSetThreadCallbacks(); if (useFactory) { int[] keys = getCallbackKeys(); emitNewInstanceCallbacks(); emitNewInstanceCallback(); emitNewInstanceMultiarg(constructors); emitNewInstanceCopy(); emitNewInstanceMultiargCopy(constructors); emitGetCallback(keys); emitSetCallback(keys); emitSetCallbacks(); } end_class(); } static void setThreadCallbacks(Class type, Callback[] callbacks) { // TODO: optimize try { Method setter = type.getDeclaredMethod(SET_THREAD_CALLBACKS_NAME, new Class[]{ Callback[].class }); setter.invoke(null, new Object[]{ callbacks }); } catch (NoSuchMethodException e) { throw new IllegalArgumentException(type + " is not an enhanced class"); } catch (IllegalAccessException e) { throw new CodeGenerationException(e); } catch (InvocationTargetException e) { throw new CodeGenerationException(e); } } private void emitConstructors(Constructor[] constructors) { for (int i = 0; i < constructors.length; i++) { Signature sig = ReflectUtils.getSignature(constructors[i]); CodeEmitter e = begin_method(Constants.ACC_PUBLIC, sig, ReflectUtils.getExceptionTypes(constructors[i]), null); e.load_this(); e.dup(); e.load_args(); e.super_invoke_constructor(sig); e.push(1); e.putfield(CONSTRUCTED_FIELD); for (int j = 0; j < callbackTypes.length; j++) { e.load_this(); e.dup(); e.getfield(getThreadLocal(j)); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET); e.checkcast(Type.getType(callbackTypes[j])); e.putfield(getCallbackField(j)); // clear thread-locals; TODO: test! e.getfield(getThreadLocal(j)); e.aconst_null(); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); } e.return_value(); e.end_method(); } } private int[] getCallbackKeys() { int[] keys = new int[callbackTypes.length]; for (int i = 0; i < callbackTypes.length; i++) { keys[i] = i; } return keys; } private void emitGetCallback(int[] keys) { final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_CALLBACK, null, null); e.load_this(); e.load_arg(0); e.process_switch(keys, new ProcessSwitchCallback() { public void processCase(int key, Label end) { e.getfield(getCallbackField(key)); e.goTo(end); } public void processDefault() { e.pop(); // stack height e.aconst_null(); } }); e.return_value(); e.end_method(); } private void emitSetCallback(int[] keys) { final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null, null); e.load_this(); e.load_arg(1); e.dup(); e.load_arg(0); e.process_switch(keys, new ProcessSwitchCallback() { public void processCase(int key, Label end) { // we set thread locals too in case this method is called from within constructor (as Proxy does) e.getfield(getThreadLocal(key)); e.swap(); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); e.checkcast(Type.getType(callbackTypes[key])); e.putfield(getCallbackField(key)); e.goTo(end); } public void processDefault() { // stack height e.pop2(); e.pop(); } }); e.return_value(); e.end_method(); } private void emitSetCallbacks() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_CALLBACKS, null, null); emitSetThreadCallbacks(e); e.load_this(); e.load_arg(0); for (int i = 0; i < callbackTypes.length; i++) { e.dup2(); e.aaload(i); e.checkcast(Type.getType(callbackTypes[i])); e.putfield(getCallbackField(i)); } e.return_value(); e.end_method(); } private void emitNewInstanceCallbacks() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null, null); e.load_arg(0); e.invoke_static_this(SET_THREAD_CALLBACKS); emitCommonNewInstance(e); } private void emitNewInstanceCopy() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, COPY_NEW_INSTANCE, null, null); emitCopyCallbacks(e); emitCommonNewInstance(e); } private void emitCopyCallbacks(CodeEmitter e) { for (int i = 0; i < callbackTypes.length; i++) { e.getfield(getThreadLocal(i)); e.load_this(); e.getfield(getCallbackField(i)); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); } } private void emitCommonNewInstance(CodeEmitter e) { e.new_instance_this(); e.dup(); e.invoke_constructor_this(); e.return_value(); e.end_method(); } private void emitNewInstanceCallback() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SINGLE_NEW_INSTANCE, null, null); switch (callbackTypes.length) { case 0: // TODO: make sure Callback is null break; case 1: e.getfield(getThreadLocal(0)); e.load_arg(0); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); break; default: e.throw_exception(ILLEGAL_STATE_EXCEPTION, "More than one callback object required"); } emitCommonNewInstance(e); } private void emitNewInstanceMultiarg(Constructor[] constructors) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null, null); e.load_arg(2); e.invoke_static_this(SET_THREAD_CALLBACKS); emitCommonMultiarg(constructors, e); } private void emitNewInstanceMultiargCopy(Constructor[] constructors) { CodeEmitter e = begin_method(Constants.ACC_PUBLIC, COPY_MULTIARG_NEW_INSTANCE, null, null); emitCopyCallbacks(e); emitCommonMultiarg(constructors, e); } private void emitCommonMultiarg(Constructor[] constructors, final CodeEmitter e) { e.new_instance_this(); e.dup(); e.load_arg(0); EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() { public void processCase(Object key, Label end) { Constructor constructor = (Constructor)key; Type types[] = TypeUtils.getTypes(constructor.getParameterTypes()); for (int i = 0; i < types.length; i++) { e.load_arg(1); e.push(i); e.aaload(); e.unbox(types[i]); } e.invoke_constructor_this(ReflectUtils.getSignature(constructor)); e.goTo(end); } public void processDefault() { e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found"); } }); e.return_value(); e.end_method(); } private void emitMethods(Map groups, final Map indexes, final Set forcePublic) throws Exception { for (int i = 0; i < callbackTypes.length; i++) { declare_field(Constants.ACC_PRIVATE, getCallbackField(i), Type.getType(callbackTypes[i]), null, null); declare_field(Constants.PRIVATE_FINAL_STATIC, getThreadLocal(i), THREAD_LOCAL, null, null); } Set seenGen = new HashSet(); CodeEmitter e = begin_static(); for (int i = 0; i < callbackTypes.length; i++) { e.new_instance(THREAD_LOCAL); e.dup(); e.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL); e.putfield(getThreadLocal(i)); CallbackGenerator gen = CallbackUtils.getGenerator(callbackTypes[i]); if (!seenGen.contains(gen)) { seenGen.add(gen); final List fmethods = (List)groups.get(gen); CallbackGenerator.Context context = new CallbackGenerator.Context() { public Iterator getMethods() { return fmethods.iterator(); } public int getIndex(Method method) { return ((Integer)indexes.get(method)).intValue(); } public void emitCallback(CodeEmitter e, int index) { emitCurrentCallback(e, index); } public int getModifiers(Method method) { int modifiers = Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED); if (forcePublic.contains(MethodWrapper.create(method))) { modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC; } return modifiers; } // TODO: this is probably slow public String getUniqueName(Method method) { return method.getName() + "_" + fmethods.indexOf(method); } }; gen.generate(this, context); gen.generateStatic(e, context); } } e.return_value(); e.end_method(); } private void emitSetThreadCallbacks() { CodeEmitter e = begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, SET_THREAD_CALLBACKS, null, null); emitSetThreadCallbacks(e); e.return_value(); e.end_method(); } private void emitSetThreadCallbacks(CodeEmitter e) { for (int i = 0; i < callbackTypes.length; i++) { e.getfield(getThreadLocal(i)); e.load_arg(0); e.aaload(i); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); } } private void emitCurrentCallback(CodeEmitter e, int index) { e.load_this(); e.getfield(getCallbackField(index)); e.dup(); Label end = e.make_label(); e.ifnonnull(end); e.load_this(); e.getfield(CONSTRUCTED_FIELD); e.if_jump(e.NE, end); e.pop(); e.getfield(getThreadLocal(index)); e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET); e.checkcast(Type.getType(callbackTypes[index])); e.mark(end); } private static String getCallbackField(int index) { return "CGLIB$CALLBACK_" + index; } private static String getThreadLocal(int index) { return "CGLIB$TL_CALLBACK_" + index; } private static void removeFinal(List list) { CollectionUtils.filter(list, new Predicate() { public boolean evaluate(Object arg) { return !Modifier.isFinal(((Method)arg).getModifiers()); } }); } } --- NEW FILE: Factory.java --- /* *... [truncated message content] |