Source Code Cross Referenced for ShadowProxyFactory.java in  » Rule-Engine » drolls-Rule-Engine » org » drools » base » 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 » Rule Engine » drolls Rule Engine » org.drools.base 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2005 JBoss Inc
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:
0017:        package org.drools.base;
0018:
0019:        import java.lang.reflect.Method;
0020:        import java.lang.reflect.Modifier;
0021:        import java.security.AccessController;
0022:        import java.security.PrivilegedAction;
0023:        import java.security.ProtectionDomain;
0024:        import java.util.ArrayList;
0025:        import java.util.Collection;
0026:        import java.util.HashMap;
0027:        import java.util.Iterator;
0028:        import java.util.List;
0029:        import java.util.Map;
0030:
0031:        import org.drools.RuntimeDroolsException;
0032:        import org.drools.asm.ClassWriter;
0033:        import org.drools.asm.FieldVisitor;
0034:        import org.drools.asm.Label;
0035:        import org.drools.asm.MethodVisitor;
0036:        import org.drools.asm.Opcodes;
0037:        import org.drools.asm.Type;
0038:        import org.drools.util.ShadowProxyUtils;
0039:
0040:        /**
0041:         * A factory for ShadowProxy classes
0042:         */
0043:        public class ShadowProxyFactory {
0044:            private static final String UPDATE_PROXY = "updateProxy";
0045:            private static final String SET_SHADOWED_OBJECT = "setShadowedObject";
0046:            private static final String GET_SHADOWED_OBJECT = "getShadowedObject";
0047:
0048:            private static final String BASE_INTERFACE = Type
0049:                    .getInternalName(ShadowProxy.class);
0050:
0051:            //private static final String FIELD_NAME_PREFIX   = "__";
0052:
0053:            public static final String FIELD_SET_FLAG = "IsSet";
0054:
0055:            public static final String DELEGATE_FIELD_NAME = "delegate";
0056:
0057:            public static final String HASHCACHE_FIELD_NAME = "__hashCache";
0058:
0059:            private static final ProtectionDomain PROTECTION_DOMAIN;
0060:
0061:            static {
0062:                PROTECTION_DOMAIN = (ProtectionDomain) AccessController
0063:                        .doPrivileged(new PrivilegedAction() {
0064:                            public Object run() {
0065:                                return ShadowProxyFactory.class
0066:                                        .getProtectionDomain();
0067:                            }
0068:                        });
0069:            }
0070:
0071:            public static Class getProxy(final Class clazz) {
0072:                try {
0073:                    if (!isPossibleToGenerateTheProxyFor(clazz)) {
0074:                        return null;
0075:                    }
0076:
0077:                    final String className = getInternalProxyClassNameForClass(clazz);
0078:                    // generating byte array to create target class
0079:                    final byte[] bytes = dump(clazz, className);
0080:                    // use bytes to get a class 
0081:                    final ByteArrayClassLoader classLoader = new ByteArrayClassLoader(
0082:                            Thread.currentThread().getContextClassLoader());
0083:                    final Class newClass = classLoader.defineClass(className
0084:                            .replace('/', '.'), bytes, PROTECTION_DOMAIN);
0085:                    return newClass;
0086:                } catch (final Exception e) {
0087:                    throw new RuntimeDroolsException(e);
0088:                }
0089:            }
0090:
0091:            public static byte[] getProxyBytes(final Class clazz) {
0092:                try {
0093:                    if (!isPossibleToGenerateTheProxyFor(clazz)) {
0094:                        return null;
0095:                    }
0096:
0097:                    final String className = getInternalProxyClassNameForClass(clazz);
0098:                    // generating byte array to create target class
0099:                    final byte[] bytes = dump(clazz, className);
0100:                    return bytes;
0101:                } catch (final Exception e) {
0102:                    throw new RuntimeDroolsException(e);
0103:                }
0104:            }
0105:
0106:            protected static boolean isPossibleToGenerateTheProxyFor(
0107:                    final Class clazz) throws Exception {
0108:                if ((clazz.getModifiers() & Modifier.FINAL) != 0) {
0109:                    return false;
0110:                }
0111:                try {
0112:                    Method equals = clazz.getMethod("equals",
0113:                            new Class[] { Object.class });
0114:                    if (Modifier.isFinal(equals.getModifiers())) {
0115:                        return false;
0116:                    }
0117:                } catch (NoSuchMethodException e) {
0118:                    // that's fine
0119:                }
0120:                try {
0121:                    Method hashcode = clazz.getMethod("hashCode", new Class[0]);
0122:                    if (Modifier.isFinal(hashcode.getModifiers())) {
0123:                        return false;
0124:                    }
0125:                } catch (NoSuchMethodException e) {
0126:                    // that's fine
0127:                }
0128:                return true;
0129:            }
0130:
0131:            /**
0132:             * @param clazz
0133:             * @return
0134:             */
0135:            public static String getInternalProxyClassNameForClass(
0136:                    final Class clazz) {
0137:                String className = null;
0138:                if (clazz.getPackage() != null
0139:                        && (clazz.getPackage().getName().startsWith("java.") || clazz
0140:                                .getPackage().getName().startsWith("javax."))) {
0141:                    className = "org/drools/shadow/"
0142:                            + Type.getInternalName(clazz) + "ShadowProxy";
0143:                } else {
0144:                    className = Type.getInternalName(clazz) + "ShadowProxy";
0145:                }
0146:                return className;
0147:            }
0148:
0149:            public static String getProxyClassNameForClass(final Class clazz) {
0150:                String className = null;
0151:                Package pkg = clazz.getPackage();
0152:                if (pkg != null
0153:                        && (pkg.getName().startsWith("java.") || pkg.getName()
0154:                                .startsWith("javax."))) {
0155:                    className = "org.drools.shadow." + clazz.getName()
0156:                            + "ShadowProxy";
0157:                } else {
0158:                    className = clazz.getName() + "ShadowProxy";
0159:                }
0160:                return className;
0161:            }
0162:
0163:            protected static byte[] dump(final Class clazz,
0164:                    final String className) throws Exception {
0165:
0166:                final ClassWriter cw = new ClassWriter(true);
0167:
0168:                buildClassHeader(clazz, className, cw);
0169:
0170:                buildConstructor(clazz, className, cw);
0171:
0172:                buildField(ShadowProxyFactory.DELEGATE_FIELD_NAME, Type
0173:                        .getDescriptor(clazz), cw);
0174:
0175:                final Method getShadowed = ShadowProxy.class.getDeclaredMethod(
0176:                        GET_SHADOWED_OBJECT, new Class[] {});
0177:                final Method setShadowed = ShadowProxy.class.getDeclaredMethod(
0178:                        SET_SHADOWED_OBJECT, new Class[] { Object.class });
0179:                buildSimpleGetMethod(ShadowProxyFactory.DELEGATE_FIELD_NAME,
0180:                        clazz, getShadowed, className, clazz, cw);
0181:
0182:                buildSetShadowedObject(clazz, className, setShadowed, cw);
0183:
0184:                if (Collection.class.isAssignableFrom(clazz)) {
0185:                    buildCollectionClass(clazz, className, cw);
0186:                } else if (Map.class.isAssignableFrom(clazz)) {
0187:                    buildMapClass(clazz, className, cw);
0188:                } else {
0189:                    buildRegularClass(clazz, className, cw);
0190:                }
0191:
0192:                return cw.toByteArray();
0193:            }
0194:
0195:            private static void buildCollectionClass(final Class clazz,
0196:                    final String className, final ClassWriter cw) {
0197:
0198:                buildCollectionUpdateProxyMethod(clazz, className, cw);
0199:
0200:            }
0201:
0202:            private static void buildMapClass(final Class clazz,
0203:                    final String className, final ClassWriter cw) {
0204:
0205:                buildMapUpdateProxyMethod(clazz, className, cw);
0206:
0207:            }
0208:
0209:            private static void buildRegularClass(final Class clazz,
0210:                    final String className, final ClassWriter cw) {
0211:                final Map fieldTypes = new HashMap();
0212:                final Method[] methods = getMethods(clazz);
0213:                for (int i = 0; i < methods.length; i++) {
0214:                    if ((!Modifier.isFinal(methods[i].getModifiers()))
0215:                            && Modifier.isPublic(methods[i].getModifiers())
0216:                            && (!Modifier.isStatic(methods[i].getModifiers()))) {
0217:                        if ((!methods[i].getReturnType().equals(Void.TYPE))
0218:                                && (methods[i].getParameterTypes().length == 0)
0219:                                && (!methods[i].getName().equals("hashCode"))
0220:                                && (!methods[i].getName().equals("toString"))) {
0221:
0222:                            final String fieldName = methods[i].getName();
0223:
0224:                            buildField(fieldName, Type.getDescriptor(methods[i]
0225:                                    .getReturnType()), cw);
0226:                            fieldTypes.put(fieldName, methods[i]);
0227:
0228:                            buildField(fieldName
0229:                                    + ShadowProxyFactory.FIELD_SET_FLAG,
0230:                                    Type.BOOLEAN_TYPE.getDescriptor(), cw);
0231:                            buildGetMethod(fieldName, methods[i]
0232:                                    .getReturnType(), fieldName
0233:                                    + ShadowProxyFactory.FIELD_SET_FLAG,
0234:                                    methods[i], className, clazz, cw);
0235:                        } else if ((!methods[i].getName().equals("hashCode"))
0236:                                && (!methods[i].getName().equals("equals"))) {
0237:                            buildDelegateMethod(methods[i], clazz, className,
0238:                                    cw);
0239:                        }
0240:                    }
0241:                }
0242:
0243:                buildUpdateProxyMethod(fieldTypes, className, cw);
0244:
0245:                buildEquals(cw, className, clazz, fieldTypes);
0246:
0247:                buildField(ShadowProxyFactory.HASHCACHE_FIELD_NAME, Type
0248:                        .getDescriptor(int.class), cw);
0249:
0250:                buildHashCode(cw, className, clazz, fieldTypes);
0251:            }
0252:
0253:            /**
0254:             * Filter out any method we are not interested in
0255:             * @param clazz
0256:             * @return
0257:             */
0258:            private static Method[] getMethods(final Class clazz) {
0259:                // to help filtering process, we will create a map of maps:
0260:                // Map< String methodName, Map< Class[] parameterTypes, Method method > >
0261:                final Map map = new HashMap();
0262:                final List helperList = new ArrayList();
0263:                final Method[] methods = clazz.getMethods();
0264:                for (int i = 0; i < methods.length; i++) {
0265:                    Method previous = null;
0266:                    Map signatures = (Map) map.get(methods[i].getName());
0267:                    final ParametersWrapper key = new ParametersWrapper(
0268:                            methods[i].getParameterTypes());
0269:                    if (signatures != null) {
0270:                        previous = (Method) signatures.get(key);
0271:                    }
0272:                    // if no previous method with the same name and parameter types is found
0273:                    // or if the previous method's return type is a super class of the 
0274:                    // current method's return type, add current to the map
0275:                    // overriding previous if it exists
0276:                    if ((previous == null)
0277:                            || (previous.getReturnType()
0278:                                    .isAssignableFrom(methods[i]
0279:                                            .getReturnType()))) {
0280:                        if (signatures == null) {
0281:                            signatures = new HashMap();
0282:                            map.put(methods[i].getName(), signatures);
0283:                        }
0284:                        if (signatures.put(key, methods[i]) != null) {
0285:                            helperList.remove(previous);
0286:                        }
0287:                        helperList.add(methods[i]);
0288:                    }
0289:                }
0290:                return (Method[]) helperList.toArray(new Method[helperList
0291:                        .size()]);
0292:            }
0293:
0294:            private static class ParametersWrapper {
0295:                private Class[] parameters;
0296:
0297:                public ParametersWrapper(final Class[] parameters) {
0298:                    this .parameters = parameters;
0299:                }
0300:
0301:                public int hashCode() {
0302:                    return this .parameters.length;
0303:                }
0304:
0305:                public boolean equals(final Object o) {
0306:                    if (!(o instanceof  ParametersWrapper)) {
0307:                        return false;
0308:                    }
0309:                    final ParametersWrapper other = (ParametersWrapper) o;
0310:
0311:                    if (this .parameters.length != other.parameters.length) {
0312:                        return false;
0313:                    }
0314:
0315:                    for (int i = 0; i < this .parameters.length; i++) {
0316:                        if (!this .parameters[i].equals(other.parameters[i])) {
0317:                            return false;
0318:                        }
0319:                    }
0320:                    return true;
0321:                }
0322:            }
0323:
0324:            /**
0325:             * Builds the shadow proxy class header
0326:             *  
0327:             * @param clazz The class to build shadow proxy for
0328:             * @param className The shadow proxy class name
0329:             * @param cw
0330:             */
0331:            protected static void buildClassHeader(final Class clazz,
0332:                    final String className, final ClassWriter cw) {
0333:                if (clazz.isInterface()) {
0334:                    cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC
0335:                            + Opcodes.ACC_SUPER, className, null, Type
0336:                            .getInternalName(Object.class), new String[] {
0337:                            ShadowProxyFactory.BASE_INTERFACE,
0338:                            Type.getInternalName(clazz) });
0339:                } else {
0340:                    cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC
0341:                            + Opcodes.ACC_SUPER, className, null, Type
0342:                            .getInternalName(clazz),
0343:                            new String[] { ShadowProxyFactory.BASE_INTERFACE });
0344:                }
0345:
0346:                cw.visitSource(null, null);
0347:            }
0348:
0349:            /**
0350:             * Creates the field defined by the given FieldDefinition 
0351:             * 
0352:             * @param cw
0353:             * @param fieldDef
0354:             */
0355:            protected static void buildField(final String name,
0356:                    final String type, final ClassWriter cw) {
0357:                FieldVisitor fv;
0358:                fv = cw.visitField(Opcodes.ACC_PRIVATE, name, type, null, null);
0359:                fv.visitEnd();
0360:            }
0361:
0362:            /**
0363:             * Creates a constructor for the shadow proxy receiving
0364:             * the actual delegate class as parameter
0365:             * 
0366:             * @param originalClassName
0367:             * @param className
0368:             * @param cw
0369:             */
0370:            private static void buildConstructor(final Class clazz,
0371:                    final String className, final ClassWriter cw) {
0372:                MethodVisitor mv;
0373:                {
0374:                    mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", Type
0375:                            .getMethodDescriptor(Type.VOID_TYPE,
0376:                                    new Type[] { Type.getType(clazz) }), null,
0377:                            null);
0378:                    mv.visitCode();
0379:
0380:                    // super();
0381:                    final Label l0 = new Label();
0382:                    mv.visitLabel(l0);
0383:                    mv.visitLineNumber(41, l0);
0384:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0385:                    if (clazz.isInterface()) {
0386:                        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type
0387:                                .getInternalName(Object.class), "<init>", Type
0388:                                .getMethodDescriptor(Type.VOID_TYPE,
0389:                                        new Type[] {}));
0390:                    } else {
0391:                        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type
0392:                                .getInternalName(clazz), "<init>", Type
0393:                                .getMethodDescriptor(Type.VOID_TYPE,
0394:                                        new Type[] {}));
0395:                    }
0396:
0397:                    // this.delegate = delegate
0398:                    final Label l1 = new Label();
0399:                    mv.visitLabel(l1);
0400:                    mv.visitLineNumber(42, l1);
0401:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0402:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0403:                    mv.visitFieldInsn(Opcodes.PUTFIELD, className,
0404:                            ShadowProxyFactory.DELEGATE_FIELD_NAME, Type
0405:                                    .getDescriptor(clazz));
0406:
0407:                    // return
0408:                    final Label l2 = new Label();
0409:                    mv.visitLabel(l2);
0410:                    mv.visitLineNumber(43, l2);
0411:                    mv.visitInsn(Opcodes.RETURN);
0412:
0413:                    final Label l3 = new Label();
0414:                    mv.visitLabel(l3);
0415:                    mv.visitLocalVariable("this", "L" + className + ";", null,
0416:                            l0, l3, 0);
0417:                    mv.visitLocalVariable(
0418:                            ShadowProxyFactory.DELEGATE_FIELD_NAME, Type
0419:                                    .getDescriptor(clazz), null, l0, l3, 1);
0420:                    mv.visitMaxs(0, 0);
0421:                    mv.visitEnd();
0422:                }
0423:            }
0424:
0425:            /**
0426:             * Creates the proxy reader method for the given method
0427:             * 
0428:             * @param fieldName
0429:             * @param fieldFlag
0430:             * @param method
0431:             * @param cw
0432:             */
0433:            protected static void buildGetMethod(final String fieldName,
0434:                    final Class fieldType, final String fieldFlag,
0435:                    final Method method, final String className,
0436:                    final Class clazz, final ClassWriter cw) {
0437:                // method signature 
0438:                final Class[] exceptionTypes = method.getExceptionTypes();
0439:                final String[] exceptions = getExceptionArrayAsString(exceptionTypes);
0440:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0441:                        method.getName(), Type.getMethodDescriptor(method),
0442:                        null, exceptions);
0443:                mv.visitCode();
0444:
0445:                // if ( ! _fieldIsSet ) {
0446:                final Label l0 = new Label();
0447:                mv.visitLabel(l0);
0448:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0449:                mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldFlag,
0450:                        Type.BOOLEAN_TYPE.getDescriptor());
0451:                final Label l1 = new Label();
0452:                mv.visitJumpInsn(Opcodes.IFNE, l1);
0453:
0454:                //     __fieldIsSet = true;
0455:                final Label l3 = new Label();
0456:                mv.visitLabel(l3);
0457:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0458:                mv.visitInsn(Opcodes.ICONST_1);
0459:                mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldFlag,
0460:                        Type.BOOLEAN_TYPE.getDescriptor());
0461:
0462:                if (Map.class.isAssignableFrom(fieldType)
0463:                        || Collection.class.isAssignableFrom(fieldType)
0464:                        || fieldType.isArray()) {
0465:
0466:                    // FieldType aux = this.delegate.getField();
0467:                    Label l01 = new Label();
0468:                    mv.visitLabel(l01);
0469:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0470:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0471:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0472:                    if (clazz.isInterface()) {
0473:                        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type
0474:                                .getInternalName(clazz), method.getName(), Type
0475:                                .getMethodDescriptor(method));
0476:                    } else {
0477:                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type
0478:                                .getInternalName(clazz), method.getName(), Type
0479:                                .getMethodDescriptor(method));
0480:                    }
0481:                    mv.visitVarInsn(Opcodes.ASTORE, 1);
0482:
0483:                    // this.field = (FieldType) ShadoProxyUtils.clone( aux );
0484:                    Label l11 = new Label();
0485:                    mv.visitLabel(l11);
0486:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0487:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0488:                    mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type
0489:                            .getInternalName(ShadowProxyUtils.class),
0490:                            "cloneObject",
0491:                            "(Ljava/lang/Object;)Ljava/lang/Object;");
0492:                    mv.visitTypeInsn(Opcodes.CHECKCAST, Type
0493:                            .getInternalName(fieldType));
0494:                    mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldName,
0495:                            Type.getDescriptor(fieldType));
0496:
0497:                } else {
0498:                    //     __field = this.delegate.method();
0499:                    final Label l2 = new Label();
0500:                    mv.visitLabel(l2);
0501:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0502:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0503:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0504:                            ShadowProxyFactory.DELEGATE_FIELD_NAME, Type
0505:                                    .getDescriptor(clazz));
0506:                    if (clazz.isInterface()) {
0507:                        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type
0508:                                .getInternalName(clazz), method.getName(), Type
0509:                                .getMethodDescriptor(method));
0510:                    } else {
0511:                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type
0512:                                .getInternalName(clazz), method.getName(), Type
0513:                                .getMethodDescriptor(method));
0514:                    }
0515:                    mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldName,
0516:                            Type.getDescriptor(fieldType));
0517:
0518:                }
0519:
0520:                // }
0521:                // return __field;
0522:                mv.visitLabel(l1);
0523:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0524:                mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, Type
0525:                        .getDescriptor(fieldType));
0526:                mv
0527:                        .visitInsn(Type.getType(fieldType).getOpcode(
0528:                                Opcodes.IRETURN));
0529:
0530:                // local variables table
0531:                final Label l4 = new Label();
0532:                mv.visitLabel(l4);
0533:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0534:                        l4, 0);
0535:                mv.visitMaxs(0, 0);
0536:                mv.visitEnd();
0537:            }
0538:
0539:            /**
0540:             * Creates the proxy reader method for the given method
0541:             * 
0542:             * @param fieldName
0543:             * @param fieldFlag
0544:             * @param method
0545:             * @param cw
0546:             */
0547:            protected static void buildSimpleGetMethod(final String fieldName,
0548:                    final Class fieldType, final Method method,
0549:                    final String className, final Class clazz,
0550:                    final ClassWriter cw) {
0551:
0552:                final Class[] exceptionTypes = method.getExceptionTypes();
0553:                final String[] exceptions = getExceptionArrayAsString(exceptionTypes);
0554:                // method signature 
0555:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0556:                        method.getName(), Type.getMethodDescriptor(method),
0557:                        null, exceptions);
0558:                mv.visitCode();
0559:
0560:                // return __field;
0561:                final Label l0 = new Label();
0562:                mv.visitLabel(l0);
0563:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0564:                mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, Type
0565:                        .getDescriptor(fieldType));
0566:                mv
0567:                        .visitInsn(Type.getType(fieldType).getOpcode(
0568:                                Opcodes.IRETURN));
0569:
0570:                // local variables table
0571:                final Label l4 = new Label();
0572:                mv.visitLabel(l4);
0573:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0574:                        l4, 0);
0575:                mv.visitMaxs(0, 0);
0576:                mv.visitEnd();
0577:            }
0578:
0579:            protected static void buildUpdateProxyMethod(final Map fieldTypes,
0580:                    final String className, final ClassWriter cw) {
0581:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0582:                        ShadowProxyFactory.UPDATE_PROXY, Type
0583:                                .getMethodDescriptor(Type.VOID_TYPE,
0584:                                        new Type[] {}), null, null);
0585:                mv.visitCode();
0586:                final Label l0 = new Label();
0587:                mv.visitLabel(l0);
0588:                for (final Iterator it = fieldTypes.entrySet().iterator(); it
0589:                        .hasNext();) {
0590:                    final Map.Entry entry = (Map.Entry) it.next();
0591:                    final String fieldName = (String) entry.getKey();
0592:                    final String fieldFlag = fieldName
0593:                            + ShadowProxyFactory.FIELD_SET_FLAG;
0594:                    final Class fieldType = ((Method) entry.getValue())
0595:                            .getReturnType();
0596:                    final Label l1 = new Label();
0597:                    mv.visitLabel(l1);
0598:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0599:                    if (fieldType.isPrimitive()) {
0600:                        if (fieldType.equals(Long.TYPE)) {
0601:                            mv.visitInsn(Opcodes.LCONST_0);
0602:                        } else if (fieldType.equals(Double.TYPE)) {
0603:                            mv.visitInsn(Opcodes.DCONST_0);
0604:                        } else if (fieldType.equals(Float.TYPE)) {
0605:                            mv.visitInsn(Opcodes.FCONST_0);
0606:                        } else {
0607:                            mv.visitInsn(Opcodes.ICONST_0);
0608:                        }
0609:                    } else {
0610:                        mv.visitInsn(Opcodes.ACONST_NULL);
0611:                    }
0612:                    mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldName,
0613:                            Type.getDescriptor(fieldType));
0614:                    final Label l2 = new Label();
0615:                    mv.visitLabel(l2);
0616:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0617:                    mv.visitInsn(Opcodes.ICONST_0);
0618:                    mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldFlag,
0619:                            Type.BOOLEAN_TYPE.getDescriptor());
0620:                }
0621:
0622:                //    this.__hashCache = 0;
0623:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0624:                mv.visitInsn(Opcodes.ICONST_0);
0625:                mv.visitFieldInsn(Opcodes.PUTFIELD, className,
0626:                        ShadowProxyFactory.HASHCACHE_FIELD_NAME, Type
0627:                                .getDescriptor(int.class));
0628:
0629:                final Label l4 = new Label();
0630:                mv.visitLabel(l4);
0631:                mv.visitInsn(Opcodes.RETURN);
0632:                final Label l5 = new Label();
0633:                mv.visitLabel(l5);
0634:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0635:                        l5, 0);
0636:                mv.visitMaxs(0, 0);
0637:                mv.visitEnd();
0638:            }
0639:
0640:            protected static void buildSetShadowedObject(final Class clazz,
0641:                    final String className, final Method setShadowed,
0642:                    final ClassWriter cw) {
0643:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0644:                        setShadowed.getName(), Type
0645:                                .getMethodDescriptor(setShadowed), null, null);
0646:                mv.visitCode();
0647:                Label l0 = new Label();
0648:                mv.visitLabel(l0);
0649:                // this.delegate = (<clazz>) object;
0650:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0651:                mv.visitVarInsn(Opcodes.ALOAD, 1);
0652:                mv
0653:                        .visitTypeInsn(Opcodes.CHECKCAST, Type
0654:                                .getInternalName(clazz));
0655:                mv.visitFieldInsn(Opcodes.PUTFIELD, className,
0656:                        DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0657:                if (Collection.class.isAssignableFrom(clazz)
0658:                        || Map.class.isAssignableFrom(clazz)) {
0659:                    Label l1 = new Label();
0660:                    mv.visitLabel(l1);
0661:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0662:                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className,
0663:                            UPDATE_PROXY, Type.getMethodDescriptor(
0664:                                    Type.VOID_TYPE, new Type[0]));
0665:                }
0666:                Label l2 = new Label();
0667:                mv.visitLabel(l2);
0668:                mv.visitInsn(Opcodes.RETURN);
0669:                Label l3 = new Label();
0670:                mv.visitLabel(l3);
0671:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0672:                        l3, 0);
0673:                mv.visitLocalVariable("object", Type
0674:                        .getDescriptor(Object.class), null, l0, l3, 1);
0675:                mv.visitMaxs(0, 0);
0676:                mv.visitEnd();
0677:            }
0678:
0679:            /**
0680:             * Creates an update proxy method for Map classes
0681:             * 
0682:             * public void updateProxy() {
0683:             *     this.clear();
0684:             *     this.addAll( this.delegate );
0685:             * }
0686:             * 
0687:             * @param clazz
0688:             * @param className
0689:             * @param cw
0690:             */
0691:            protected static void buildCollectionUpdateProxyMethod(
0692:                    final Class clazz, final String className,
0693:                    final ClassWriter cw) {
0694:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0695:                        ShadowProxyFactory.UPDATE_PROXY, Type
0696:                                .getMethodDescriptor(Type.VOID_TYPE,
0697:                                        new Type[] {}), null, null);
0698:                mv.visitCode();
0699:                final Label l0 = new Label();
0700:                mv.visitLabel(l0);
0701:                // this.clear();
0702:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0703:                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "clear",
0704:                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]));
0705:                Label l1 = new Label();
0706:                mv.visitLabel(l1);
0707:                // this.addAll( this.delegate );
0708:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0709:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0710:                mv.visitFieldInsn(Opcodes.GETFIELD, className,
0711:                        DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0712:                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "addAll",
0713:                        Type.getMethodDescriptor(Type.BOOLEAN_TYPE,
0714:                                new Type[] { Type.getType(Collection.class) }));
0715:                mv.visitInsn(Opcodes.POP);
0716:                Label l2 = new Label();
0717:                mv.visitLabel(l2);
0718:                mv.visitInsn(Opcodes.RETURN);
0719:                Label l3 = new Label();
0720:                mv.visitLabel(l3);
0721:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0722:                        l3, 0);
0723:                mv.visitMaxs(0, 0);
0724:                mv.visitEnd();
0725:            }
0726:
0727:            /**
0728:             * Creates an update proxy method for Map classes
0729:             * 
0730:             * public void updateProxy() {
0731:             *     this.clear();
0732:             *     this.putAll( this.delegate );
0733:             * }
0734:             * 
0735:             * @param clazz
0736:             * @param className
0737:             * @param cw
0738:             */
0739:            protected static void buildMapUpdateProxyMethod(final Class clazz,
0740:                    final String className, final ClassWriter cw) {
0741:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0742:                        ShadowProxyFactory.UPDATE_PROXY, Type
0743:                                .getMethodDescriptor(Type.VOID_TYPE,
0744:                                        new Type[] {}), null, null);
0745:                mv.visitCode();
0746:                final Label l0 = new Label();
0747:                mv.visitLabel(l0);
0748:                // this.clear();
0749:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0750:                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "clear",
0751:                        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]));
0752:                Label l1 = new Label();
0753:                mv.visitLabel(l1);
0754:                // this.putAll( this.delegate );
0755:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0756:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0757:                mv.visitFieldInsn(Opcodes.GETFIELD, className,
0758:                        DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0759:                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "putAll",
0760:                        Type.getMethodDescriptor(Type.VOID_TYPE,
0761:                                new Type[] { Type.getType(Map.class) }));
0762:                Label l2 = new Label();
0763:                mv.visitLabel(l2);
0764:                mv.visitInsn(Opcodes.RETURN);
0765:                Label l3 = new Label();
0766:                mv.visitLabel(l3);
0767:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0768:                        l3, 0);
0769:                mv.visitMaxs(0, 0);
0770:                mv.visitEnd();
0771:            }
0772:
0773:            protected static void buildDelegateMethod(final Method method,
0774:                    final Class clazz, final String className,
0775:                    final ClassWriter cw) {
0776:
0777:                // creating method visitor
0778:                final String[] exceptions = getExceptionArrayAsString(method
0779:                        .getExceptionTypes());
0780:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0781:                        method.getName(), Type.getMethodDescriptor(method),
0782:                        null, exceptions);
0783:                mv.visitCode();
0784:
0785:                // return this.delegate.method(...);
0786:                final Label l0 = new Label();
0787:                mv.visitLabel(l0);
0788:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0789:                mv.visitFieldInsn(Opcodes.GETFIELD, className,
0790:                        ShadowProxyFactory.DELEGATE_FIELD_NAME, Type
0791:                                .getDescriptor(clazz));
0792:
0793:                final Class[] parameters = method.getParameterTypes();
0794:                for (int i = 0, offset = 1; i < parameters.length; i++) {
0795:                    Type type = Type.getType(parameters[i]);
0796:                    mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), offset);
0797:                    offset += type.getSize();
0798:                }
0799:                if (clazz.isInterface()) {
0800:                    mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type
0801:                            .getInternalName(clazz), method.getName(), Type
0802:                            .getMethodDescriptor(method));
0803:                } else {
0804:                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type
0805:                            .getInternalName(clazz), method.getName(), Type
0806:                            .getMethodDescriptor(method));
0807:                }
0808:                mv.visitInsn(Type.getType(method.getReturnType()).getOpcode(
0809:                        Opcodes.IRETURN));
0810:                final Label l1 = new Label();
0811:                mv.visitLabel(l1);
0812:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
0813:                        l1, 0);
0814:                for (int i = 0, offset = 0; i < parameters.length; i++) {
0815:                    mv
0816:                            .visitLocalVariable("arg" + i, Type
0817:                                    .getDescriptor(parameters[i]), null, l0,
0818:                                    l1, offset);
0819:                    offset += Type.getType(parameters[i]).getSize();
0820:                }
0821:                mv.visitMaxs(0, 0);
0822:                mv.visitEnd();
0823:            }
0824:
0825:            protected static void buildEquals(final ClassWriter cw,
0826:                    final String className, final Class clazz,
0827:                    final Map fieldTypes) {
0828:                MethodVisitor mv;
0829:                // Building equals method
0830:                {
0831:                    mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "equals", Type
0832:                            .getMethodDescriptor(Type.BOOLEAN_TYPE,
0833:                                    new Type[] { Type.getType(Object.class) }),
0834:                            null, null);
0835:                    mv.visitCode();
0836:                    final Label l0 = new Label();
0837:                    mv.visitLabel(l0);
0838:
0839:                    // if ( this == object || this.delegate == object || this.delegate.equals( object ) ) {
0840:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0841:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0842:                    final Label l1 = new Label();
0843:                    mv.visitJumpInsn(Opcodes.IF_ACMPEQ, l1);
0844:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0845:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0846:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0847:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0848:                    mv.visitJumpInsn(Opcodes.IF_ACMPEQ, l1);
0849:
0850:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0851:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0852:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0853:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0854:                    if (clazz.isInterface()) {
0855:                        mv
0856:                                .visitMethodInsn(
0857:                                        Opcodes.INVOKEINTERFACE,
0858:                                        Type.getInternalName(clazz),
0859:                                        "equals",
0860:                                        Type
0861:                                                .getMethodDescriptor(
0862:                                                        Type.BOOLEAN_TYPE,
0863:                                                        new Type[] { Type
0864:                                                                .getType(Object.class) }));
0865:                    } else {
0866:                        mv
0867:                                .visitMethodInsn(
0868:                                        Opcodes.INVOKEVIRTUAL,
0869:                                        Type.getInternalName(clazz),
0870:                                        "equals",
0871:                                        Type
0872:                                                .getMethodDescriptor(
0873:                                                        Type.BOOLEAN_TYPE,
0874:                                                        new Type[] { Type
0875:                                                                .getType(Object.class) }));
0876:                    }
0877:                    Label l2 = new Label();
0878:                    mv.visitJumpInsn(Opcodes.IFEQ, l2);
0879:
0880:                    //      return true;
0881:                    mv.visitLabel(l1);
0882:                    mv.visitInsn(Opcodes.ICONST_1);
0883:                    mv.visitInsn(Opcodes.IRETURN);
0884:                    mv.visitLabel(l2);
0885:
0886:                    // if (( object == null ) || ( ! ( object instanceof <class> ) ) ) 
0887:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0888:                    final Label l3 = new Label();
0889:                    mv.visitJumpInsn(Opcodes.IFNULL, l3);
0890:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0891:                    mv.visitTypeInsn(Opcodes.INSTANCEOF, Type
0892:                            .getInternalName(clazz));
0893:                    final Label l4 = new Label();
0894:                    mv.visitJumpInsn(Opcodes.IFNE, l4);
0895:
0896:                    //       return false;
0897:                    mv.visitLabel(l3);
0898:                    mv.visitInsn(Opcodes.ICONST_0);
0899:                    mv.visitInsn(Opcodes.IRETURN);
0900:                    mv.visitLabel(l4);
0901:
0902:                    // if( object instanceof ShadowProxy && 
0903:                    //     ( this.delegate == ((ShadowProxy)object).delegate ||
0904:                    //       this.delegate.equals( ((ShadowProxy)object).delegate ) ) ) {
0905:                    Label c0 = new Label();
0906:                    mv.visitLabel(c0);
0907:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0908:                    mv.visitTypeInsn(Opcodes.INSTANCEOF, className);
0909:                    Label c1 = new Label();
0910:                    mv.visitJumpInsn(Opcodes.IFEQ, c1);
0911:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0912:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0913:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0914:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0915:                    mv.visitTypeInsn(Opcodes.CHECKCAST, className);
0916:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0917:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0918:                    Label c2 = new Label();
0919:                    mv.visitJumpInsn(Opcodes.IF_ACMPEQ, c2);
0920:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
0921:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0922:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0923:                    mv.visitVarInsn(Opcodes.ALOAD, 1);
0924:                    mv.visitTypeInsn(Opcodes.CHECKCAST, className);
0925:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
0926:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
0927:                    if (clazz.isInterface()) {
0928:                        mv
0929:                                .visitMethodInsn(
0930:                                        Opcodes.INVOKEINTERFACE,
0931:                                        Type.getInternalName(clazz),
0932:                                        "equals",
0933:                                        Type
0934:                                                .getMethodDescriptor(
0935:                                                        Type.BOOLEAN_TYPE,
0936:                                                        new Type[] { Type
0937:                                                                .getType(Object.class) }));
0938:                    } else {
0939:                        mv
0940:                                .visitMethodInsn(
0941:                                        Opcodes.INVOKEVIRTUAL,
0942:                                        Type.getInternalName(clazz),
0943:                                        "equals",
0944:                                        Type
0945:                                                .getMethodDescriptor(
0946:                                                        Type.BOOLEAN_TYPE,
0947:                                                        new Type[] { Type
0948:                                                                .getType(Object.class) }));
0949:                    }
0950:                    mv.visitJumpInsn(Opcodes.IFEQ, c1);
0951:                    mv.visitLabel(c2);
0952:                    //     return true;
0953:                    mv.visitInsn(Opcodes.ICONST_1);
0954:                    mv.visitInsn(Opcodes.IRETURN);
0955:                    // }
0956:                    mv.visitLabel(c1);
0957:
0958:                    // return false;
0959:                    mv.visitInsn(Opcodes.ICONST_0);
0960:                    mv.visitInsn(Opcodes.IRETURN);
0961:                    final Label lastLabel = new Label();
0962:                    mv.visitLabel(lastLabel);
0963:
0964:                    mv.visitLocalVariable("this", "L" + className + ";", null,
0965:                            l0, lastLabel, 0);
0966:                    mv.visitLocalVariable("object", Type
0967:                            .getDescriptor(Object.class), null, l0, lastLabel,
0968:                            1);
0969:
0970:                    mv.visitMaxs(0, 0);
0971:                    mv.visitEnd();
0972:                }
0973:            }
0974:
0975:            protected static void buildCollectionEquals(final ClassWriter cw,
0976:                    final String className, final Class clazz) {
0977:
0978:                final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
0979:                        "equals", Type.getMethodDescriptor(Type.BOOLEAN_TYPE,
0980:                                new Type[] { Type.getType(Object.class) }),
0981:                        null, null);
0982:                // if ( this == object ) {
0983:                Label l0 = new Label();
0984:                mv.visitLabel(l0);
0985:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0986:                mv.visitVarInsn(Opcodes.ALOAD, 1);
0987:                Label l1 = new Label();
0988:                mv.visitJumpInsn(Opcodes.IF_ACMPNE, l1);
0989:                //    return true;
0990:                Label l2 = new Label();
0991:                mv.visitLabel(l2);
0992:                mv.visitInsn(Opcodes.ICONST_1);
0993:                mv.visitInsn(Opcodes.IRETURN);
0994:                // }
0995:                mv.visitLabel(l1);
0996:                // return this.delegate.equals( object );
0997:                mv.visitVarInsn(Opcodes.ALOAD, 0);
0998:                mv.visitFieldInsn(Opcodes.GETFIELD, className,
0999:                        DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
1000:                mv.visitVarInsn(Opcodes.ALOAD, 1);
1001:                if (clazz.isInterface()) {
1002:                    mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type
1003:                            .getInternalName(clazz), "equals", Type
1004:                            .getMethodDescriptor(Type.BOOLEAN_TYPE,
1005:                                    new Type[] { Type.getType(Object.class) }));
1006:                } else {
1007:                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type
1008:                            .getInternalName(clazz), "equals", Type
1009:                            .getMethodDescriptor(Type.BOOLEAN_TYPE,
1010:                                    new Type[] { Type.getType(Object.class) }));
1011:                }
1012:                mv.visitInsn(Opcodes.IRETURN);
1013:                Label l3 = new Label();
1014:                mv.visitLabel(l3);
1015:                mv.visitLocalVariable("this", "L" + className + ";", null, l0,
1016:                        l3, 0);
1017:                mv.visitLocalVariable("object", Type
1018:                        .getDescriptor(Object.class), null, l0, l3, 1);
1019:                mv.visitMaxs(0, 0);
1020:                mv.visitEnd();
1021:            }
1022:
1023:            /**
1024:             *  Sample of generated code for all primitive + object types
1025:             *  
1026:             *  public int hashCode() {
1027:             *       if( ___hashCache == 0 ) {
1028:             *           __hashCache = this.delegate.hashCode();
1029:             *       }
1030:             *       return this.__hashCache;
1031:             *   }
1032:             * 
1033:             * @param cw
1034:             * @param className
1035:             * @param clazz
1036:             * @param fieldTypes
1037:             */
1038:            protected static void buildHashCode(final ClassWriter cw,
1039:                    final String className, final Class clazz,
1040:                    final Map fieldTypes) {
1041:                MethodVisitor mv;
1042:                // Building hashcode method
1043:                {
1044:                    mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "hashCode", Type
1045:                            .getMethodDescriptor(Type.INT_TYPE, new Type[] {}),
1046:                            null, null);
1047:                    mv.visitCode();
1048:
1049:                    // if( this.__hashCache == 0 ) {
1050:                    Label l0 = new Label();
1051:                    mv.visitLabel(l0);
1052:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
1053:                    mv
1054:                            .visitFieldInsn(Opcodes.GETFIELD, className,
1055:                                    HASHCACHE_FIELD_NAME, Type.INT_TYPE
1056:                                            .getDescriptor());
1057:                    Label l1 = new Label();
1058:                    mv.visitJumpInsn(Opcodes.IFNE, l1);
1059:                    Label l2 = new Label();
1060:
1061:                    //    this.__hashCache = this.delegate.hashCode();
1062:                    mv.visitLabel(l2);
1063:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
1064:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
1065:                    mv.visitFieldInsn(Opcodes.GETFIELD, className,
1066:                            DELEGATE_FIELD_NAME, Type.getDescriptor(clazz));
1067:                    if (clazz.isInterface()) {
1068:                        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type
1069:                                .getInternalName(clazz), "hashCode",
1070:                                Type.getMethodDescriptor(Type.INT_TYPE,
1071:                                        new Type[0]));
1072:                    } else {
1073:                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type
1074:                                .getInternalName(clazz), "hashCode",
1075:                                Type.getMethodDescriptor(Type.INT_TYPE,
1076:                                        new Type[0]));
1077:                    }
1078:                    mv
1079:                            .visitFieldInsn(Opcodes.PUTFIELD, className,
1080:                                    HASHCACHE_FIELD_NAME, Type.INT_TYPE
1081:                                            .getDescriptor());
1082:                    // }
1083:                    mv.visitLabel(l1);
1084:
1085:                    // return this.__hashCache;
1086:                    mv.visitVarInsn(Opcodes.ALOAD, 0);
1087:                    mv
1088:                            .visitFieldInsn(Opcodes.GETFIELD, className,
1089:                                    HASHCACHE_FIELD_NAME, Type.INT_TYPE
1090:                                            .getDescriptor());
1091:                    mv.visitInsn(Opcodes.IRETURN);
1092:                    Label l3 = new Label();
1093:                    mv.visitLabel(l3);
1094:                    mv.visitLocalVariable("this", "L" + className + ";", null,
1095:                            l0, l3, 0);
1096:
1097:                    mv.visitMaxs(0, 0);
1098:                    mv.visitEnd();
1099:                }
1100:            }
1101:
1102:            /**
1103:             * @param exceptionTypes
1104:             * @return
1105:             */
1106:            private static String[] getExceptionArrayAsString(
1107:                    final Class[] exceptionTypes) {
1108:                final String[] exceptions = new String[exceptionTypes.length];
1109:                for (int i = 0; i < exceptions.length; i++) {
1110:                    exceptions[i] = Type.getInternalName(exceptionTypes[i]);
1111:                }
1112:                return exceptions;
1113:            }
1114:
1115:            /**
1116:             * Simple classloader
1117:             * @author Michael Neale
1118:             */
1119:            static class ByteArrayClassLoader extends ClassLoader {
1120:                public ByteArrayClassLoader(final ClassLoader parent) {
1121:                    super (parent);
1122:                }
1123:
1124:                public Class defineClass(final String name, final byte[] bytes,
1125:                        final ProtectionDomain PROTECTION_DOMAIN) {
1126:                    return defineClass(name, bytes, 0, bytes.length,
1127:                            PROTECTION_DOMAIN);
1128:                }
1129:            }
1130:
1131:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.