Source Code Cross Referenced for BytecodeEnhancer.java in  » JMX » je » com » sleepycat » persist » model » 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 » JMX » je » com.sleepycat.persist.model 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*-
0002:         * See the file LICENSE for redistribution information.
0003:         *
0004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
0005:         *
0006:         * $Id: BytecodeEnhancer.java,v 1.11.2.3 2008/01/07 15:14:20 cwl Exp $
0007:         */
0008:
0009:        package com.sleepycat.persist.model;
0010:
0011:        import static com.sleepycat.asm.Opcodes.ACC_ABSTRACT;
0012:        import static com.sleepycat.asm.Opcodes.ACC_PRIVATE;
0013:        import static com.sleepycat.asm.Opcodes.ACC_PUBLIC;
0014:        import static com.sleepycat.asm.Opcodes.ACC_STATIC;
0015:        import static com.sleepycat.asm.Opcodes.ACC_TRANSIENT;
0016:        import static com.sleepycat.asm.Opcodes.ACONST_NULL;
0017:        import static com.sleepycat.asm.Opcodes.ALOAD;
0018:        import static com.sleepycat.asm.Opcodes.ANEWARRAY;
0019:        import static com.sleepycat.asm.Opcodes.ARETURN;
0020:        import static com.sleepycat.asm.Opcodes.BIPUSH;
0021:        import static com.sleepycat.asm.Opcodes.CHECKCAST;
0022:        import static com.sleepycat.asm.Opcodes.DCMPL;
0023:        import static com.sleepycat.asm.Opcodes.DCONST_0;
0024:        import static com.sleepycat.asm.Opcodes.DUP;
0025:        import static com.sleepycat.asm.Opcodes.FCMPL;
0026:        import static com.sleepycat.asm.Opcodes.FCONST_0;
0027:        import static com.sleepycat.asm.Opcodes.GETFIELD;
0028:        import static com.sleepycat.asm.Opcodes.GOTO;
0029:        import static com.sleepycat.asm.Opcodes.ICONST_0;
0030:        import static com.sleepycat.asm.Opcodes.ICONST_1;
0031:        import static com.sleepycat.asm.Opcodes.ICONST_2;
0032:        import static com.sleepycat.asm.Opcodes.ICONST_3;
0033:        import static com.sleepycat.asm.Opcodes.ICONST_4;
0034:        import static com.sleepycat.asm.Opcodes.ICONST_5;
0035:        import static com.sleepycat.asm.Opcodes.IFEQ;
0036:        import static com.sleepycat.asm.Opcodes.IFGT;
0037:        import static com.sleepycat.asm.Opcodes.IFLE;
0038:        import static com.sleepycat.asm.Opcodes.IFNE;
0039:        import static com.sleepycat.asm.Opcodes.IFNONNULL;
0040:        import static com.sleepycat.asm.Opcodes.IF_ICMPNE;
0041:        import static com.sleepycat.asm.Opcodes.ILOAD;
0042:        import static com.sleepycat.asm.Opcodes.INVOKEINTERFACE;
0043:        import static com.sleepycat.asm.Opcodes.INVOKESPECIAL;
0044:        import static com.sleepycat.asm.Opcodes.INVOKESTATIC;
0045:        import static com.sleepycat.asm.Opcodes.INVOKEVIRTUAL;
0046:        import static com.sleepycat.asm.Opcodes.IRETURN;
0047:        import static com.sleepycat.asm.Opcodes.ISUB;
0048:        import static com.sleepycat.asm.Opcodes.LCMP;
0049:        import static com.sleepycat.asm.Opcodes.LCONST_0;
0050:        import static com.sleepycat.asm.Opcodes.NEW;
0051:        import static com.sleepycat.asm.Opcodes.POP;
0052:        import static com.sleepycat.asm.Opcodes.PUTFIELD;
0053:        import static com.sleepycat.asm.Opcodes.RETURN;
0054:
0055:        import java.math.BigInteger;
0056:        import java.util.ArrayList;
0057:        import java.util.Collections;
0058:        import java.util.Comparator;
0059:        import java.util.Date;
0060:        import java.util.HashMap;
0061:        import java.util.List;
0062:        import java.util.Map;
0063:
0064:        import com.sleepycat.asm.AnnotationVisitor;
0065:        import com.sleepycat.asm.Attribute;
0066:        import com.sleepycat.asm.ClassAdapter;
0067:        import com.sleepycat.asm.ClassVisitor;
0068:        import com.sleepycat.asm.FieldVisitor;
0069:        import com.sleepycat.asm.Label;
0070:        import com.sleepycat.asm.MethodVisitor;
0071:        import com.sleepycat.asm.Type;
0072:
0073:        /**
0074:         * An ASM ClassVisitor that examines a class, throws NotPersistentException if
0075:         * it is not persistent, or enhances it if it is persistent.  A class is
0076:         * persistent if it contains the @Entity or @Persistent annotations.  A
0077:         * resulting enhanced class implements the com.sleepycat.persist.impl.Enhanced
0078:         * interface.
0079:         *
0080:         * <p>NotPersistentException is thrown to abort the transformation in order to
0081:         * avoid making two passes over the class file (one to look for the annotations
0082:         * and another to enhance the bytecode) or outputing a class that isn't
0083:         * enhanced.  By aborting the transformation as soon as we detect that the
0084:         * annotations are missing, we make only one partial pass for a non-persistent
0085:         * class.</p>
0086:         *
0087:         * @author Mark Hayes
0088:         */
0089:        class BytecodeEnhancer extends ClassAdapter {
0090:
0091:            /** Thrown when we determine that a class is not persistent. */
0092:            static class NotPersistentException extends RuntimeException {
0093:            }
0094:
0095:            /** A static instance is used to avoid fillInStaceTrace overhead. */
0096:            private static final NotPersistentException NOT_PERSISTENT = new NotPersistentException();
0097:
0098:            private static final Map<String, Integer> PRIMITIVE_WRAPPERS = new HashMap<String, Integer>();
0099:            static {
0100:                PRIMITIVE_WRAPPERS.put(Boolean.class.getName(), Type.BOOLEAN);
0101:                PRIMITIVE_WRAPPERS.put(Character.class.getName(), Type.CHAR);
0102:                PRIMITIVE_WRAPPERS.put(Byte.class.getName(), Type.BYTE);
0103:                PRIMITIVE_WRAPPERS.put(Short.class.getName(), Type.SHORT);
0104:                PRIMITIVE_WRAPPERS.put(Integer.class.getName(), Type.INT);
0105:                PRIMITIVE_WRAPPERS.put(Long.class.getName(), Type.LONG);
0106:                PRIMITIVE_WRAPPERS.put(Float.class.getName(), Type.FLOAT);
0107:                PRIMITIVE_WRAPPERS.put(Double.class.getName(), Type.DOUBLE);
0108:            }
0109:
0110:            private String className;
0111:            private String super className;
0112:            private boolean isPersistent;
0113:            private boolean isAbstract;
0114:            private boolean hasDefaultConstructor;
0115:            private boolean hasPersistentSuperclass;
0116:            private boolean isCompositeKey;
0117:            private FieldInfo priKeyField;
0118:            private List<FieldInfo> secKeyFields;
0119:            private List<FieldInfo> nonKeyFields;
0120:            private String staticBlockMethod;
0121:
0122:            BytecodeEnhancer(ClassVisitor parentVisitor) {
0123:                super (parentVisitor);
0124:                secKeyFields = new ArrayList<FieldInfo>();
0125:                nonKeyFields = new ArrayList<FieldInfo>();
0126:            }
0127:
0128:            @Override
0129:            public void visit(int version, int access, String name, String sig,
0130:                    String super Name, String[] interfaces) {
0131:                className = name;
0132:                super className = super Name;
0133:                final String ENHANCED = "com/sleepycat/persist/impl/Enhanced";
0134:                if (containsString(interfaces, ENHANCED)) {
0135:                    throw abort();
0136:                }
0137:                interfaces = appendString(interfaces, ENHANCED);
0138:                isAbstract = ((access & ACC_ABSTRACT) != 0);
0139:                hasPersistentSuperclass = (super Name != null && !super Name
0140:                        .equals("java/lang/Object"));
0141:                super .visit(version, access, name, sig, super Name, interfaces);
0142:            }
0143:
0144:            @Override
0145:            public void visitSource(String source, String debug) {
0146:                super .visitSource(source, debug);
0147:            }
0148:
0149:            @Override
0150:            public AnnotationVisitor visitAnnotation(String desc,
0151:                    boolean visible) {
0152:                if (desc.equals("Lcom/sleepycat/persist/model/Entity;")
0153:                        || desc
0154:                                .equals("Lcom/sleepycat/persist/model/Persistent;")) {
0155:                    isPersistent = true;
0156:                }
0157:                return super .visitAnnotation(desc, visible);
0158:            }
0159:
0160:            @Override
0161:            public FieldVisitor visitField(int access, String name,
0162:                    String desc, String sig, Object value) {
0163:                if (!isPersistent) {
0164:                    throw abort();
0165:                }
0166:                FieldVisitor ret = super .visitField(access, name, desc, sig,
0167:                        value);
0168:                if ((access & (ACC_STATIC | ACC_TRANSIENT)) == 0) {
0169:                    FieldInfo info = new FieldInfo(ret, name, desc);
0170:                    nonKeyFields.add(info);
0171:                    ret = info;
0172:                }
0173:                return ret;
0174:            }
0175:
0176:            @Override
0177:            public MethodVisitor visitMethod(int access, String name,
0178:                    String desc, String sig, String[] exceptions) {
0179:                if (!isPersistent) {
0180:                    throw abort();
0181:                }
0182:                if ("<init>".equals(name) && "()V".equals(desc)) {
0183:                    hasDefaultConstructor = true;
0184:                }
0185:                if ("<clinit>".equals(name)) {
0186:                    if (staticBlockMethod != null) {
0187:                        throw new IllegalStateException();
0188:                    }
0189:                    staticBlockMethod = "bdbExistingStaticBlock";
0190:                    return cv.visitMethod(ACC_PRIVATE + ACC_STATIC,
0191:                            staticBlockMethod, "()V", null, null);
0192:                }
0193:                return super .visitMethod(access, name, desc, sig, exceptions);
0194:            }
0195:
0196:            @Override
0197:            public void visitEnd() {
0198:                if (!isPersistent || !hasDefaultConstructor) {
0199:                    throw abort();
0200:                }
0201:                /* Generate new code at the end of the class. */
0202:                sortFields();
0203:                genBdbNewInstance();
0204:                genBdbNewArray();
0205:                genBdbIsPriKeyFieldNullOrZero();
0206:                genBdbWritePriKeyField();
0207:                genBdbReadPriKeyField();
0208:                genBdbWriteSecKeyFields();
0209:                genBdbReadSecKeyFields();
0210:                genBdbWriteNonKeyFields();
0211:                genBdbReadNonKeyFields();
0212:                genBdbGetField();
0213:                genBdbSetField();
0214:                genStaticBlock();
0215:                super .visitEnd();
0216:            }
0217:
0218:            private void sortFields() {
0219:                /*
0220:                System.out.println("AllFields: " + nonKeyFields);
0221:                //*/
0222:                if (nonKeyFields.size() == 0) {
0223:                    return;
0224:                }
0225:                isCompositeKey = true;
0226:                for (FieldInfo field : nonKeyFields) {
0227:                    if (field.order == null) {
0228:                        isCompositeKey = false;
0229:                    }
0230:                }
0231:                if (isCompositeKey) {
0232:                    Collections.sort(nonKeyFields, new Comparator<FieldInfo>() {
0233:                        public int compare(FieldInfo f1, FieldInfo f2) {
0234:                            return f1.order.value - f2.order.value;
0235:                        }
0236:                    });
0237:                } else {
0238:                    for (int i = 0; i < nonKeyFields.size();) {
0239:                        FieldInfo field = nonKeyFields.get(i);
0240:                        if (field.isPriKey) {
0241:                            if (priKeyField == null) {
0242:                                priKeyField = field;
0243:                                nonKeyFields.remove(i);
0244:                            }
0245:                        } else if (field.isSecKey) {
0246:                            secKeyFields.add(field);
0247:                            nonKeyFields.remove(i);
0248:                        } else {
0249:                            i += 1;
0250:                        }
0251:                    }
0252:                    Comparator<FieldInfo> cmp = new Comparator<FieldInfo>() {
0253:                        public int compare(FieldInfo f1, FieldInfo f2) {
0254:                            return f1.name.compareTo(f2.name);
0255:                        }
0256:                    };
0257:                    Collections.sort(secKeyFields, cmp);
0258:                    Collections.sort(nonKeyFields, cmp);
0259:                }
0260:                /*
0261:                System.out.println("PriKey: " + priKeyField);
0262:                System.out.println("SecKeys: " + secKeyFields);
0263:                System.out.println("NonKeys: " + nonKeyFields);
0264:                //*/
0265:            }
0266:
0267:            /**
0268:             * Outputs code in a static block to register the prototype instance:
0269:             *
0270:             *  static {
0271:             *      EnhancedAccessor.registerClass(TheClassName, new TheClass());
0272:             *      // or for an abstract class:
0273:             *      EnhancedAccessor.registerClass(TheClassName, null);
0274:             *  }
0275:             */
0276:            private void genStaticBlock() {
0277:                MethodVisitor mv = cv.visitMethod(ACC_STATIC, "<clinit>",
0278:                        "()V", null, null);
0279:                mv.visitCode();
0280:                if (staticBlockMethod != null) {
0281:                    mv.visitMethodInsn(INVOKESTATIC, className,
0282:                            staticBlockMethod, "()V");
0283:                }
0284:                mv.visitLdcInsn(className.replace('/', '.'));
0285:                if (isAbstract) {
0286:                    mv.visitInsn(ACONST_NULL);
0287:                } else {
0288:                    mv.visitTypeInsn(NEW, className);
0289:                    mv.visitInsn(DUP);
0290:                    mv.visitMethodInsn(INVOKESPECIAL, className, "<init>",
0291:                            "()V");
0292:                }
0293:                mv
0294:                        .visitMethodInsn(INVOKESTATIC,
0295:                                "com/sleepycat/persist/impl/EnhancedAccessor",
0296:                                "registerClass",
0297:                                "(Ljava/lang/String;Lcom/sleepycat/persist/impl/Enhanced;)V");
0298:                mv.visitInsn(RETURN);
0299:                mv.visitMaxs(3, 0);
0300:                mv.visitEnd();
0301:            }
0302:
0303:            /**
0304:             *  public Object bdbNewInstance() {
0305:             *      return new TheClass();
0306:             *      // or if abstract:
0307:             *      return null;
0308:             *  }
0309:             */
0310:            private void genBdbNewInstance() {
0311:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "bdbNewInstance",
0312:                        "()Ljava/lang/Object;", null, null);
0313:                mv.visitCode();
0314:                if (isAbstract) {
0315:                    mv.visitInsn(ACONST_NULL);
0316:                    mv.visitInsn(ARETURN);
0317:                    mv.visitMaxs(1, 1);
0318:                } else {
0319:                    mv.visitTypeInsn(NEW, className);
0320:                    mv.visitInsn(DUP);
0321:                    mv.visitMethodInsn(INVOKESPECIAL, className, "<init>",
0322:                            "()V");
0323:                    mv.visitInsn(ARETURN);
0324:                    mv.visitMaxs(2, 1);
0325:                }
0326:                mv.visitEnd();
0327:            }
0328:
0329:            /**
0330:             *  public Object bdbNewArray(int len) {
0331:             *      return new TheClass[len];
0332:             *      // or if abstract:
0333:             *      return null;
0334:             *  }
0335:             */
0336:            private void genBdbNewArray() {
0337:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "bdbNewArray",
0338:                        "(I)Ljava/lang/Object;", null, null);
0339:                mv.visitCode();
0340:                if (isAbstract) {
0341:                    mv.visitInsn(ACONST_NULL);
0342:                    mv.visitInsn(ARETURN);
0343:                    mv.visitMaxs(1, 2);
0344:                } else {
0345:                    mv.visitVarInsn(ILOAD, 1);
0346:                    mv.visitTypeInsn(ANEWARRAY, className);
0347:                    mv.visitInsn(ARETURN);
0348:                    mv.visitMaxs(1, 2);
0349:                    mv.visitEnd();
0350:                }
0351:            }
0352:
0353:            /**
0354:             *  public boolean bdbIsPriKeyFieldNullOrZero() {
0355:             *      return theField == null; // or zero or false, as appropriate
0356:             *      // or if no primary key but has superclass:
0357:             *      return super.bdbIsPriKeyFieldNullOrZero();
0358:             *  }
0359:             */
0360:            private void genBdbIsPriKeyFieldNullOrZero() {
0361:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0362:                        "bdbIsPriKeyFieldNullOrZero", "()Z", null, null);
0363:                mv.visitCode();
0364:                if (priKeyField != null) {
0365:                    mv.visitVarInsn(ALOAD, 0);
0366:                    mv.visitFieldInsn(GETFIELD, className, priKeyField.name,
0367:                            priKeyField.type.getDescriptor());
0368:                    Label l0 = new Label();
0369:                    if (isRefType(priKeyField.type)) {
0370:                        mv.visitJumpInsn(IFNONNULL, l0);
0371:                    } else {
0372:                        genBeforeCompareToZero(mv, priKeyField.type);
0373:                        mv.visitJumpInsn(IFNE, l0);
0374:                    }
0375:                    mv.visitInsn(ICONST_1);
0376:                    Label l1 = new Label();
0377:                    mv.visitJumpInsn(GOTO, l1);
0378:                    mv.visitLabel(l0);
0379:                    mv.visitInsn(ICONST_0);
0380:                    mv.visitLabel(l1);
0381:                } else if (hasPersistentSuperclass) {
0382:                    mv.visitVarInsn(ALOAD, 0);
0383:                    mv.visitMethodInsn(INVOKESPECIAL, super className,
0384:                            "bdbIsPriKeyFieldNullOrZero", "()Z");
0385:                } else {
0386:                    mv.visitInsn(ICONST_0);
0387:                }
0388:                mv.visitInsn(IRETURN);
0389:                mv.visitMaxs(1, 1);
0390:                mv.visitEnd();
0391:            }
0392:
0393:            /**
0394:             *  public void bdbWritePriKeyField(EntityOutput output, Format format) {
0395:             *      output.writeKeyObject(theField, format);
0396:             *      // or
0397:             *      output.writeInt(theField); // and other simple types
0398:             *      // or if no primary key but has superclass:
0399:             *      return super.bdbWritePriKeyField(output, format);
0400:             *  }
0401:             */
0402:            private void genBdbWritePriKeyField() {
0403:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0404:                        "bdbWritePriKeyField",
0405:                        "(Lcom/sleepycat/persist/impl/EntityOutput;"
0406:                                + "Lcom/sleepycat/persist/impl/Format;)V",
0407:                        null, null);
0408:                mv.visitCode();
0409:                if (priKeyField != null) {
0410:                    if (!genWriteSimpleKeyField(mv, priKeyField)) {
0411:                        /* For a non-simple type, call EntityOutput.writeKeyObject. */
0412:                        mv.visitVarInsn(ALOAD, 1);
0413:                        mv.visitVarInsn(ALOAD, 0);
0414:                        mv.visitFieldInsn(GETFIELD, className,
0415:                                priKeyField.name, priKeyField.type
0416:                                        .getDescriptor());
0417:                        mv.visitVarInsn(ALOAD, 2);
0418:                        mv
0419:                                .visitMethodInsn(
0420:                                        INVOKEINTERFACE,
0421:                                        "com/sleepycat/persist/impl/EntityOutput",
0422:                                        "writeKeyObject",
0423:                                        "(Ljava/lang/Object;"
0424:                                                + "Lcom/sleepycat/persist/impl/Format;)V");
0425:                    }
0426:                } else if (hasPersistentSuperclass) {
0427:                    mv.visitVarInsn(ALOAD, 0);
0428:                    mv.visitVarInsn(ALOAD, 1);
0429:                    mv.visitVarInsn(ALOAD, 2);
0430:                    mv.visitMethodInsn(INVOKESPECIAL, super className,
0431:                            "bdbWritePriKeyField",
0432:                            "(Lcom/sleepycat/persist/impl/EntityOutput;"
0433:                                    + "Lcom/sleepycat/persist/impl/Format;)V");
0434:                }
0435:                mv.visitInsn(RETURN);
0436:                mv.visitMaxs(3, 3);
0437:                mv.visitEnd();
0438:            }
0439:
0440:            /**
0441:             *  public void bdbReadPriKeyField(EntityInput input, Format format) {
0442:             *      theField = (TheFieldClass) input.readKeyObject(format);
0443:             *      // or
0444:             *      theField = input.readInt(); // and other simple types
0445:             *      // or if no primary key but has superclass:
0446:             *      super.bdbReadPriKeyField(input, format);
0447:             *  }
0448:             */
0449:            private void genBdbReadPriKeyField() {
0450:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0451:                        "bdbReadPriKeyField",
0452:                        "(Lcom/sleepycat/persist/impl/EntityInput;"
0453:                                + "Lcom/sleepycat/persist/impl/Format;)V",
0454:                        null, null);
0455:                mv.visitCode();
0456:                if (priKeyField != null) {
0457:                    if (!genReadSimpleKeyField(mv, priKeyField)) {
0458:                        /* For a non-simple type, call EntityInput.readKeyObject. */
0459:                        mv.visitVarInsn(ALOAD, 0);
0460:                        mv.visitVarInsn(ALOAD, 1);
0461:                        mv.visitVarInsn(ALOAD, 2);
0462:                        mv.visitMethodInsn(INVOKEINTERFACE,
0463:                                "com/sleepycat/persist/impl/EntityInput",
0464:                                "readKeyObject",
0465:                                "(Lcom/sleepycat/persist/impl/Format;)"
0466:                                        + "Ljava/lang/Object;");
0467:                        mv.visitTypeInsn(CHECKCAST,
0468:                                getTypeInstName(priKeyField.type));
0469:                        mv.visitFieldInsn(PUTFIELD, className,
0470:                                priKeyField.name, priKeyField.type
0471:                                        .getDescriptor());
0472:                    }
0473:                } else if (hasPersistentSuperclass) {
0474:                    mv.visitVarInsn(ALOAD, 0);
0475:                    mv.visitVarInsn(ALOAD, 1);
0476:                    mv.visitVarInsn(ALOAD, 2);
0477:                    mv.visitMethodInsn(INVOKESPECIAL, super className,
0478:                            "bdbReadPriKeyField",
0479:                            "(Lcom/sleepycat/persist/impl/EntityInput;"
0480:                                    + "Lcom/sleepycat/persist/impl/Format;)V");
0481:                }
0482:                mv.visitInsn(RETURN);
0483:                mv.visitMaxs(3, 3);
0484:                mv.visitEnd();
0485:            }
0486:
0487:            /**
0488:             *  public void bdbWriteSecKeyFields(EntityOutput output) {
0489:             *      output.registerPriKeyObject(priKeyField); // if an object
0490:             *      super.bdbWriteSecKeyFields(EntityOutput output); // if has super
0491:             *      output.writeInt(secKeyField1);
0492:             *      output.writeObject(secKeyField2, null);
0493:             *      // etc
0494:             *  }
0495:             */
0496:            private void genBdbWriteSecKeyFields() {
0497:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0498:                        "bdbWriteSecKeyFields",
0499:                        "(Lcom/sleepycat/persist/impl/EntityOutput;)V", null,
0500:                        null);
0501:                mv.visitCode();
0502:                if (priKeyField != null && isRefType(priKeyField.type)) {
0503:                    genRegisterPrimaryKey(mv, false);
0504:                }
0505:                if (hasPersistentSuperclass) {
0506:                    mv.visitVarInsn(ALOAD, 0);
0507:                    mv.visitVarInsn(ALOAD, 1);
0508:                    mv.visitMethodInsn(INVOKESPECIAL, super className,
0509:                            "bdbWriteSecKeyFields",
0510:                            "(Lcom/sleepycat/persist/impl/EntityOutput;)V");
0511:                }
0512:                for (FieldInfo field : secKeyFields) {
0513:                    genWriteField(mv, field);
0514:                }
0515:                mv.visitInsn(RETURN);
0516:                mv.visitMaxs(2, 2);
0517:                mv.visitEnd();
0518:            }
0519:
0520:            /**
0521:             *  public void bdbReadSecKeyFields(EntityInput input,
0522:             *                                  int startField,
0523:             *                                  int endField,
0524:             *                                  int superLevel) {
0525:             *      input.registerPriKeyObject(priKeyField); // if an object
0526:             *      // if has super:
0527:             *      if (superLevel != 0) {
0528:             *          super.bdbReadSecKeyFields(..., superLevel - 1);
0529:             *      }
0530:             *      if (superLevel <= 0) {
0531:             *          switch (startField) {
0532:             *          case 0:
0533:             *              secKeyField1 = input.readInt();
0534:             *              if (endField == 0) break;
0535:             *          case 1:
0536:             *              secKeyField2 = (String) input.readObject();
0537:             *              if (endField == 1) break;
0538:             *          case 2:
0539:             *              secKeyField3 = input.readInt();
0540:             *          }
0541:             *      }
0542:             *  }
0543:             */
0544:            private void genBdbReadSecKeyFields() {
0545:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0546:                        "bdbReadSecKeyFields",
0547:                        "(Lcom/sleepycat/persist/impl/EntityInput;III)V", null,
0548:                        null);
0549:                mv.visitCode();
0550:                if (priKeyField != null && isRefType(priKeyField.type)) {
0551:                    genRegisterPrimaryKey(mv, true);
0552:                }
0553:                genReadSuperKeyFields(mv, true);
0554:                genReadFieldSwitch(mv, secKeyFields);
0555:                mv.visitInsn(RETURN);
0556:                mv.visitMaxs(5, 5);
0557:                mv.visitEnd();
0558:            }
0559:
0560:            /**
0561:             *      output.registerPriKeyObject(priKeyField);
0562:             *      // or
0563:             *      input.registerPriKeyObject(priKeyField);
0564:             */
0565:            private void genRegisterPrimaryKey(MethodVisitor mv, boolean input) {
0566:                String entityInputOrOutputClass = input ? "com/sleepycat/persist/impl/EntityInput"
0567:                        : "com/sleepycat/persist/impl/EntityOutput";
0568:                mv.visitVarInsn(ALOAD, 1);
0569:                mv.visitVarInsn(ALOAD, 0);
0570:                mv.visitFieldInsn(GETFIELD, className, priKeyField.name,
0571:                        priKeyField.type.getDescriptor());
0572:                mv.visitMethodInsn(INVOKEINTERFACE, entityInputOrOutputClass,
0573:                        "registerPriKeyObject", "(Ljava/lang/Object;)V");
0574:            }
0575:
0576:            /**
0577:             *  public void bdbWriteNonKeyFields(EntityOutput output) {
0578:             *      super.bdbWriteNonKeyFields(output); // if has super
0579:             *      output.writeInt(nonKeyField1);
0580:             *      output.writeObject(nonKeyField2, null);
0581:             *      // etc
0582:             *  }
0583:             */
0584:            private void genBdbWriteNonKeyFields() {
0585:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0586:                        "bdbWriteNonKeyFields",
0587:                        "(Lcom/sleepycat/persist/impl/EntityOutput;)V", null,
0588:                        null);
0589:                mv.visitCode();
0590:                if (hasPersistentSuperclass) {
0591:                    mv.visitVarInsn(ALOAD, 0);
0592:                    mv.visitVarInsn(ALOAD, 1);
0593:                    mv.visitMethodInsn(INVOKESPECIAL, super className,
0594:                            "bdbWriteNonKeyFields",
0595:                            "(Lcom/sleepycat/persist/impl/EntityOutput;)V");
0596:                }
0597:                if (isCompositeKey) {
0598:                    for (FieldInfo field : nonKeyFields) {
0599:                        genWriteSimpleKeyField(mv, field);
0600:                        /* Ignore non-simple (illegal) types for composite key. */
0601:                    }
0602:                } else {
0603:                    for (FieldInfo field : nonKeyFields) {
0604:                        genWriteField(mv, field);
0605:                    }
0606:                }
0607:                mv.visitInsn(RETURN);
0608:                mv.visitMaxs(2, 2);
0609:                mv.visitEnd();
0610:            }
0611:
0612:            /**
0613:             *  public void bdbReadNonKeyFields(EntityInput input,
0614:             *                                  int startField,
0615:             *                                  int endField,
0616:             *                                  int superLevel) {
0617:             *      // if has super:
0618:             *      if (superLevel != 0) {
0619:             *          super.bdbReadNonKeyFields(..., superLevel - 1);
0620:             *      }
0621:             *      nonKeyField1 = input.readInt();
0622:             *      nonKeyField2 = (String) input.readObject();
0623:             *      // etc
0624:             *      // or like bdbReadSecKeyFields if not a composite key class
0625:             *  }
0626:             */
0627:            private void genBdbReadNonKeyFields() {
0628:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC,
0629:                        "bdbReadNonKeyFields",
0630:                        "(Lcom/sleepycat/persist/impl/EntityInput;III)V", null,
0631:                        null);
0632:                mv.visitCode();
0633:                if (isCompositeKey) {
0634:                    for (FieldInfo field : nonKeyFields) {
0635:                        genReadSimpleKeyField(mv, field);
0636:                        /* Ignore non-simple (illegal) types for composite key. */
0637:                    }
0638:                } else {
0639:                    genReadSuperKeyFields(mv, false);
0640:                    genReadFieldSwitch(mv, nonKeyFields);
0641:                }
0642:                mv.visitInsn(RETURN);
0643:                mv.visitMaxs(5, 5);
0644:                mv.visitEnd();
0645:            }
0646:
0647:            /**
0648:             *      output.writeInt(field); // and other primitives
0649:             *      // or
0650:             *      output.writeObject(field, null);
0651:             */
0652:            private void genWriteField(MethodVisitor mv, FieldInfo field) {
0653:                mv.visitVarInsn(ALOAD, 1);
0654:                mv.visitVarInsn(ALOAD, 0);
0655:                mv.visitFieldInsn(GETFIELD, className, field.name, field.type
0656:                        .getDescriptor());
0657:                int sort = field.type.getSort();
0658:                if (sort == Type.OBJECT || sort == Type.ARRAY) {
0659:                    mv.visitInsn(ACONST_NULL);
0660:                    mv
0661:                            .visitMethodInsn(INVOKEINTERFACE,
0662:                                    "com/sleepycat/persist/impl/EntityOutput",
0663:                                    "writeObject",
0664:                                    "(Ljava/lang/Object;Lcom/sleepycat/persist/impl/Format;)V");
0665:                } else {
0666:                    genWritePrimitive(mv, sort);
0667:                }
0668:            }
0669:
0670:            /**
0671:             * Generates writing of a simple type key field, or returns false if the
0672:             * key field is not a simple type (i.e., it is a composite key type).
0673:             *
0674:             *      output.writeInt(theField); // and other primitives
0675:             *      // or
0676:             *      output.writeInt(theField.intValue()); // and other simple types
0677:             *      // or returns false
0678:             */
0679:            private boolean genWriteSimpleKeyField(MethodVisitor mv,
0680:                    FieldInfo field) {
0681:                if (genWritePrimitiveField(mv, field)) {
0682:                    return true;
0683:                }
0684:                String fieldClassName = field.type.getClassName();
0685:                if (!isSimpleRefType(fieldClassName)) {
0686:                    return false;
0687:                }
0688:                mv.visitVarInsn(ALOAD, 1);
0689:                mv.visitVarInsn(ALOAD, 0);
0690:                mv.visitFieldInsn(GETFIELD, className, field.name, field.type
0691:                        .getDescriptor());
0692:                Integer sort = PRIMITIVE_WRAPPERS.get(fieldClassName);
0693:                if (sort != null) {
0694:                    genUnwrapPrimitive(mv, sort);
0695:                    genWritePrimitive(mv, sort);
0696:                } else if (fieldClassName.equals(Date.class.getName())) {
0697:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Date",
0698:                            "getTime", "()J");
0699:                    genWritePrimitive(mv, Type.LONG);
0700:                } else if (fieldClassName.equals(String.class.getName())) {
0701:                    mv
0702:                            .visitMethodInsn(INVOKEINTERFACE,
0703:                                    "com/sleepycat/persist/impl/EntityOutput",
0704:                                    "writeString",
0705:                                    "(Ljava/lang/String;)Lcom/sleepycat/bind/tuple/TupleOutput;");
0706:                    mv.visitInsn(POP);
0707:                } else if (fieldClassName.equals(BigInteger.class.getName())) {
0708:                    mv
0709:                            .visitMethodInsn(INVOKEINTERFACE,
0710:                                    "com/sleepycat/persist/impl/EntityOutput",
0711:                                    "writeBigInteger",
0712:                                    "(Ljava/math/BigInteger;)Lcom/sleepycat/bind/tuple/TupleOutput;");
0713:                    mv.visitInsn(POP);
0714:                } else {
0715:                    throw new IllegalStateException(fieldClassName);
0716:                }
0717:                return true;
0718:            }
0719:
0720:            private boolean genWritePrimitiveField(MethodVisitor mv,
0721:                    FieldInfo field) {
0722:                int sort = field.type.getSort();
0723:                if (sort == Type.OBJECT || sort == Type.ARRAY) {
0724:                    return false;
0725:                }
0726:                mv.visitVarInsn(ALOAD, 1);
0727:                mv.visitVarInsn(ALOAD, 0);
0728:                mv.visitFieldInsn(GETFIELD, className, field.name, field.type
0729:                        .getDescriptor());
0730:                genWritePrimitive(mv, sort);
0731:                return true;
0732:            }
0733:
0734:            /**
0735:             *      // if has super:
0736:             *      if (superLevel != 0) {
0737:             *          super.bdbReadXxxKeyFields(..., superLevel - 1);
0738:             *      }
0739:             */
0740:            private void genReadSuperKeyFields(MethodVisitor mv,
0741:                    boolean areSecKeyFields) {
0742:                if (hasPersistentSuperclass) {
0743:                    Label next = new Label();
0744:                    mv.visitVarInsn(ILOAD, 4);
0745:                    mv.visitJumpInsn(IFEQ, next);
0746:                    mv.visitVarInsn(ALOAD, 0);
0747:                    mv.visitVarInsn(ALOAD, 1);
0748:                    mv.visitVarInsn(ILOAD, 2);
0749:                    mv.visitVarInsn(ILOAD, 3);
0750:                    mv.visitVarInsn(ILOAD, 4);
0751:                    mv.visitInsn(ICONST_1);
0752:                    mv.visitInsn(ISUB);
0753:                    String name = areSecKeyFields ? "bdbReadSecKeyFields"
0754:                            : "bdbReadNonKeyFields";
0755:                    mv.visitMethodInsn(INVOKESPECIAL, super className, name,
0756:                            "(Lcom/sleepycat/persist/impl/EntityInput;III)V");
0757:                    mv.visitLabel(next);
0758:                }
0759:            }
0760:
0761:            /**
0762:             *  public void bdbReadXxxKeyFields(EntityInput input,
0763:             *                                  int startField,
0764:             *                                  int endField,
0765:             *                                  int superLevel) {
0766:             *      // ...
0767:             *      if (superLevel <= 0) {
0768:             *          switch (startField) {
0769:             *          case 0:
0770:             *              keyField1 = input.readInt();
0771:             *              if (endField == 0) break;
0772:             *          case 1:
0773:             *              keyField2 = (String) input.readObject();
0774:             *              if (endField == 1) break;
0775:             *          case 2:
0776:             *              keyField3 = input.readInt();
0777:             *          }
0778:             *      }
0779:             */
0780:            private void genReadFieldSwitch(MethodVisitor mv,
0781:                    List<FieldInfo> fields) {
0782:                int nFields = fields.size();
0783:                if (nFields > 0) {
0784:                    mv.visitVarInsn(ILOAD, 4);
0785:                    Label pastSwitch = new Label();
0786:                    mv.visitJumpInsn(IFGT, pastSwitch);
0787:                    Label[] labels = new Label[nFields];
0788:                    for (int i = 0; i < nFields; i += 1) {
0789:                        labels[i] = new Label();
0790:                    }
0791:                    mv.visitVarInsn(ILOAD, 2);
0792:                    mv.visitTableSwitchInsn(0, nFields - 1, pastSwitch, labels);
0793:                    for (int i = 0; i < nFields; i += 1) {
0794:                        FieldInfo field = fields.get(i);
0795:                        mv.visitLabel(labels[i]);
0796:                        genReadField(mv, field);
0797:                        if (i < nFields - 1) {
0798:                            Label nextCase = labels[i + 1];
0799:                            mv.visitVarInsn(ILOAD, 3);
0800:                            if (i == 0) {
0801:                                mv.visitJumpInsn(IFNE, nextCase);
0802:                            } else {
0803:                                switch (i) {
0804:                                case 1:
0805:                                    mv.visitInsn(ICONST_1);
0806:                                    break;
0807:                                case 2:
0808:                                    mv.visitInsn(ICONST_2);
0809:                                    break;
0810:                                case 3:
0811:                                    mv.visitInsn(ICONST_3);
0812:                                    break;
0813:                                case 4:
0814:                                    mv.visitInsn(ICONST_4);
0815:                                    break;
0816:                                case 5:
0817:                                    mv.visitInsn(ICONST_5);
0818:                                    break;
0819:                                default:
0820:                                    mv.visitIntInsn(BIPUSH, i);
0821:                                }
0822:                                mv.visitJumpInsn(IF_ICMPNE, nextCase);
0823:                            }
0824:                            mv.visitJumpInsn(GOTO, pastSwitch);
0825:                        }
0826:                    }
0827:                    mv.visitLabel(pastSwitch);
0828:                }
0829:            }
0830:
0831:            /**
0832:             *      field = input.readInt(); // and other primitives
0833:             *      // or
0834:             *      field = (FieldClass) input.readObject();
0835:             */
0836:            private void genReadField(MethodVisitor mv, FieldInfo field) {
0837:                mv.visitVarInsn(ALOAD, 0);
0838:                mv.visitVarInsn(ALOAD, 1);
0839:                if (isRefType(field.type)) {
0840:                    mv.visitMethodInsn(INVOKEINTERFACE,
0841:                            "com/sleepycat/persist/impl/EntityInput",
0842:                            "readObject", "()Ljava/lang/Object;");
0843:                    mv.visitTypeInsn(CHECKCAST, getTypeInstName(field.type));
0844:                } else {
0845:                    genReadPrimitive(mv, field.type.getSort());
0846:                }
0847:                mv.visitFieldInsn(PUTFIELD, className, field.name, field.type
0848:                        .getDescriptor());
0849:            }
0850:
0851:            /**
0852:             * Generates reading of a simple type key field, or returns false if the
0853:             * key field is not a simple type (i.e., it is a composite key type).
0854:             *
0855:             *      field = input.readInt(); // and other primitives
0856:             *      // or
0857:             *      field = Integer.valueOf(input.readInt()); // and other simple types
0858:             *      // or returns false
0859:             */
0860:            private boolean genReadSimpleKeyField(MethodVisitor mv,
0861:                    FieldInfo field) {
0862:                if (genReadPrimitiveField(mv, field)) {
0863:                    return true;
0864:                }
0865:                String fieldClassName = field.type.getClassName();
0866:                if (!isSimpleRefType(fieldClassName)) {
0867:                    return false;
0868:                }
0869:                Integer sort = PRIMITIVE_WRAPPERS.get(fieldClassName);
0870:                if (sort != null) {
0871:                    mv.visitVarInsn(ALOAD, 0);
0872:                    mv.visitVarInsn(ALOAD, 1);
0873:                    genReadPrimitive(mv, sort);
0874:                    genWrapPrimitive(mv, sort);
0875:                } else if (fieldClassName.equals(Date.class.getName())) {
0876:                    /* Date is a special case because we use NEW instead of valueOf. */
0877:                    mv.visitVarInsn(ALOAD, 0);
0878:                    mv.visitTypeInsn(NEW, "java/util/Date");
0879:                    mv.visitInsn(DUP);
0880:                    mv.visitVarInsn(ALOAD, 1);
0881:                    genReadPrimitive(mv, Type.LONG);
0882:                    mv.visitMethodInsn(INVOKESPECIAL, "java/util/Date",
0883:                            "<init>", "(J)V");
0884:                } else if (fieldClassName.equals(String.class.getName())) {
0885:                    mv.visitVarInsn(ALOAD, 0);
0886:                    mv.visitVarInsn(ALOAD, 1);
0887:                    mv.visitMethodInsn(INVOKEINTERFACE,
0888:                            "com/sleepycat/persist/impl/EntityInput",
0889:                            "readString", "()Ljava/lang/String;");
0890:                } else if (fieldClassName.equals(BigInteger.class.getName())) {
0891:                    mv.visitVarInsn(ALOAD, 0);
0892:                    mv.visitVarInsn(ALOAD, 1);
0893:                    mv.visitMethodInsn(INVOKEINTERFACE,
0894:                            "com/sleepycat/persist/impl/EntityInput",
0895:                            "readBigInteger", "()Ljava/math/BigInteger;");
0896:                } else {
0897:                    throw new IllegalStateException(fieldClassName);
0898:                }
0899:                mv.visitFieldInsn(PUTFIELD, className, field.name, field.type
0900:                        .getDescriptor());
0901:                return true;
0902:            }
0903:
0904:            private boolean genReadPrimitiveField(MethodVisitor mv,
0905:                    FieldInfo field) {
0906:                int sort = field.type.getSort();
0907:                if (sort == Type.OBJECT || sort == Type.ARRAY) {
0908:                    return false;
0909:                }
0910:                mv.visitVarInsn(ALOAD, 0);
0911:                mv.visitVarInsn(ALOAD, 1);
0912:                genReadPrimitive(mv, sort);
0913:                mv.visitFieldInsn(PUTFIELD, className, field.name, field.type
0914:                        .getDescriptor());
0915:                return true;
0916:            }
0917:
0918:            /**
0919:             *  public Object bdbGetField(Object o,
0920:             *                            int field,
0921:             *                            int superLevel,
0922:             *                            boolean isSecField) {
0923:             *      if (superLevel > 0) {
0924:             *          // if has superclass:
0925:             *          return super.bdbGetField
0926:             *              (o, field, superLevel - 1, isSecField);
0927:             *      } else if (isSecField) {
0928:             *          switch (field) {
0929:             *          case 0:
0930:             *              return Integer.valueOf(f2);
0931:             *          case 1:
0932:             *              return f3;
0933:             *          case 2:
0934:             *              return f4;
0935:             *          }
0936:             *      } else {
0937:             *          switch (field) {
0938:             *          case 0:
0939:             *              return Integer.valueOf(f5);
0940:             *          case 1:
0941:             *              return f6;
0942:             *          case 2:
0943:             *              return f7;
0944:             *          }
0945:             *      }
0946:             *      return null;
0947:             *  }
0948:             */
0949:            private void genBdbGetField() {
0950:                MethodVisitor mv = cv
0951:                        .visitMethod(ACC_PUBLIC, "bdbGetField",
0952:                                "(Ljava/lang/Object;IIZ)Ljava/lang/Object;",
0953:                                null, null);
0954:                mv.visitCode();
0955:                mv.visitVarInsn(ILOAD, 3);
0956:                Label l0 = new Label();
0957:                mv.visitJumpInsn(IFLE, l0);
0958:                Label l1 = new Label();
0959:                if (hasPersistentSuperclass) {
0960:                    mv.visitVarInsn(ALOAD, 0);
0961:                    mv.visitVarInsn(ALOAD, 1);
0962:                    mv.visitVarInsn(ILOAD, 2);
0963:                    mv.visitVarInsn(ILOAD, 3);
0964:                    mv.visitInsn(ICONST_1);
0965:                    mv.visitInsn(ISUB);
0966:                    mv.visitVarInsn(ILOAD, 4);
0967:                    mv.visitMethodInsn(INVOKESPECIAL, className, "bdbGetField",
0968:                            "(Ljava/lang/Object;IIZ)Ljava/lang/Object;");
0969:                    mv.visitInsn(ARETURN);
0970:                } else {
0971:                    mv.visitJumpInsn(GOTO, l1);
0972:                }
0973:                mv.visitLabel(l0);
0974:                mv.visitVarInsn(ILOAD, 4);
0975:                Label l2 = new Label();
0976:                mv.visitJumpInsn(IFEQ, l2);
0977:                genGetFieldSwitch(mv, secKeyFields, l1);
0978:                mv.visitLabel(l2);
0979:                genGetFieldSwitch(mv, nonKeyFields, l1);
0980:                mv.visitLabel(l1);
0981:                mv.visitInsn(ACONST_NULL);
0982:                mv.visitInsn(ARETURN);
0983:                mv.visitMaxs(1, 5);
0984:                mv.visitEnd();
0985:            }
0986:
0987:            /**
0988:             *  mv.visitVarInsn(ILOAD, 2);
0989:             *  Label l0 = new Label();
0990:             *  Label l1 = new Label();
0991:             *  Label l2 = new Label();
0992:             *  mv.visitTableSwitchInsn(0, 2, TheDefLabel, new Label[] { l0, l1, l2 });
0993:             *  mv.visitLabel(l0);
0994:             *  mv.visitVarInsn(ALOAD, 0);
0995:             *  mv.visitFieldInsn(GETFIELD, TheClassName, "f2", "I");
0996:             *  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf",
0997:             *                     "(I)Ljava/lang/Integer;");
0998:             *  mv.visitInsn(ARETURN);
0999:             *  mv.visitLabel(l1);
1000:             *  mv.visitVarInsn(ALOAD, 0);
1001:             *  mv.visitFieldInsn(GETFIELD, TheClassName, "f3", "Ljava/lang/String;");
1002:             *  mv.visitInsn(ARETURN);
1003:             *  mv.visitLabel(l2);
1004:             *  mv.visitVarInsn(ALOAD, 0);
1005:             *  mv.visitFieldInsn(GETFIELD, TheClassName, "f4", "Ljava/lang/String;");
1006:             *  mv.visitInsn(ARETURN);
1007:             */
1008:            private void genGetFieldSwitch(MethodVisitor mv,
1009:                    List<FieldInfo> fields, Label defaultLabel) {
1010:                int nFields = fields.size();
1011:                if (nFields == 0) {
1012:                    mv.visitJumpInsn(GOTO, defaultLabel);
1013:                    return;
1014:                }
1015:                Label[] labels = new Label[nFields];
1016:                for (int i = 0; i < nFields; i += 1) {
1017:                    labels[i] = new Label();
1018:                }
1019:                mv.visitVarInsn(ILOAD, 2);
1020:                mv.visitTableSwitchInsn(0, nFields - 1, defaultLabel, labels);
1021:                for (int i = 0; i < nFields; i += 1) {
1022:                    FieldInfo field = fields.get(i);
1023:                    mv.visitLabel(labels[i]);
1024:                    mv.visitVarInsn(ALOAD, 0);
1025:                    mv.visitFieldInsn(GETFIELD, className, field.name,
1026:                            field.type.getDescriptor());
1027:                    if (!isRefType(field.type)) {
1028:                        genWrapPrimitive(mv, field.type.getSort());
1029:                    }
1030:                    mv.visitInsn(ARETURN);
1031:                }
1032:            }
1033:
1034:            /**
1035:             *  public void bdbSetField(Object o,
1036:             *                          int field,
1037:             *                          int superLevel,
1038:             *                          boolean isSecField,
1039:             *                          Object value) {
1040:             *      if (superLevel > 0) {
1041:             *          // if has superclass:
1042:             *          super.bdbSetField
1043:             *              (o, field, superLevel - 1, isSecField, value);
1044:             *      } else if (isSecField) {
1045:             *          switch (field) {
1046:             *          case 0:
1047:             *              f2 = ((Integer) value).intValue();
1048:             *          case 1:
1049:             *              f3 = (String) value;
1050:             *          case 2:
1051:             *              f4 = (String) value;
1052:             *          }
1053:             *      } else {
1054:             *          switch (field) {
1055:             *          case 0:
1056:             *              f5 = ((Integer) value).intValue();
1057:             *          case 1:
1058:             *              f6 = (String) value;
1059:             *          case 2:
1060:             *              f7 = (String) value;
1061:             *          }
1062:             *      }
1063:             *  }
1064:             */
1065:            private void genBdbSetField() {
1066:                MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "bdbSetField",
1067:                        "(Ljava/lang/Object;IIZLjava/lang/Object;)V", null,
1068:                        null);
1069:                mv.visitCode();
1070:                mv.visitVarInsn(ILOAD, 3);
1071:                Label l0 = new Label();
1072:                mv.visitJumpInsn(IFLE, l0);
1073:                if (hasPersistentSuperclass) {
1074:                    mv.visitVarInsn(ALOAD, 0);
1075:                    mv.visitVarInsn(ALOAD, 1);
1076:                    mv.visitVarInsn(ILOAD, 2);
1077:                    mv.visitVarInsn(ILOAD, 3);
1078:                    mv.visitInsn(ICONST_1);
1079:                    mv.visitInsn(ISUB);
1080:                    mv.visitVarInsn(ILOAD, 4);
1081:                    mv.visitVarInsn(ALOAD, 5);
1082:                    mv.visitMethodInsn(INVOKESPECIAL, className, "bdbSetField",
1083:                            "(Ljava/lang/Object;IIZLjava/lang/Object;)V");
1084:                }
1085:                mv.visitInsn(RETURN);
1086:                mv.visitLabel(l0);
1087:                mv.visitVarInsn(ILOAD, 4);
1088:                Label l2 = new Label();
1089:                mv.visitJumpInsn(IFEQ, l2);
1090:                Label l1 = new Label();
1091:                genSetFieldSwitch(mv, secKeyFields, l1);
1092:                mv.visitLabel(l2);
1093:                genSetFieldSwitch(mv, nonKeyFields, l1);
1094:                mv.visitLabel(l1);
1095:                mv.visitInsn(RETURN);
1096:                mv.visitMaxs(2, 6);
1097:                mv.visitEnd();
1098:            }
1099:
1100:            /**
1101:             *  mv.visitVarInsn(ILOAD, 2);
1102:             *  Label l0 = new Label();
1103:             *  Label l1 = new Label();
1104:             *  Label l2 = new Label();
1105:             *  mv.visitTableSwitchInsn(0, 2, TheDefLabel, new Label[] { l0, l1, l2 });
1106:             *  mv.visitLabel(l0);
1107:             *  mv.visitVarInsn(ALOAD, 0);
1108:             *  mv.visitVarInsn(ALOAD, 5);
1109:             *  mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
1110:             *  mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue",
1111:             *                     "()I");
1112:             *  mv.visitFieldInsn(PUTFIELD, TheClassName, "f2", "I");
1113:             *  mv.visitLabel(l1);
1114:             *  mv.visitVarInsn(ALOAD, 0);
1115:             *  mv.visitVarInsn(ALOAD, 5);
1116:             *  mv.visitTypeInsn(CHECKCAST, "java/lang/String");
1117:             *  mv.visitFieldInsn(PUTFIELD, TheClassName, "f3", "Ljava/lang/String;");
1118:             *  mv.visitLabel(l2);
1119:             *  mv.visitVarInsn(ALOAD, 0);
1120:             *  mv.visitVarInsn(ALOAD, 5);
1121:             *  mv.visitTypeInsn(CHECKCAST, "java/lang/String");
1122:             *  mv.visitFieldInsn(PUTFIELD, TheClassName, "f4", "Ljava/lang/String;");
1123:             */
1124:            private void genSetFieldSwitch(MethodVisitor mv,
1125:                    List<FieldInfo> fields, Label defaultLabel) {
1126:                int nFields = fields.size();
1127:                if (nFields == 0) {
1128:                    mv.visitJumpInsn(GOTO, defaultLabel);
1129:                    return;
1130:                }
1131:                Label[] labels = new Label[nFields];
1132:                for (int i = 0; i < nFields; i += 1) {
1133:                    labels[i] = new Label();
1134:                }
1135:                mv.visitVarInsn(ILOAD, 2);
1136:                mv.visitTableSwitchInsn(0, nFields - 1, defaultLabel, labels);
1137:                for (int i = 0; i < nFields; i += 1) {
1138:                    FieldInfo field = fields.get(i);
1139:                    mv.visitLabel(labels[i]);
1140:                    mv.visitVarInsn(ALOAD, 0);
1141:                    mv.visitVarInsn(ALOAD, 5);
1142:                    if (isRefType(field.type)) {
1143:                        mv
1144:                                .visitTypeInsn(CHECKCAST,
1145:                                        getTypeInstName(field.type));
1146:                    } else {
1147:                        int sort = field.type.getSort();
1148:                        mv.visitTypeInsn(CHECKCAST, getPrimitiveWrapperClass(
1149:                                sort).replace('.', '/'));
1150:                        genUnwrapPrimitive(mv, sort);
1151:                    }
1152:                    mv.visitFieldInsn(PUTFIELD, className, field.name,
1153:                            field.type.getDescriptor());
1154:                    mv.visitInsn(RETURN);
1155:                }
1156:            }
1157:
1158:            private void genWritePrimitive(MethodVisitor mv, int sort) {
1159:                switch (sort) {
1160:                case Type.BOOLEAN:
1161:                    mv.visitMethodInsn(INVOKEINTERFACE,
1162:                            "com/sleepycat/persist/impl/EntityOutput",
1163:                            "writeBoolean",
1164:                            "(Z)Lcom/sleepycat/bind/tuple/TupleOutput;");
1165:                    break;
1166:                case Type.CHAR:
1167:                    mv.visitMethodInsn(INVOKEINTERFACE,
1168:                            "com/sleepycat/persist/impl/EntityOutput",
1169:                            "writeChar",
1170:                            "(I)Lcom/sleepycat/bind/tuple/TupleOutput;");
1171:                    break;
1172:                case Type.BYTE:
1173:                    mv.visitMethodInsn(INVOKEINTERFACE,
1174:                            "com/sleepycat/persist/impl/EntityOutput",
1175:                            "writeByte",
1176:                            "(I)Lcom/sleepycat/bind/tuple/TupleOutput;");
1177:                    break;
1178:                case Type.SHORT:
1179:                    mv.visitMethodInsn(INVOKEINTERFACE,
1180:                            "com/sleepycat/persist/impl/EntityOutput",
1181:                            "writeShort",
1182:                            "(I)Lcom/sleepycat/bind/tuple/TupleOutput;");
1183:                    break;
1184:                case Type.INT:
1185:                    mv.visitMethodInsn(INVOKEINTERFACE,
1186:                            "com/sleepycat/persist/impl/EntityOutput",
1187:                            "writeInt",
1188:                            "(I)Lcom/sleepycat/bind/tuple/TupleOutput;");
1189:                    break;
1190:                case Type.LONG:
1191:                    mv.visitMethodInsn(INVOKEINTERFACE,
1192:                            "com/sleepycat/persist/impl/EntityOutput",
1193:                            "writeLong",
1194:                            "(J)Lcom/sleepycat/bind/tuple/TupleOutput;");
1195:                    break;
1196:                case Type.FLOAT:
1197:                    mv.visitMethodInsn(INVOKEINTERFACE,
1198:                            "com/sleepycat/persist/impl/EntityOutput",
1199:                            "writeSortedFloat",
1200:                            "(F)Lcom/sleepycat/bind/tuple/TupleOutput;");
1201:                    break;
1202:                case Type.DOUBLE:
1203:                    mv.visitMethodInsn(INVOKEINTERFACE,
1204:                            "com/sleepycat/persist/impl/EntityOutput",
1205:                            "writeSortedDouble",
1206:                            "(D)Lcom/sleepycat/bind/tuple/TupleOutput;");
1207:                    break;
1208:                default:
1209:                    throw new IllegalStateException(String.valueOf(sort));
1210:                }
1211:                /* The write methods always return 'this' and we always discard it. */
1212:                mv.visitInsn(POP);
1213:            }
1214:
1215:            private void genReadPrimitive(MethodVisitor mv, int sort) {
1216:                switch (sort) {
1217:                case Type.BOOLEAN:
1218:                    mv.visitMethodInsn(INVOKEINTERFACE,
1219:                            "com/sleepycat/persist/impl/EntityInput",
1220:                            "readBoolean", "()Z");
1221:                    break;
1222:                case Type.CHAR:
1223:                    mv.visitMethodInsn(INVOKEINTERFACE,
1224:                            "com/sleepycat/persist/impl/EntityInput",
1225:                            "readChar", "()C");
1226:                    break;
1227:                case Type.BYTE:
1228:                    mv.visitMethodInsn(INVOKEINTERFACE,
1229:                            "com/sleepycat/persist/impl/EntityInput",
1230:                            "readByte", "()B");
1231:                    break;
1232:                case Type.SHORT:
1233:                    mv.visitMethodInsn(INVOKEINTERFACE,
1234:                            "com/sleepycat/persist/impl/EntityInput",
1235:                            "readShort", "()S");
1236:                    break;
1237:                case Type.INT:
1238:                    mv.visitMethodInsn(INVOKEINTERFACE,
1239:                            "com/sleepycat/persist/impl/EntityInput",
1240:                            "readInt", "()I");
1241:                    break;
1242:                case Type.LONG:
1243:                    mv.visitMethodInsn(INVOKEINTERFACE,
1244:                            "com/sleepycat/persist/impl/EntityInput",
1245:                            "readLong", "()J");
1246:                    break;
1247:                case Type.FLOAT:
1248:                    mv.visitMethodInsn(INVOKEINTERFACE,
1249:                            "com/sleepycat/persist/impl/EntityInput",
1250:                            "readSortedFloat", "()F");
1251:                    break;
1252:                case Type.DOUBLE:
1253:                    mv.visitMethodInsn(INVOKEINTERFACE,
1254:                            "com/sleepycat/persist/impl/EntityInput",
1255:                            "readSortedDouble", "()D");
1256:                    break;
1257:                default:
1258:                    throw new IllegalStateException(String.valueOf(sort));
1259:                }
1260:            }
1261:
1262:            private void genWrapPrimitive(MethodVisitor mv, int sort) {
1263:                switch (sort) {
1264:                case Type.BOOLEAN:
1265:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean",
1266:                            "valueOf", "(Z)Ljava/lang/Boolean;");
1267:                    break;
1268:                case Type.CHAR:
1269:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character",
1270:                            "valueOf", "(C)Ljava/lang/Character;");
1271:                    break;
1272:                case Type.BYTE:
1273:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte",
1274:                            "valueOf", "(B)Ljava/lang/Byte;");
1275:                    break;
1276:                case Type.SHORT:
1277:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short",
1278:                            "valueOf", "(S)Ljava/lang/Short;");
1279:                    break;
1280:                case Type.INT:
1281:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer",
1282:                            "valueOf", "(I)Ljava/lang/Integer;");
1283:                    break;
1284:                case Type.LONG:
1285:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long",
1286:                            "valueOf", "(J)Ljava/lang/Long;");
1287:                    break;
1288:                case Type.FLOAT:
1289:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float",
1290:                            "valueOf", "(F)Ljava/lang/Float;");
1291:                    break;
1292:                case Type.DOUBLE:
1293:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double",
1294:                            "valueOf", "(D)Ljava/lang/Double;");
1295:                    break;
1296:                default:
1297:                    throw new IllegalStateException(String.valueOf(sort));
1298:                }
1299:            }
1300:
1301:            private void genUnwrapPrimitive(MethodVisitor mv, int sort) {
1302:                switch (sort) {
1303:                case Type.BOOLEAN:
1304:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean",
1305:                            "booleanValue", "()Z");
1306:                    break;
1307:                case Type.CHAR:
1308:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character",
1309:                            "charValue", "()C");
1310:                    break;
1311:                case Type.BYTE:
1312:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte",
1313:                            "byteValue", "()B");
1314:                    break;
1315:                case Type.SHORT:
1316:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short",
1317:                            "shortValue", "()S");
1318:                    break;
1319:                case Type.INT:
1320:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer",
1321:                            "intValue", "()I");
1322:                    break;
1323:                case Type.LONG:
1324:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long",
1325:                            "longValue", "()J");
1326:                    break;
1327:                case Type.FLOAT:
1328:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float",
1329:                            "floatValue", "()F");
1330:                    break;
1331:                case Type.DOUBLE:
1332:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double",
1333:                            "doubleValue", "()D");
1334:                    break;
1335:                default:
1336:                    throw new IllegalStateException(String.valueOf(sort));
1337:                }
1338:            }
1339:
1340:            /**
1341:             * Returns the type name for a visitTypeInsn operand, which is the internal
1342:             * name for an object type and the descriptor for an array type.  Must not
1343:             * be called for a non-reference type.
1344:             */
1345:            private static String getTypeInstName(Type type) {
1346:                if (type.getSort() == Type.OBJECT) {
1347:                    return type.getInternalName();
1348:                } else if (type.getSort() == Type.ARRAY) {
1349:                    return type.getDescriptor();
1350:                } else {
1351:                    throw new IllegalStateException();
1352:                }
1353:            }
1354:
1355:            /**
1356:             * Call this method before comparing a non-reference operand to zero as an
1357:             * int, for example, with IFNE, IFEQ, IFLT, etc.  If the operand is a long,
1358:             * float or double, this method will compare it to zero and leave the
1359:             * result as an int operand.
1360:             */
1361:            private static void genBeforeCompareToZero(MethodVisitor mv,
1362:                    Type type) {
1363:                switch (type.getSort()) {
1364:                case Type.LONG:
1365:                    mv.visitInsn(LCONST_0);
1366:                    mv.visitInsn(LCMP);
1367:                    break;
1368:                case Type.FLOAT:
1369:                    mv.visitInsn(FCONST_0);
1370:                    mv.visitInsn(FCMPL);
1371:                    break;
1372:                case Type.DOUBLE:
1373:                    mv.visitInsn(DCONST_0);
1374:                    mv.visitInsn(DCMPL);
1375:                    break;
1376:                }
1377:            }
1378:
1379:            /**
1380:             * Returns true if the given class is a primitive wrapper, Date or String.
1381:             */
1382:            static boolean isSimpleRefType(String className) {
1383:                return (PRIMITIVE_WRAPPERS.containsKey(className)
1384:                        || className.equals(BigInteger.class.getName())
1385:                        || className.equals(Date.class.getName()) || className
1386:                        .equals(String.class.getName()));
1387:            }
1388:
1389:            /**
1390:             * Returns the wrapper class for a primitive.
1391:             */
1392:            static String getPrimitiveWrapperClass(int primitiveSort) {
1393:                for (Map.Entry<String, Integer> entry : PRIMITIVE_WRAPPERS
1394:                        .entrySet()) {
1395:                    if (entry.getValue() == primitiveSort) {
1396:                        return entry.getKey();
1397:                    }
1398:                }
1399:                throw new IllegalStateException(String.valueOf(primitiveSort));
1400:            }
1401:
1402:            /**
1403:             * Returns true if the given type is an object or array.
1404:             */
1405:            private static boolean isRefType(Type type) {
1406:                int sort = type.getSort();
1407:                return (sort == Type.OBJECT || sort == Type.ARRAY);
1408:            }
1409:
1410:            /**
1411:             * Returns whether a string array contains a given string.
1412:             */
1413:            private static boolean containsString(String[] a, String s) {
1414:                if (a != null) {
1415:                    for (String t : a) {
1416:                        if (s.equals(t)) {
1417:                            return true;
1418:                        }
1419:                    }
1420:                }
1421:                return false;
1422:            }
1423:
1424:            /**
1425:             * Appends a string to a string array.
1426:             */
1427:            private static String[] appendString(String[] a, String s) {
1428:                if (a != null) {
1429:                    int len = a.length;
1430:                    String[] a2 = new String[len + 1];
1431:                    System.arraycopy(a, 0, a2, 0, len);
1432:                    a2[len] = s;
1433:                    return a2;
1434:                } else {
1435:                    return new String[] { s };
1436:                }
1437:            }
1438:
1439:            /**
1440:             * Aborts the enhancement process when we determine that enhancement is
1441:             * unnecessary or not possible.
1442:             */
1443:            private NotPersistentException abort() {
1444:                return NOT_PERSISTENT;
1445:            }
1446:
1447:            private static class FieldInfo implements  FieldVisitor {
1448:
1449:                FieldVisitor parent;
1450:                String name;
1451:                Type type;
1452:                OrderInfo order;
1453:                boolean isPriKey;
1454:                boolean isSecKey;
1455:
1456:                FieldInfo(FieldVisitor parent, String name, String desc) {
1457:                    this .parent = parent;
1458:                    this .name = name;
1459:                    type = Type.getType(desc);
1460:                }
1461:
1462:                public AnnotationVisitor visitAnnotation(String desc,
1463:                        boolean visible) {
1464:                    AnnotationVisitor ret = parent.visitAnnotation(desc,
1465:                            visible);
1466:                    if (desc.equals("Lcom/sleepycat/persist/model/KeyField;")) {
1467:                        order = new OrderInfo(ret);
1468:                        ret = order;
1469:                    } else if (desc
1470:                            .equals("Lcom/sleepycat/persist/model/PrimaryKey;")) {
1471:                        isPriKey = true;
1472:                    } else if (desc
1473:                            .equals("Lcom/sleepycat/persist/model/SecondaryKey;")) {
1474:                        isSecKey = true;
1475:                    }
1476:                    return ret;
1477:                }
1478:
1479:                public void visitAttribute(Attribute attr) {
1480:                    parent.visitAttribute(attr);
1481:                }
1482:
1483:                public void visitEnd() {
1484:                    parent.visitEnd();
1485:                }
1486:
1487:                @Override
1488:                public String toString() {
1489:                    String label;
1490:                    if (isPriKey) {
1491:                        label = "PrimaryKey";
1492:                    } else if (isSecKey) {
1493:                        label = "SecondaryKey";
1494:                    } else if (order != null) {
1495:                        label = "CompositeKeyField " + order.value;
1496:                    } else {
1497:                        label = "NonKeyField";
1498:                    }
1499:                    return "[" + label + ' ' + name + ' ' + type + ']';
1500:                }
1501:            }
1502:
1503:            private static class OrderInfo extends AnnotationInfo {
1504:
1505:                int value;
1506:
1507:                OrderInfo(AnnotationVisitor parent) {
1508:                    super (parent);
1509:                }
1510:
1511:                @Override
1512:                public void visit(String name, Object value) {
1513:                    if (name.equals("value")) {
1514:                        this .value = (Integer) value;
1515:                    }
1516:                    parent.visit(name, value);
1517:                }
1518:            }
1519:
1520:            private static abstract class AnnotationInfo implements 
1521:                    AnnotationVisitor {
1522:
1523:                AnnotationVisitor parent;
1524:
1525:                AnnotationInfo(AnnotationVisitor parent) {
1526:                    this .parent = parent;
1527:                }
1528:
1529:                public void visit(String name, Object value) {
1530:                    parent.visit(name, value);
1531:                }
1532:
1533:                public AnnotationVisitor visitAnnotation(String name,
1534:                        String desc) {
1535:                    return parent.visitAnnotation(name, desc);
1536:                }
1537:
1538:                public AnnotationVisitor visitArray(String name) {
1539:                    return parent.visitArray(name);
1540:                }
1541:
1542:                public void visitEnum(String name, String desc, String value) {
1543:                    parent.visitEnum(name, desc, value);
1544:                }
1545:
1546:                public void visitEnd() {
1547:                    parent.visitEnd();
1548:                }
1549:            }
1550:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.