Source Code Cross Referenced for Enhancer.java in  » Byte-Code » cglib » net » sf » cglib » proxy » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Byte Code » cglib » net.sf.cglib.proxy 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002,2003,2004 The Apache Software Foundation
0003:         *
0004:         *  Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         *  Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package net.sf.cglib.proxy;
0017:
0018:        import java.lang.reflect.Constructor;
0019:        import java.lang.reflect.InvocationTargetException;
0020:        import java.lang.reflect.Method;
0021:        import java.util.*;
0022:        import net.sf.cglib.core.*;
0023:        import org.objectweb.asm.Attribute;
0024:        import org.objectweb.asm.ClassVisitor;
0025:        import org.objectweb.asm.Type;
0026:        import org.objectweb.asm.Label;
0027:
0028:        /**
0029:         * Generates dynamic subclasses to enable method interception. This
0030:         * class started as a substitute for the standard Dynamic Proxy support
0031:         * included with JDK 1.3, but one that allowed the proxies to extend a
0032:         * concrete base class, in addition to implementing interfaces. The dynamically
0033:         * generated subclasses override the non-final methods of the superclass and
0034:         * have hooks which callback to user-defined interceptor
0035:         * implementations.
0036:         * <p>
0037:         * The original and most general callback type is the {@link MethodInterceptor}, which
0038:         * in AOP terms enables "around advice"--that is, you can invoke custom code both before
0039:         * and after the invocation of the "super" method. In addition you can modify the
0040:         * arguments before calling the super method, or not call it at all.
0041:         * <p>
0042:         * Although <code>MethodInterceptor</code> is generic enough to meet any
0043:         * interception need, it is often overkill. For simplicity and performance, additional
0044:         * specialized callback types, such as {@link LazyLoader} are also available.
0045:         * Often a single callback will be used per enhanced class, but you can control
0046:         * which callback is used on a per-method basis with a {@link CallbackFilter}.
0047:         * <p>
0048:         * The most common uses of this class are embodied in the static helper methods. For
0049:         * advanced needs, such as customizing the <code>ClassLoader</code> to use, you should create
0050:         * a new instance of <code>Enhancer</code>. Other classes within CGLIB follow a similar pattern.
0051:         * <p>
0052:         * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is
0053:         * used to explicitly disable this feature. The <code>Factory</code> interface provides an API
0054:         * to change the callbacks of an existing object, as well as a faster and easier way to create
0055:         * new instances of the same type.
0056:         * <p>
0057:         * For an almost drop-in replacement for
0058:         * <code>java.lang.reflect.Proxy</code>, see the {@link Proxy} class.
0059:         */
0060:        public class Enhancer extends AbstractClassGenerator {
0061:            private static final CallbackFilter ALL_ZERO = new CallbackFilter() {
0062:                public int accept(Method method) {
0063:                    return 0;
0064:                }
0065:            };
0066:
0067:            private static final Source SOURCE = new Source(Enhancer.class
0068:                    .getName());
0069:            private static final EnhancerKey KEY_FACTORY = (EnhancerKey) KeyFactory
0070:                    .create(EnhancerKey.class);
0071:
0072:            private static final String BOUND_FIELD = "CGLIB$BOUND";
0073:            private static final String THREAD_CALLBACKS_FIELD = "CGLIB$THREAD_CALLBACKS";
0074:            private static final String STATIC_CALLBACKS_FIELD = "CGLIB$STATIC_CALLBACKS";
0075:            private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS";
0076:            private static final String SET_STATIC_CALLBACKS_NAME = "CGLIB$SET_STATIC_CALLBACKS";
0077:            private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED";
0078:
0079:            private static final Type FACTORY = TypeUtils
0080:                    .parseType("net.sf.cglib.proxy.Factory");
0081:            private static final Type ILLEGAL_STATE_EXCEPTION = TypeUtils
0082:                    .parseType("IllegalStateException");
0083:            private static final Type ILLEGAL_ARGUMENT_EXCEPTION = TypeUtils
0084:                    .parseType("IllegalArgumentException");
0085:            private static final Type THREAD_LOCAL = TypeUtils
0086:                    .parseType("ThreadLocal");
0087:            private static final Type CALLBACK = TypeUtils
0088:                    .parseType("net.sf.cglib.proxy.Callback");
0089:            private static final Type CALLBACK_ARRAY = TypeUtils
0090:                    .parseType("net.sf.cglib.proxy.Callback[]");
0091:            private static final Signature CSTRUCT_NULL = TypeUtils
0092:                    .parseConstructor("");
0093:            private static final Signature SET_THREAD_CALLBACKS = new Signature(
0094:                    SET_THREAD_CALLBACKS_NAME, Type.VOID_TYPE,
0095:                    new Type[] { CALLBACK_ARRAY });
0096:            private static final Signature SET_STATIC_CALLBACKS = new Signature(
0097:                    SET_STATIC_CALLBACKS_NAME, Type.VOID_TYPE,
0098:                    new Type[] { CALLBACK_ARRAY });
0099:            private static final Signature NEW_INSTANCE = new Signature(
0100:                    "newInstance", Constants.TYPE_OBJECT,
0101:                    new Type[] { CALLBACK_ARRAY });
0102:            private static final Signature MULTIARG_NEW_INSTANCE = new Signature(
0103:                    "newInstance", Constants.TYPE_OBJECT, new Type[] {
0104:                            Constants.TYPE_CLASS_ARRAY,
0105:                            Constants.TYPE_OBJECT_ARRAY, CALLBACK_ARRAY, });
0106:            private static final Signature SINGLE_NEW_INSTANCE = new Signature(
0107:                    "newInstance", Constants.TYPE_OBJECT,
0108:                    new Type[] { CALLBACK });
0109:            private static final Signature SET_CALLBACK = new Signature(
0110:                    "setCallback", Type.VOID_TYPE, new Type[] { Type.INT_TYPE,
0111:                            CALLBACK });
0112:            private static final Signature GET_CALLBACK = new Signature(
0113:                    "getCallback", CALLBACK, new Type[] { Type.INT_TYPE });
0114:            private static final Signature SET_CALLBACKS = new Signature(
0115:                    "setCallbacks", Type.VOID_TYPE,
0116:                    new Type[] { CALLBACK_ARRAY });
0117:            private static final Signature GET_CALLBACKS = new Signature(
0118:                    "getCallbacks", CALLBACK_ARRAY, new Type[0]);
0119:            private static final Signature THREAD_LOCAL_GET = TypeUtils
0120:                    .parseSignature("Object get()");
0121:            private static final Signature THREAD_LOCAL_SET = TypeUtils
0122:                    .parseSignature("void set(Object)");
0123:            private static final Signature BIND_CALLBACKS = TypeUtils
0124:                    .parseSignature("void CGLIB$BIND_CALLBACKS(Object)");
0125:
0126:            /** Internal interface, only public due to ClassLoader issues. */
0127:            public interface EnhancerKey {
0128:                public Object newInstance(String type, String[] interfaces,
0129:                        CallbackFilter filter, Type[] callbackTypes,
0130:                        boolean useFactory,
0131:                        boolean interceptDuringConstruction,
0132:                        Long serialVersionUID);
0133:            }
0134:
0135:            private Class[] interfaces;
0136:            private CallbackFilter filter;
0137:            private Callback[] callbacks;
0138:            private Type[] callbackTypes;
0139:            private boolean classOnly;
0140:            private Class super class;
0141:            private Class[] argumentTypes;
0142:            private Object[] arguments;
0143:            private boolean useFactory = true;
0144:            private Long serialVersionUID;
0145:            private boolean interceptDuringConstruction = true;
0146:
0147:            /**
0148:             * Create a new <code>Enhancer</code>. A new <code>Enhancer</code>
0149:             * object should be used for each generated object, and should not
0150:             * be shared across threads. To create additional instances of a
0151:             * generated class, use the <code>Factory</code> interface.
0152:             * @see Factory
0153:             */
0154:            public Enhancer() {
0155:                super (SOURCE);
0156:            }
0157:
0158:            /**
0159:             * Set the class which the generated class will extend. As a convenience,
0160:             * if the supplied superclass is actually an interface, <code>setInterfaces</code>
0161:             * will be called with the appropriate argument instead.
0162:             * A non-interface argument must not be declared as final, and must have an
0163:             * accessible constructor.
0164:             * @param superclass class to extend or interface to implement
0165:             * @see #setInterfaces(Class[])
0166:             */
0167:            public void setSuperclass(Class super class) {
0168:                if (super class != null && super class.isInterface()) {
0169:                    setInterfaces(new Class[] { super class });
0170:                } else if (super class != null
0171:                        && super class.equals(Object.class)) {
0172:                    // affects choice of ClassLoader
0173:                    this .super class = null;
0174:                } else {
0175:                    this .super class = super class;
0176:                }
0177:            }
0178:
0179:            /**
0180:             * Set the interfaces to implement. The <code>Factory</code> interface will
0181:             * always be implemented regardless of what is specified here.
0182:             * @param interfaces array of interfaces to implement, or null
0183:             * @see Factory
0184:             */
0185:            public void setInterfaces(Class[] interfaces) {
0186:                this .interfaces = interfaces;
0187:            }
0188:
0189:            /**
0190:             * Set the {@link CallbackFilter} used to map the generated class' methods
0191:             * to a particular callback index.
0192:             * New object instances will always use the same mapping, but may use different
0193:             * actual callback objects.
0194:             * @param filter the callback filter to use when generating a new class
0195:             * @see #setCallbacks
0196:             */
0197:            public void setCallbackFilter(CallbackFilter filter) {
0198:                this .filter = filter;
0199:            }
0200:
0201:            /**
0202:             * Set the single {@link Callback} to use.
0203:             * Ignored if you use {@link #createClass}.
0204:             * @param callback the callback to use for all methods
0205:             * @see #setCallbacks
0206:             */
0207:            public void setCallback(final Callback callback) {
0208:                setCallbacks(new Callback[] { callback });
0209:            }
0210:
0211:            /**
0212:             * Set the array of callbacks to use.
0213:             * Ignored if you use {@link #createClass}.
0214:             * You must use a {@link CallbackFilter} to specify the index into this
0215:             * array for each method in the proxied class.
0216:             * @param callbacks the callback array
0217:             * @see #setCallbackFilter
0218:             * @see #setCallback
0219:             */
0220:            public void setCallbacks(Callback[] callbacks) {
0221:                if (callbacks != null && callbacks.length == 0) {
0222:                    throw new IllegalArgumentException("Array cannot be empty");
0223:                }
0224:                this .callbacks = callbacks;
0225:            }
0226:
0227:            /**
0228:             * Set whether the enhanced object instances should implement
0229:             * the {@link Factory} interface.
0230:             * This was added for tools that need for proxies to be more
0231:             * indistinguishable from their targets. Also, in some cases it may
0232:             * be necessary to disable the <code>Factory</code> interface to
0233:             * prevent code from changing the underlying callbacks.
0234:             * @param useFactory whether to implement <code>Factory</code>; default is <code>true</code>
0235:             */
0236:            public void setUseFactory(boolean useFactory) {
0237:                this .useFactory = useFactory;
0238:            }
0239:
0240:            /**
0241:             * Set whether methods called from within the proxy's constructer
0242:             * will be intercepted. The default value is true. Unintercepted methods
0243:             * will call the method of the proxy's base class, if it exists.
0244:             * @param interceptDuringConstruction whether to intercept methods called from the constructor
0245:             */
0246:            public void setInterceptDuringConstruction(
0247:                    boolean interceptDuringConstruction) {
0248:                this .interceptDuringConstruction = interceptDuringConstruction;
0249:            }
0250:
0251:            /**
0252:             * Set the single type of {@link Callback} to use.
0253:             * This may be used instead of {@link #setCallback} when calling
0254:             * {@link #createClass}, since it may not be possible to have
0255:             * an array of actual callback instances.
0256:             * @param callbackType the type of callback to use for all methods
0257:             * @see #setCallbackTypes
0258:             */
0259:            public void setCallbackType(Class callbackType) {
0260:                setCallbackTypes(new Class[] { callbackType });
0261:            }
0262:
0263:            /**
0264:             * Set the array of callback types to use.
0265:             * This may be used instead of {@link #setCallbacks} when calling
0266:             * {@link #createClass}, since it may not be possible to have
0267:             * an array of actual callback instances.
0268:             * You must use a {@link CallbackFilter} to specify the index into this
0269:             * array for each method in the proxied class.
0270:             * @param callbackTypes the array of callback types
0271:             */
0272:            public void setCallbackTypes(Class[] callbackTypes) {
0273:                if (callbackTypes != null && callbackTypes.length == 0) {
0274:                    throw new IllegalArgumentException("Array cannot be empty");
0275:                }
0276:                this .callbackTypes = CallbackInfo.determineTypes(callbackTypes);
0277:            }
0278:
0279:            /**
0280:             * Generate a new class if necessary and uses the specified
0281:             * callbacks (if any) to create a new object instance.
0282:             * Uses the no-arg constructor of the superclass.
0283:             * @return a new instance
0284:             */
0285:            public Object create() {
0286:                classOnly = false;
0287:                argumentTypes = null;
0288:                return createHelper();
0289:            }
0290:
0291:            /**
0292:             * Generate a new class if necessary and uses the specified
0293:             * callbacks (if any) to create a new object instance.
0294:             * Uses the constructor of the superclass matching the <code>argumentTypes</code>
0295:             * parameter, with the given arguments.
0296:             * @param argumentTypes constructor signature
0297:             * @param arguments compatible wrapped arguments to pass to constructor
0298:             * @return a new instance
0299:             */
0300:            public Object create(Class[] argumentTypes, Object[] arguments) {
0301:                classOnly = false;
0302:                if (argumentTypes == null || arguments == null
0303:                        || argumentTypes.length != arguments.length) {
0304:                    throw new IllegalArgumentException(
0305:                            "Arguments must be non-null and of equal length");
0306:                }
0307:                this .argumentTypes = argumentTypes;
0308:                this .arguments = arguments;
0309:                return createHelper();
0310:            }
0311:
0312:            /**
0313:             * Generate a new class if necessary and return it without creating a new instance.
0314:             * This ignores any callbacks that have been set.
0315:             * To create a new instance you will have to use reflection, and methods
0316:             * called during the constructor will not be intercepted. To avoid this problem,
0317:             * use the multi-arg <code>create</code> method.
0318:             * @see #create(Class[], Object[])
0319:             */
0320:            public Class createClass() {
0321:                classOnly = true;
0322:                return (Class) createHelper();
0323:            }
0324:
0325:            /**
0326:             * Insert a static serialVersionUID field into the generated class.
0327:             * @param sUID the field value, or null to avoid generating field.
0328:             */
0329:            public void setSerialVersionUID(Long sUID) {
0330:                serialVersionUID = sUID;
0331:            }
0332:
0333:            private void validate() {
0334:                if (classOnly ^ (callbacks == null)) {
0335:                    if (classOnly) {
0336:                        throw new IllegalStateException(
0337:                                "createClass does not accept callbacks");
0338:                    } else {
0339:                        throw new IllegalStateException(
0340:                                "Callbacks are required");
0341:                    }
0342:                }
0343:                if (classOnly && (callbackTypes == null)) {
0344:                    throw new IllegalStateException(
0345:                            "Callback types are required");
0346:                }
0347:                if (callbacks != null && callbackTypes != null) {
0348:                    if (callbacks.length != callbackTypes.length) {
0349:                        throw new IllegalStateException(
0350:                                "Lengths of callback and callback types array must be the same");
0351:                    }
0352:                    Type[] check = CallbackInfo.determineTypes(callbacks);
0353:                    for (int i = 0; i < check.length; i++) {
0354:                        if (!check[i].equals(callbackTypes[i])) {
0355:                            throw new IllegalStateException("Callback "
0356:                                    + check[i] + " is not assignable to "
0357:                                    + callbackTypes[i]);
0358:                        }
0359:                    }
0360:                } else if (callbacks != null) {
0361:                    callbackTypes = CallbackInfo.determineTypes(callbacks);
0362:                }
0363:                if (filter == null) {
0364:                    if (callbackTypes.length > 1) {
0365:                        throw new IllegalStateException(
0366:                                "Multiple callback types possible but no filter specified");
0367:                    }
0368:                    filter = ALL_ZERO;
0369:                }
0370:                if (interfaces != null) {
0371:                    for (int i = 0; i < interfaces.length; i++) {
0372:                        if (interfaces[i] == null) {
0373:                            throw new IllegalStateException(
0374:                                    "Interfaces cannot be null");
0375:                        }
0376:                        if (!interfaces[i].isInterface()) {
0377:                            throw new IllegalStateException(interfaces[i]
0378:                                    + " is not an interface");
0379:                        }
0380:                    }
0381:                }
0382:            }
0383:
0384:            private Object createHelper() {
0385:                validate();
0386:                if (super class != null) {
0387:                    setNamePrefix(super class.getName());
0388:                } else if (interfaces != null) {
0389:                    setNamePrefix(interfaces[ReflectUtils
0390:                            .findPackageProtected(interfaces)].getName());
0391:                }
0392:                return super .create(KEY_FACTORY.newInstance(
0393:                        (super class != null) ? super class.getName() : null,
0394:                        ReflectUtils.getNames(interfaces), filter,
0395:                        callbackTypes, useFactory, interceptDuringConstruction,
0396:                        serialVersionUID));
0397:            }
0398:
0399:            protected ClassLoader getDefaultClassLoader() {
0400:                if (super class != null) {
0401:                    return super class.getClassLoader();
0402:                } else if (interfaces != null) {
0403:                    return interfaces[0].getClassLoader();
0404:                } else {
0405:                    return null;
0406:                }
0407:            }
0408:
0409:            private Signature rename(Signature sig, int index) {
0410:                return new Signature("CGLIB$" + sig.getName() + "$" + index,
0411:                        sig.getDescriptor());
0412:            }
0413:
0414:            /**
0415:             * Finds all of the methods that will be extended by an
0416:             * Enhancer-generated class using the specified superclass and
0417:             * interfaces. This can be useful in building a list of Callback
0418:             * objects. The methods are added to the end of the given list.  Due
0419:             * to the subclassing nature of the classes generated by Enhancer,
0420:             * the methods are guaranteed to be non-static, non-final, and
0421:             * non-private. Each method signature will only occur once, even if
0422:             * it occurs in multiple classes.
0423:             * @param superclass the class that will be extended, or null
0424:             * @param interfaces the list of interfaces that will be implemented, or null
0425:             * @param methods the list into which to copy the applicable methods
0426:             */
0427:            public static void getMethods(Class super class, Class[] interfaces,
0428:                    List methods) {
0429:                getMethods(super class, interfaces, methods, null, null);
0430:            }
0431:
0432:            private static void getMethods(Class super class,
0433:                    Class[] interfaces, List methods, List interfaceMethods,
0434:                    Set forcePublic) {
0435:                ReflectUtils.addAllMethods(super class, methods);
0436:                List target = (interfaceMethods != null) ? interfaceMethods
0437:                        : methods;
0438:                if (interfaces != null) {
0439:                    for (int i = 0; i < interfaces.length; i++) {
0440:                        if (interfaces[i] != Factory.class) {
0441:                            ReflectUtils.addAllMethods(interfaces[i], target);
0442:                        }
0443:                    }
0444:                }
0445:                if (interfaceMethods != null) {
0446:                    if (forcePublic != null) {
0447:                        forcePublic.addAll(MethodWrapper
0448:                                .createSet(interfaceMethods));
0449:                    }
0450:                    methods.addAll(interfaceMethods);
0451:                }
0452:                CollectionUtils.filter(methods, new RejectModifierPredicate(
0453:                        Constants.ACC_STATIC));
0454:                CollectionUtils.filter(methods, new VisibilityPredicate(
0455:                        super class, true));
0456:                CollectionUtils.filter(methods, new DuplicatesPredicate());
0457:                CollectionUtils.filter(methods, new RejectModifierPredicate(
0458:                        Constants.ACC_FINAL));
0459:            }
0460:
0461:            public void generateClass(ClassVisitor v) throws Exception {
0462:                Class sc = (super class == null) ? Object.class : super class;
0463:
0464:                if (TypeUtils.isFinal(sc.getModifiers()))
0465:                    throw new IllegalArgumentException(
0466:                            "Cannot subclass final class " + sc);
0467:                List constructors = new ArrayList(Arrays.asList(sc
0468:                        .getDeclaredConstructors()));
0469:                filterConstructors(sc, constructors);
0470:
0471:                // Order is very important: must add superclass, then
0472:                // its superclass chain, then each interface and
0473:                // its superinterfaces.
0474:                List actualMethods = new ArrayList();
0475:                List interfaceMethods = new ArrayList();
0476:                final Set forcePublic = new HashSet();
0477:                getMethods(sc, interfaces, actualMethods, interfaceMethods,
0478:                        forcePublic);
0479:
0480:                List methods = CollectionUtils.transform(actualMethods,
0481:                        new Transformer() {
0482:                            public Object transform(Object value) {
0483:                                Method method = (Method) value;
0484:                                int modifiers = Constants.ACC_FINAL
0485:                                        | (method.getModifiers()
0486:                                                & ~Constants.ACC_ABSTRACT
0487:                                                & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED);
0488:                                if (forcePublic.contains(MethodWrapper
0489:                                        .create(method))) {
0490:                                    modifiers = (modifiers & ~Constants.ACC_PROTECTED)
0491:                                            | Constants.ACC_PUBLIC;
0492:                                }
0493:                                return ReflectUtils.getMethodInfo(method,
0494:                                        modifiers);
0495:                            }
0496:                        });
0497:
0498:                ClassEmitter e = new ClassEmitter(v);
0499:                e.begin_class(Constants.V1_2, Constants.ACC_PUBLIC,
0500:                        getClassName(), Type.getType(sc),
0501:                        (useFactory ? TypeUtils.add(TypeUtils
0502:                                .getTypes(interfaces), FACTORY) : TypeUtils
0503:                                .getTypes(interfaces)), Constants.SOURCE_FILE);
0504:                List constructorInfo = CollectionUtils.transform(constructors,
0505:                        MethodInfoTransformer.getInstance());
0506:
0507:                e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD,
0508:                        Type.BOOLEAN_TYPE, null);
0509:                if (!interceptDuringConstruction) {
0510:                    e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD,
0511:                            Type.BOOLEAN_TYPE, null);
0512:                }
0513:                e.declare_field(Constants.PRIVATE_FINAL_STATIC,
0514:                        THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
0515:                e.declare_field(Constants.PRIVATE_FINAL_STATIC,
0516:                        STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
0517:                if (serialVersionUID != null) {
0518:                    e.declare_field(Constants.PRIVATE_FINAL_STATIC,
0519:                            Constants.SUID_FIELD_NAME, Type.LONG_TYPE,
0520:                            serialVersionUID);
0521:                }
0522:
0523:                for (int i = 0; i < callbackTypes.length; i++) {
0524:                    e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i),
0525:                            callbackTypes[i], null);
0526:                }
0527:
0528:                emitMethods(e, methods, actualMethods);
0529:                emitConstructors(e, constructorInfo);
0530:                emitSetThreadCallbacks(e);
0531:                emitSetStaticCallbacks(e);
0532:                emitBindCallbacks(e);
0533:
0534:                if (useFactory) {
0535:                    int[] keys = getCallbackKeys();
0536:                    emitNewInstanceCallbacks(e);
0537:                    emitNewInstanceCallback(e);
0538:                    emitNewInstanceMultiarg(e, constructorInfo);
0539:                    emitGetCallback(e, keys);
0540:                    emitSetCallback(e, keys);
0541:                    emitGetCallbacks(e);
0542:                    emitSetCallbacks(e);
0543:                }
0544:
0545:                e.end_class();
0546:            }
0547:
0548:            /**
0549:             * Filter the list of constructors from the superclass. The
0550:             * constructors which remain will be included in the generated
0551:             * class. The default implementation is to filter out all private
0552:             * constructors, but subclasses may extend Enhancer to override this
0553:             * behavior.
0554:             * @param sc the superclass
0555:             * @param constructors the list of all declared constructors from the superclass
0556:             * @throws IllegalArgumentException if there are no non-private constructors
0557:             */
0558:            protected void filterConstructors(Class sc, List constructors) {
0559:                CollectionUtils.filter(constructors, new VisibilityPredicate(
0560:                        sc, true));
0561:                if (constructors.size() == 0)
0562:                    throw new IllegalArgumentException(
0563:                            "No visible constructors in " + sc);
0564:            }
0565:
0566:            protected Object firstInstance(Class type) throws Exception {
0567:                if (classOnly) {
0568:                    return type;
0569:                } else {
0570:                    return createUsingReflection(type);
0571:                }
0572:            }
0573:
0574:            protected Object nextInstance(Object instance) {
0575:                Class protoclass = (instance instanceof  Class) ? (Class) instance
0576:                        : instance.getClass();
0577:                if (classOnly) {
0578:                    return protoclass;
0579:                } else if (instance instanceof  Factory) {
0580:                    if (argumentTypes != null) {
0581:                        return ((Factory) instance).newInstance(argumentTypes,
0582:                                arguments, callbacks);
0583:                    } else {
0584:                        return ((Factory) instance).newInstance(callbacks);
0585:                    }
0586:                } else {
0587:                    return createUsingReflection(protoclass);
0588:                }
0589:            }
0590:
0591:            /**
0592:             * Call this method to register the {@link Callback} array to use before
0593:             * creating a new instance of the generated class via reflection. If you are using
0594:             * an instance of <code>Enhancer</code> or the {@link Factory} interface to create
0595:             * new instances, this method is unnecessary. Its primary use is for when you want to
0596:             * cache and reuse a generated class yourself, and the generated class does
0597:             * <i>not</i> implement the {@link Factory} interface.
0598:             * <p>
0599:             * Note that this method only registers the callbacks on the current thread.
0600:             * If you want to register callbacks for instances created by multiple threads,
0601:             * use {@link #registerStaticCallbacks}.
0602:             * <p>
0603:             * The registered callbacks are overwritten and subsequently cleared
0604:             * when calling any of the <code>create</code> methods (such as
0605:             * {@link #create}).
0606:             * @param generatedClass a class previously created by {@link Enhancer}
0607:             * @param callbacks the array of callbacks to use when instances of the generated
0608:             * class are created
0609:             * @see #setUseFactory
0610:             */
0611:            public static void registerCallbacks(Class generatedClass,
0612:                    Callback[] callbacks) {
0613:                setThreadCallbacks(generatedClass, callbacks);
0614:            }
0615:
0616:            /**
0617:             * Similar to {@link #registerCallbacks}, but suitable for use
0618:             * when multiple threads will be creating instances of the generated class.
0619:             * The thread-level callbacks will always override the static callbacks.
0620:             * Static callbacks are never cleared.
0621:             * @param generatedClass a class previously created by {@link Enhancer}
0622:             * @param callbacks the array of callbacks to use when instances of the generated
0623:             * class are created
0624:             */
0625:            public static void registerStaticCallbacks(Class generatedClass,
0626:                    Callback[] callbacks) {
0627:                setCallbacksHelper(generatedClass, callbacks,
0628:                        SET_STATIC_CALLBACKS_NAME);
0629:            }
0630:
0631:            /**
0632:             * Determine if a class was generated using <code>Enhancer</code>.
0633:             * @param type any class
0634:             * @return whether the class was generated  using <code>Enhancer</code>
0635:             */
0636:            public static boolean isEnhanced(Class type) {
0637:                try {
0638:                    getCallbacksSetter(type, SET_THREAD_CALLBACKS_NAME);
0639:                    return true;
0640:                } catch (NoSuchMethodException e) {
0641:                    return false;
0642:                }
0643:            }
0644:
0645:            private static void setThreadCallbacks(Class type,
0646:                    Callback[] callbacks) {
0647:                setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME);
0648:            }
0649:
0650:            private static void setCallbacksHelper(Class type,
0651:                    Callback[] callbacks, String methodName) {
0652:                // TODO: optimize
0653:                try {
0654:                    Method setter = getCallbacksSetter(type, methodName);
0655:                    setter.invoke(null, new Object[] { callbacks });
0656:                } catch (NoSuchMethodException e) {
0657:                    throw new IllegalArgumentException(type
0658:                            + " is not an enhanced class");
0659:                } catch (IllegalAccessException e) {
0660:                    throw new CodeGenerationException(e);
0661:                } catch (InvocationTargetException e) {
0662:                    throw new CodeGenerationException(e);
0663:                }
0664:            }
0665:
0666:            private static Method getCallbacksSetter(Class type,
0667:                    String methodName) throws NoSuchMethodException {
0668:                return type.getDeclaredMethod(methodName,
0669:                        new Class[] { Callback[].class });
0670:            }
0671:
0672:            private Object createUsingReflection(Class type) {
0673:                setThreadCallbacks(type, callbacks);
0674:                try {
0675:
0676:                    if (argumentTypes != null) {
0677:
0678:                        return ReflectUtils.newInstance(type, argumentTypes,
0679:                                arguments);
0680:
0681:                    } else {
0682:
0683:                        return ReflectUtils.newInstance(type);
0684:
0685:                    }
0686:                } finally {
0687:                    // clear thread callbacks to allow them to be gc'd
0688:                    setThreadCallbacks(type, null);
0689:                }
0690:            }
0691:
0692:            /**
0693:             * Helper method to create an intercepted object.
0694:             * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
0695:             * instead of this static method.
0696:             * @param type class to extend or interface to implement
0697:             * @param callback the callback to use for all methods
0698:             */
0699:            public static Object create(Class type, Callback callback) {
0700:                Enhancer e = new Enhancer();
0701:                e.setSuperclass(type);
0702:                e.setCallback(callback);
0703:                return e.create();
0704:            }
0705:
0706:            /**
0707:             * Helper method to create an intercepted object.
0708:             * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
0709:             * instead of this static method.
0710:             * @param type class to extend or interface to implement
0711:             * @param interfaces array of interfaces to implement, or null
0712:             * @param callback the callback to use for all methods
0713:             */
0714:            public static Object create(Class super class, Class interfaces[],
0715:                    Callback callback) {
0716:                Enhancer e = new Enhancer();
0717:                e.setSuperclass(super class);
0718:                e.setInterfaces(interfaces);
0719:                e.setCallback(callback);
0720:                return e.create();
0721:            }
0722:
0723:            /**
0724:             * Helper method to create an intercepted object.
0725:             * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
0726:             * instead of this static method.
0727:             * @param type class to extend or interface to implement
0728:             * @param interfaces array of interfaces to implement, or null
0729:             * @param filter the callback filter to use when generating a new class
0730:             * @param callbacks callback implementations to use for the enhanced object
0731:             */
0732:            public static Object create(Class super class, Class[] interfaces,
0733:                    CallbackFilter filter, Callback[] callbacks) {
0734:                Enhancer e = new Enhancer();
0735:                e.setSuperclass(super class);
0736:                e.setInterfaces(interfaces);
0737:                e.setCallbackFilter(filter);
0738:                e.setCallbacks(callbacks);
0739:                return e.create();
0740:            }
0741:
0742:            private void emitConstructors(ClassEmitter ce, List constructors) {
0743:                boolean seenNull = false;
0744:                for (Iterator it = constructors.iterator(); it.hasNext();) {
0745:                    MethodInfo constructor = (MethodInfo) it.next();
0746:                    CodeEmitter e = EmitUtils.begin_method(ce, constructor,
0747:                            Constants.ACC_PUBLIC);
0748:                    e.load_this ();
0749:                    e.dup();
0750:                    e.load_args();
0751:                    Signature sig = constructor.getSignature();
0752:                    seenNull = seenNull || sig.getDescriptor().equals("()V");
0753:                    e.super _invoke_constructor(sig);
0754:                    e.invoke_static_this (BIND_CALLBACKS);
0755:                    if (!interceptDuringConstruction) {
0756:                        e.load_this ();
0757:                        e.push(1);
0758:                        e.putfield(CONSTRUCTED_FIELD);
0759:                    }
0760:                    e.return_value();
0761:                    e.end_method();
0762:                }
0763:                if (!classOnly && !seenNull && arguments == null)
0764:                    throw new IllegalArgumentException(
0765:                            "Superclass has no null constructors but no arguments were given");
0766:            }
0767:
0768:            private int[] getCallbackKeys() {
0769:                int[] keys = new int[callbackTypes.length];
0770:                for (int i = 0; i < callbackTypes.length; i++) {
0771:                    keys[i] = i;
0772:                }
0773:                return keys;
0774:            }
0775:
0776:            private void emitGetCallback(ClassEmitter ce, int[] keys) {
0777:                final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0778:                        GET_CALLBACK, null);
0779:                e.load_this ();
0780:                e.invoke_static_this (BIND_CALLBACKS);
0781:                e.load_this ();
0782:                e.load_arg(0);
0783:                e.process_switch(keys, new ProcessSwitchCallback() {
0784:                    public void processCase(int key, Label end) {
0785:                        e.getfield(getCallbackField(key));
0786:                        e.goTo(end);
0787:                    }
0788:
0789:                    public void processDefault() {
0790:                        e.pop(); // stack height
0791:                        e.aconst_null();
0792:                    }
0793:                });
0794:                e.return_value();
0795:                e.end_method();
0796:            }
0797:
0798:            private void emitSetCallback(ClassEmitter ce, int[] keys) {
0799:                final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0800:                        SET_CALLBACK, null);
0801:                e.load_this ();
0802:                e.load_arg(1);
0803:                e.load_arg(0);
0804:                e.process_switch(keys, new ProcessSwitchCallback() {
0805:                    public void processCase(int key, Label end) {
0806:                        e.checkcast(callbackTypes[key]);
0807:                        e.putfield(getCallbackField(key));
0808:                        e.goTo(end);
0809:                    }
0810:
0811:                    public void processDefault() {
0812:                        // TODO: error?
0813:                        e.pop2(); // stack height
0814:                    }
0815:                });
0816:                e.return_value();
0817:                e.end_method();
0818:            }
0819:
0820:            private void emitSetCallbacks(ClassEmitter ce) {
0821:                CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0822:                        SET_CALLBACKS, null);
0823:                e.load_this ();
0824:                e.load_arg(0);
0825:                for (int i = 0; i < callbackTypes.length; i++) {
0826:                    e.dup2();
0827:                    e.aaload(i);
0828:                    e.checkcast(callbackTypes[i]);
0829:                    e.putfield(getCallbackField(i));
0830:                }
0831:                e.return_value();
0832:                e.end_method();
0833:            }
0834:
0835:            private void emitGetCallbacks(ClassEmitter ce) {
0836:                CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0837:                        GET_CALLBACKS, null);
0838:                e.load_this ();
0839:                e.invoke_static_this (BIND_CALLBACKS);
0840:                e.load_this ();
0841:                e.push(callbackTypes.length);
0842:                e.newarray(CALLBACK);
0843:                for (int i = 0; i < callbackTypes.length; i++) {
0844:                    e.dup();
0845:                    e.push(i);
0846:                    e.load_this ();
0847:                    e.getfield(getCallbackField(i));
0848:                    e.aastore();
0849:                }
0850:                e.return_value();
0851:                e.end_method();
0852:            }
0853:
0854:            private void emitNewInstanceCallbacks(ClassEmitter ce) {
0855:                CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0856:                        NEW_INSTANCE, null);
0857:                e.load_arg(0);
0858:                e.invoke_static_this (SET_THREAD_CALLBACKS);
0859:                emitCommonNewInstance(e);
0860:            }
0861:
0862:            private void emitCommonNewInstance(CodeEmitter e) {
0863:                e.new_instance_this ();
0864:                e.dup();
0865:                e.invoke_constructor_this ();
0866:                e.aconst_null();
0867:                e.invoke_static_this (SET_THREAD_CALLBACKS);
0868:                e.return_value();
0869:                e.end_method();
0870:            }
0871:
0872:            private void emitNewInstanceCallback(ClassEmitter ce) {
0873:                CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0874:                        SINGLE_NEW_INSTANCE, null);
0875:                switch (callbackTypes.length) {
0876:                case 0:
0877:                    // TODO: make sure Callback is null
0878:                    break;
0879:                case 1:
0880:                    // for now just make a new array; TODO: optimize
0881:                    e.push(1);
0882:                    e.newarray(CALLBACK);
0883:                    e.dup();
0884:                    e.push(0);
0885:                    e.load_arg(0);
0886:                    e.aastore();
0887:                    e.invoke_static_this (SET_THREAD_CALLBACKS);
0888:                    break;
0889:                default:
0890:                    e.throw_exception(ILLEGAL_STATE_EXCEPTION,
0891:                            "More than one callback object required");
0892:                }
0893:                emitCommonNewInstance(e);
0894:            }
0895:
0896:            private void emitNewInstanceMultiarg(ClassEmitter ce,
0897:                    List constructors) {
0898:                final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
0899:                        MULTIARG_NEW_INSTANCE, null);
0900:                e.load_arg(2);
0901:                e.invoke_static_this (SET_THREAD_CALLBACKS);
0902:                e.new_instance_this ();
0903:                e.dup();
0904:                e.load_arg(0);
0905:                EmitUtils.constructor_switch(e, constructors,
0906:                        new ObjectSwitchCallback() {
0907:                            public void processCase(Object key, Label end) {
0908:                                MethodInfo constructor = (MethodInfo) key;
0909:                                Type types[] = constructor.getSignature()
0910:                                        .getArgumentTypes();
0911:                                for (int i = 0; i < types.length; i++) {
0912:                                    e.load_arg(1);
0913:                                    e.push(i);
0914:                                    e.aaload();
0915:                                    e.unbox(types[i]);
0916:                                }
0917:                                e.invoke_constructor_this (constructor
0918:                                        .getSignature());
0919:                                e.goTo(end);
0920:                            }
0921:
0922:                            public void processDefault() {
0923:                                e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION,
0924:                                        "Constructor not found");
0925:                            }
0926:                        });
0927:                e.aconst_null();
0928:                e.invoke_static_this (SET_THREAD_CALLBACKS);
0929:                e.return_value();
0930:                e.end_method();
0931:            }
0932:
0933:            private void emitMethods(final ClassEmitter ce, List methods,
0934:                    List actualMethods) {
0935:                CallbackGenerator[] generators = CallbackInfo
0936:                        .getGenerators(callbackTypes);
0937:
0938:                Map groups = new HashMap();
0939:                final Map indexes = new HashMap();
0940:                final Map originalModifiers = new HashMap();
0941:                final Map positions = CollectionUtils.getIndexMap(methods);
0942:
0943:                Iterator it1 = methods.iterator();
0944:                Iterator it2 = (actualMethods != null) ? actualMethods
0945:                        .iterator() : null;
0946:
0947:                while (it1.hasNext()) {
0948:                    MethodInfo method = (MethodInfo) it1.next();
0949:                    Method actualMethod = (it2 != null) ? (Method) it2.next()
0950:                            : null;
0951:                    int index = filter.accept(actualMethod);
0952:                    if (index >= callbackTypes.length) {
0953:                        throw new IllegalArgumentException(
0954:                                "Callback filter returned an index that is too large: "
0955:                                        + index);
0956:                    }
0957:                    originalModifiers.put(method, new Integer(
0958:                            (actualMethod != null) ? actualMethod
0959:                                    .getModifiers() : method.getModifiers()));
0960:                    indexes.put(method, new Integer(index));
0961:                    List group = (List) groups.get(generators[index]);
0962:                    if (group == null) {
0963:                        groups.put(generators[index], group = new ArrayList(
0964:                                methods.size()));
0965:                    }
0966:                    group.add(method);
0967:                }
0968:
0969:                Set seenGen = new HashSet();
0970:                CodeEmitter se = ce.getStaticHook();
0971:                se.new_instance(THREAD_LOCAL);
0972:                se.dup();
0973:                se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);
0974:                se.putfield(THREAD_CALLBACKS_FIELD);
0975:
0976:                final Object[] state = new Object[1];
0977:                CallbackGenerator.Context context = new CallbackGenerator.Context() {
0978:                    public ClassLoader getClassLoader() {
0979:                        return Enhancer.this .getClassLoader();
0980:                    }
0981:
0982:                    public int getOriginalModifiers(MethodInfo method) {
0983:                        return ((Integer) originalModifiers.get(method))
0984:                                .intValue();
0985:                    }
0986:
0987:                    public int getIndex(MethodInfo method) {
0988:                        return ((Integer) indexes.get(method)).intValue();
0989:                    }
0990:
0991:                    public void emitCallback(CodeEmitter e, int index) {
0992:                        emitCurrentCallback(e, index);
0993:                    }
0994:
0995:                    public Signature getImplSignature(MethodInfo method) {
0996:                        return rename(method.getSignature(),
0997:                                ((Integer) positions.get(method)).intValue());
0998:                    }
0999:
1000:                    public CodeEmitter beginMethod(ClassEmitter ce,
1001:                            MethodInfo method) {
1002:                        CodeEmitter e = EmitUtils.begin_method(ce, method);
1003:                        if (!interceptDuringConstruction
1004:                                && !TypeUtils.isAbstract(method.getModifiers())) {
1005:                            Label constructed = e.make_label();
1006:                            e.load_this ();
1007:                            e.getfield(CONSTRUCTED_FIELD);
1008:                            e.if_jump(e.NE, constructed);
1009:                            e.load_this ();
1010:                            e.load_args();
1011:                            e.super _invoke();
1012:                            e.return_value();
1013:                            e.mark(constructed);
1014:                        }
1015:                        return e;
1016:                    }
1017:                };
1018:                for (int i = 0; i < callbackTypes.length; i++) {
1019:                    CallbackGenerator gen = generators[i];
1020:                    if (!seenGen.contains(gen)) {
1021:                        seenGen.add(gen);
1022:                        final List fmethods = (List) groups.get(gen);
1023:                        if (fmethods != null) {
1024:                            try {
1025:                                gen.generate(ce, context, fmethods);
1026:                                gen.generateStatic(se, context, fmethods);
1027:                            } catch (RuntimeException x) {
1028:                                throw x;
1029:                            } catch (Exception x) {
1030:                                throw new CodeGenerationException(x);
1031:                            }
1032:                        }
1033:                    }
1034:                }
1035:                se.return_value();
1036:                se.end_method();
1037:            }
1038:
1039:            private void emitSetThreadCallbacks(ClassEmitter ce) {
1040:                CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC
1041:                        | Constants.ACC_STATIC, SET_THREAD_CALLBACKS, null);
1042:                e.getfield(THREAD_CALLBACKS_FIELD);
1043:                e.load_arg(0);
1044:                e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET);
1045:                e.return_value();
1046:                e.end_method();
1047:            }
1048:
1049:            private void emitSetStaticCallbacks(ClassEmitter ce) {
1050:                CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC
1051:                        | Constants.ACC_STATIC, SET_STATIC_CALLBACKS, null);
1052:                e.load_arg(0);
1053:                e.putfield(STATIC_CALLBACKS_FIELD);
1054:                e.return_value();
1055:                e.end_method();
1056:            }
1057:
1058:            private void emitCurrentCallback(CodeEmitter e, int index) {
1059:                e.load_this ();
1060:                e.getfield(getCallbackField(index));
1061:                e.dup();
1062:                Label end = e.make_label();
1063:                e.ifnonnull(end);
1064:                e.pop(); // stack height
1065:                e.load_this ();
1066:                e.invoke_static_this (BIND_CALLBACKS);
1067:                e.load_this ();
1068:                e.getfield(getCallbackField(index));
1069:                e.mark(end);
1070:            }
1071:
1072:            private void emitBindCallbacks(ClassEmitter ce) {
1073:                CodeEmitter e = ce.begin_method(Constants.PRIVATE_FINAL_STATIC,
1074:                        BIND_CALLBACKS, null);
1075:                Local me = e.make_local();
1076:                e.load_arg(0);
1077:                e.checkcast_this ();
1078:                e.store_local(me);
1079:
1080:                Label end = e.make_label();
1081:                e.load_local(me);
1082:                e.getfield(BOUND_FIELD);
1083:                e.if_jump(e.NE, end);
1084:                e.load_local(me);
1085:                e.push(1);
1086:                e.putfield(BOUND_FIELD);
1087:
1088:                e.getfield(THREAD_CALLBACKS_FIELD);
1089:                e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET);
1090:                e.dup();
1091:                Label found_callback = e.make_label();
1092:                e.ifnonnull(found_callback);
1093:                e.pop();
1094:
1095:                e.getfield(STATIC_CALLBACKS_FIELD);
1096:                e.dup();
1097:                e.ifnonnull(found_callback);
1098:                e.pop();
1099:                e.goTo(end);
1100:
1101:                e.mark(found_callback);
1102:                e.checkcast(CALLBACK_ARRAY);
1103:                e.load_local(me);
1104:                e.swap();
1105:                for (int i = callbackTypes.length - 1; i >= 0; i--) {
1106:                    if (i != 0) {
1107:                        e.dup2();
1108:                    }
1109:                    e.aaload(i);
1110:                    e.checkcast(callbackTypes[i]);
1111:                    e.putfield(getCallbackField(i));
1112:                }
1113:
1114:                e.mark(end);
1115:                e.return_value();
1116:                e.end_method();
1117:            }
1118:
1119:            private static String getCallbackField(int index) {
1120:                return "CGLIB$CALLBACK_" + index;
1121:            }
1122:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.