All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.persist.model.BytecodeEnhancer Maven / Gradle / Ivy

Go to download

Berkeley DB Java Edition is a open source, transactional storage solution for Java applications. The Direct Persistence Layer (DPL) API is faster and easier to develop, deploy, and manage than serialized object files or ORM-based Java persistence solutions. The Collections API enhances the standard java.util.collections classes allowing them to be persisted to a local file system and accessed concurrently while protected by ACID transactions. Data is stored by serializing objects and managing class and instance data separately so as not to waste space. Berkeley DB Java Edition is the reliable drop-in solution for complex, fast, and scalable storage. Source for this release is in 'je-4.0.92-sources.jar', the Javadoc is located at 'http://download.oracle.com/berkeley-db/docs/je/4.0.92/'.

There is a newer version: 5.0.73
Show newest version
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.persist.model;

import static com.sleepycat.asm.Opcodes.AALOAD;
import static com.sleepycat.asm.Opcodes.ACC_ABSTRACT;
import static com.sleepycat.asm.Opcodes.ACC_PRIVATE;
import static com.sleepycat.asm.Opcodes.ACC_PUBLIC;
import static com.sleepycat.asm.Opcodes.ACC_STATIC;
import static com.sleepycat.asm.Opcodes.ACC_TRANSIENT;
import static com.sleepycat.asm.Opcodes.ACONST_NULL;
import static com.sleepycat.asm.Opcodes.ALOAD;
import static com.sleepycat.asm.Opcodes.ANEWARRAY;
import static com.sleepycat.asm.Opcodes.ARETURN;
import static com.sleepycat.asm.Opcodes.ASM4;
import static com.sleepycat.asm.Opcodes.BIPUSH;
import static com.sleepycat.asm.Opcodes.CHECKCAST;
import static com.sleepycat.asm.Opcodes.DCMPL;
import static com.sleepycat.asm.Opcodes.DCONST_0;
import static com.sleepycat.asm.Opcodes.DUP;
import static com.sleepycat.asm.Opcodes.FCMPL;
import static com.sleepycat.asm.Opcodes.FCONST_0;
import static com.sleepycat.asm.Opcodes.GETFIELD;
import static com.sleepycat.asm.Opcodes.GOTO;
import static com.sleepycat.asm.Opcodes.ICONST_0;
import static com.sleepycat.asm.Opcodes.ICONST_1;
import static com.sleepycat.asm.Opcodes.ICONST_2;
import static com.sleepycat.asm.Opcodes.ICONST_3;
import static com.sleepycat.asm.Opcodes.ICONST_4;
import static com.sleepycat.asm.Opcodes.ICONST_5;
import static com.sleepycat.asm.Opcodes.IFEQ;
import static com.sleepycat.asm.Opcodes.IFGT;
import static com.sleepycat.asm.Opcodes.IFLE;
import static com.sleepycat.asm.Opcodes.IFNE;
import static com.sleepycat.asm.Opcodes.IFNONNULL;
import static com.sleepycat.asm.Opcodes.IF_ICMPNE;
import static com.sleepycat.asm.Opcodes.ILOAD;
import static com.sleepycat.asm.Opcodes.INVOKEINTERFACE;
import static com.sleepycat.asm.Opcodes.INVOKESPECIAL;
import static com.sleepycat.asm.Opcodes.INVOKESTATIC;
import static com.sleepycat.asm.Opcodes.INVOKEVIRTUAL;
import static com.sleepycat.asm.Opcodes.IRETURN;
import static com.sleepycat.asm.Opcodes.ISUB;
import static com.sleepycat.asm.Opcodes.LCMP;
import static com.sleepycat.asm.Opcodes.LCONST_0;
import static com.sleepycat.asm.Opcodes.NEW;
import static com.sleepycat.asm.Opcodes.POP;
import static com.sleepycat.asm.Opcodes.PUTFIELD;
import static com.sleepycat.asm.Opcodes.RETURN;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sleepycat.asm.AnnotationVisitor;
import com.sleepycat.asm.Attribute;
import com.sleepycat.asm.ClassVisitor;
import com.sleepycat.asm.FieldVisitor;
import com.sleepycat.asm.Label;
import com.sleepycat.asm.MethodVisitor;
import com.sleepycat.asm.Type;
import com.sleepycat.compat.DbCompat;

/**
 * An ASM ClassVisitor that examines a class, throws NotPersistentException if
 * it is not persistent, or enhances it if it is persistent.  A class is
 * persistent if it contains the @Entity or @Persistent annotations.  A
 * resulting enhanced class implements the com.sleepycat.persist.impl.Enhanced
 * interface.
 *
 * 

NotPersistentException is thrown to abort the transformation in order to * avoid making two passes over the class file (one to look for the annotations * and another to enhance the bytecode) or outputing a class that isn't * enhanced. By aborting the transformation as soon as we detect that the * annotations are missing, we make only one partial pass for a non-persistent * class.

* * @author Mark Hayes */ class BytecodeEnhancer extends ClassVisitor { /** Thrown when we determine that a class is not persistent. */ @SuppressWarnings("serial") static class NotPersistentException extends RuntimeException {} /** A static instance is used to avoid fillInStaceTrace overhead. */ private static final NotPersistentException NOT_PERSISTENT = new NotPersistentException(); private static final Map PRIMITIVE_WRAPPERS = new HashMap(); static { PRIMITIVE_WRAPPERS.put(Boolean.class.getName(), Type.BOOLEAN); PRIMITIVE_WRAPPERS.put(Character.class.getName(), Type.CHAR); PRIMITIVE_WRAPPERS.put(Byte.class.getName(), Type.BYTE); PRIMITIVE_WRAPPERS.put(Short.class.getName(), Type.SHORT); PRIMITIVE_WRAPPERS.put(Integer.class.getName(), Type.INT); PRIMITIVE_WRAPPERS.put(Long.class.getName(), Type.LONG); PRIMITIVE_WRAPPERS.put(Float.class.getName(), Type.FLOAT); PRIMITIVE_WRAPPERS.put(Double.class.getName(), Type.DOUBLE); } private String className; private String superclassName; private boolean isPersistent; private boolean isAbstract; private boolean hasDefaultConstructor; private boolean hasPersistentSuperclass; private boolean isCompositeKey; private FieldInfo priKeyField; private List secKeyFields; private List nonKeyFields; private String staticBlockMethod; BytecodeEnhancer(ClassVisitor parentVisitor) { super(ASM4, parentVisitor); secKeyFields = new ArrayList(); nonKeyFields = new ArrayList(); } @Override public void visit(int version, int access, String name, String sig, String superName, String[] interfaces) { className = name; superclassName = superName; final String ENHANCED = "com/sleepycat/persist/impl/Enhanced"; if (containsString(interfaces, ENHANCED)) { throw abort(); } interfaces = appendString(interfaces, ENHANCED); isAbstract = ((access & ACC_ABSTRACT) != 0); hasPersistentSuperclass = (superName != null && !superName.equals("java/lang/Object")); super.visit(version, access, name, sig, superName, interfaces); } @Override public void visitSource(String source, String debug) { super.visitSource(source, debug); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if (desc.equals("Lcom/sleepycat/persist/model/Entity;") || desc.equals("Lcom/sleepycat/persist/model/Persistent;")) { isPersistent = true; } return super.visitAnnotation(desc, visible); } @Override public FieldVisitor visitField(int access, String name, String desc, String sig, Object value) { if (!isPersistent) { throw abort(); } FieldVisitor ret = super.visitField(access, name, desc, sig, value); if ((access & ACC_STATIC) == 0) { FieldInfo info = new FieldInfo(ret, name, desc, (access & ACC_TRANSIENT) != 0); nonKeyFields.add(info); ret = info; } return ret; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] exceptions) { if (!isPersistent) { throw abort(); } if ("".equals(name) && "()V".equals(desc)) { hasDefaultConstructor = true; } if ("".equals(name)) { if (staticBlockMethod != null) { throw DbCompat.unexpectedState(); } staticBlockMethod = "bdbExistingStaticBlock"; return cv.visitMethod (ACC_PRIVATE + ACC_STATIC, staticBlockMethod, "()V", null, null); } return super.visitMethod(access, name, desc, sig, exceptions); } @Override public void visitEnd() { if (!isPersistent || !hasDefaultConstructor) { throw abort(); } /* Generate new code at the end of the class. */ sortFields(); genBdbNewInstance(); genBdbNewArray(); genBdbIsPriKeyFieldNullOrZero(); genBdbWritePriKeyField(); genBdbReadPriKeyField(); genBdbWriteSecKeyFields(); genBdbReadSecKeyFields(); genBdbWriteNonKeyFields(); genBdbReadNonKeyFields(); genBdbWriteCompositeKeyFields(); genBdbReadCompositeKeyFields(); genBdbGetField(); genBdbSetField(); genBdbSetPriField(); genStaticBlock(); super.visitEnd(); } private void sortFields() { /* System.out.println("AllFields: " + nonKeyFields); //*/ if (nonKeyFields.size() == 0) { return; } isCompositeKey = true; for (FieldInfo field : nonKeyFields) { if (field.order == null) { isCompositeKey = false; } } if (isCompositeKey) { Collections.sort(nonKeyFields, new Comparator() { public int compare(FieldInfo f1, FieldInfo f2) { return f1.order.value - f2.order.value; } }); } else { for (int i = 0; i < nonKeyFields.size();) { FieldInfo field = nonKeyFields.get(i); if (field.isTransient) { nonKeyFields.remove(i); } else if (field.isPriKey) { if (priKeyField == null) { priKeyField = field; nonKeyFields.remove(i); } } else if (field.isSecKey) { secKeyFields.add(field); nonKeyFields.remove(i); } else { i += 1; } } Comparator cmp = new Comparator() { public int compare(FieldInfo f1, FieldInfo f2) { return f1.name.compareTo(f2.name); } }; Collections.sort(secKeyFields, cmp); Collections.sort(nonKeyFields, cmp); } /* System.out.println("PriKey: " + priKeyField); System.out.println("SecKeys: " + secKeyFields); System.out.println("NonKeys: " + nonKeyFields); //*/ } /** * Outputs code in a static block to register the prototype instance: * * static { * EnhancedAccessor.registerClass(TheClassName, new TheClass()); * // or for an abstract class: * EnhancedAccessor.registerClass(TheClassName, null); * } */ private void genStaticBlock() { MethodVisitor mv = cv.visitMethod(ACC_STATIC, "", "()V", null, null); mv.visitCode(); if (staticBlockMethod != null) { mv.visitMethodInsn (INVOKESTATIC, className, staticBlockMethod, "()V"); } mv.visitLdcInsn(className.replace('/', '.')); if (isAbstract) { mv.visitInsn(ACONST_NULL); } else { mv.visitTypeInsn(NEW, className); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, className, "", "()V"); } mv.visitMethodInsn (INVOKESTATIC, "com/sleepycat/persist/impl/EnhancedAccessor", "registerClass", "(Ljava/lang/String;Lcom/sleepycat/persist/impl/Enhanced;)V"); mv.visitInsn(RETURN); mv.visitMaxs(3, 0); mv.visitEnd(); } /** * public Object bdbNewInstance() { * return new TheClass(); * // or if abstract: * return null; * } */ private void genBdbNewInstance() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbNewInstance", "()Ljava/lang/Object;", null, null); mv.visitCode(); if (isAbstract) { mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); } else { mv.visitTypeInsn(NEW, className); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, className, "", "()V"); mv.visitInsn(ARETURN); mv.visitMaxs(2, 1); } mv.visitEnd(); } /** * public Object bdbNewArray(int len) { * return new TheClass[len]; * // or if abstract: * return null; * } */ private void genBdbNewArray() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbNewArray", "(I)Ljava/lang/Object;", null, null); mv.visitCode(); if (isAbstract) { mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); mv.visitMaxs(1, 2); } else { mv.visitVarInsn(ILOAD, 1); mv.visitTypeInsn(ANEWARRAY, className); mv.visitInsn(ARETURN); mv.visitMaxs(1, 2); mv.visitEnd(); } } /** * public boolean bdbIsPriKeyFieldNullOrZero() { * return theField == null; // or zero or false, as appropriate * // or if no primary key but has superclass: * return super.bdbIsPriKeyFieldNullOrZero(); * } */ private void genBdbIsPriKeyFieldNullOrZero() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbIsPriKeyFieldNullOrZero", "()Z", null, null); mv.visitCode(); if (priKeyField != null) { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, priKeyField.name, priKeyField.type.getDescriptor()); Label l0 = new Label(); if (isRefType(priKeyField.type)) { mv.visitJumpInsn(IFNONNULL, l0); } else { genBeforeCompareToZero(mv, priKeyField.type); mv.visitJumpInsn(IFNE, l0); } mv.visitInsn(ICONST_1); Label l1 = new Label(); mv.visitJumpInsn(GOTO, l1); mv.visitLabel(l0); mv.visitInsn(ICONST_0); mv.visitLabel(l1); } else if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn (INVOKESPECIAL, superclassName, "bdbIsPriKeyFieldNullOrZero", "()Z"); } else { mv.visitInsn(ICONST_0); } mv.visitInsn(IRETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } /** * public void bdbWritePriKeyField(EntityOutput output, Format format) { * output.writeKeyObject(theField, format); * // or * output.writeInt(theField); // and other simple types * // or if no primary key but has superclass: * return super.bdbWritePriKeyField(output, format); * } */ private void genBdbWritePriKeyField() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbWritePriKeyField", "(Lcom/sleepycat/persist/impl/EntityOutput;" + "Lcom/sleepycat/persist/impl/Format;)V", null, null); mv.visitCode(); if (priKeyField != null) { if (!genWriteSimpleKeyField(mv, priKeyField)) { /* For a non-simple type, call EntityOutput.writeKeyObject. */ mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, priKeyField.name, priKeyField.type.getDescriptor()); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeKeyObject", "(Ljava/lang/Object;" + "Lcom/sleepycat/persist/impl/Format;)V"); } } else if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn (INVOKESPECIAL, superclassName, "bdbWritePriKeyField", "(Lcom/sleepycat/persist/impl/EntityOutput;" + "Lcom/sleepycat/persist/impl/Format;)V"); } mv.visitInsn(RETURN); mv.visitMaxs(3, 3); mv.visitEnd(); } /** * public void bdbReadPriKeyField(EntityInput input, Format format) { * theField = (TheFieldClass) input.readKeyObject(format); * // or * theField = input.readInt(); // and other simple types * // or if no primary key but has superclass: * super.bdbReadPriKeyField(input, format); * } */ private void genBdbReadPriKeyField() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbReadPriKeyField", "(Lcom/sleepycat/persist/impl/EntityInput;" + "Lcom/sleepycat/persist/impl/Format;)V", null, null); mv.visitCode(); if (priKeyField != null) { if (!genReadSimpleKeyField(mv, priKeyField)) { /* For a non-simple type, call EntityInput.readKeyObject. */ mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readKeyObject", "(Lcom/sleepycat/persist/impl/Format;)" + "Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, getTypeInstName(priKeyField.type)); mv.visitFieldInsn (PUTFIELD, className, priKeyField.name, priKeyField.type.getDescriptor()); } } else if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn (INVOKESPECIAL, superclassName, "bdbReadPriKeyField", "(Lcom/sleepycat/persist/impl/EntityInput;" + "Lcom/sleepycat/persist/impl/Format;)V"); } mv.visitInsn(RETURN); mv.visitMaxs(3, 3); mv.visitEnd(); } /** * public void bdbWriteSecKeyFields(EntityOutput output) { * output.registerPriKeyObject(priKeyField); // if an object * super.bdbWriteSecKeyFields(EntityOutput output); // if has super * output.writeInt(secKeyField1); * output.writeObject(secKeyField2, null); * // etc * } */ private void genBdbWriteSecKeyFields() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbWriteSecKeyFields", "(Lcom/sleepycat/persist/impl/EntityOutput;)V", null, null); mv.visitCode(); /* * In JE 5.0, String is treated as primitive type, so String does * not need to be registered. [#19247] */ if (priKeyField != null && isRefType(priKeyField.type) && !priKeyField.isString) { genRegisterPrimaryKey(mv, false); } if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn (INVOKESPECIAL, superclassName, "bdbWriteSecKeyFields", "(Lcom/sleepycat/persist/impl/EntityOutput;)V"); } for (FieldInfo field : secKeyFields) { genWriteField(mv, field); } mv.visitInsn(RETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } /** * public void bdbReadSecKeyFields(EntityInput input, * int startField, * int endField, * int superLevel) { * input.registerPriKeyObject(priKeyField); // if an object * // if has super: * if (superLevel != 0) { * super.bdbReadSecKeyFields(..., superLevel - 1); * } * if (superLevel <= 0) { * switch (startField) { * case 0: * secKeyField1 = input.readInt(); * if (endField == 0) break; * case 1: * secKeyField2 = (String) input.readObject(); * if (endField == 1) break; * case 2: * secKeyField3 = input.readInt(); * } * } * } */ private void genBdbReadSecKeyFields() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbReadSecKeyFields", "(Lcom/sleepycat/persist/impl/EntityInput;III)V", null, null); mv.visitCode(); if (priKeyField != null && isRefType(priKeyField.type) && !priKeyField.isString) { genRegisterPrimaryKey(mv, true); } else if (priKeyField != null && priKeyField.isString) { genRegisterPrimaryStringKey(mv); } genReadSuperKeyFields(mv, true); genReadFieldSwitch(mv, secKeyFields); mv.visitInsn(RETURN); mv.visitMaxs(5, 5); mv.visitEnd(); } /** * output.registerPriKeyObject(priKeyField); * // or * input.registerPriKeyObject(priKeyField); */ private void genRegisterPrimaryKey(MethodVisitor mv, boolean input) { String entityInputOrOutputClass = input ? "com/sleepycat/persist/impl/EntityInput" : "com/sleepycat/persist/impl/EntityOutput"; mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, priKeyField.name, priKeyField.type.getDescriptor()); mv.visitMethodInsn (INVOKEINTERFACE, entityInputOrOutputClass, "registerPriKeyObject", "(Ljava/lang/Object;)V"); } /** * input.registerPriStringKeyObject(priKeyField); */ private void genRegisterPrimaryStringKey(MethodVisitor mv) { String entityInputOrOutputClass = "com/sleepycat/persist/impl/EntityInput"; mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, priKeyField.name, priKeyField.type.getDescriptor()); mv.visitMethodInsn (INVOKEINTERFACE, entityInputOrOutputClass, "registerPriStringKeyObject", "(Ljava/lang/Object;)V"); } /** * public void bdbWriteNonKeyFields(EntityOutput output) { * // like bdbWriteSecKeyFields but does not call registerPriKeyObject * } */ private void genBdbWriteNonKeyFields() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbWriteNonKeyFields", "(Lcom/sleepycat/persist/impl/EntityOutput;)V", null, null); mv.visitCode(); if (!isCompositeKey) { if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn (INVOKESPECIAL, superclassName, "bdbWriteNonKeyFields", "(Lcom/sleepycat/persist/impl/EntityOutput;)V"); } for (FieldInfo field : nonKeyFields) { genWriteField(mv, field); } } mv.visitInsn(RETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } /** * public void bdbReadNonKeyFields(EntityInput input, * int startField, * int endField, * int superLevel) { * // like bdbReadSecKeyFields but does not call registerPriKeyObject * } */ private void genBdbReadNonKeyFields() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbReadNonKeyFields", "(Lcom/sleepycat/persist/impl/EntityInput;III)V", null, null); mv.visitCode(); if (!isCompositeKey) { genReadSuperKeyFields(mv, false); genReadFieldSwitch(mv, nonKeyFields); } mv.visitInsn(RETURN); mv.visitMaxs(5, 5); mv.visitEnd(); } /** * public void bdbWriteCompositeKeyFields(EntityOutput output, * Format[] formats) { * output.writeInt(compositeKeyField1); * output.writeKeyObject(compositeKeyField2, formats[1]); * // etc * } */ private void genBdbWriteCompositeKeyFields() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbWriteCompositeKeyFields", "(Lcom/sleepycat/persist/impl/EntityOutput;" + "[Lcom/sleepycat/persist/impl/Format;)V", null, null); mv.visitCode(); if (isCompositeKey) { for (int i = 0; i < nonKeyFields.size(); i += 1) { FieldInfo field = nonKeyFields.get(i); if (!genWriteSimpleKeyField(mv, field)) { /* For a non-simple type, call writeKeyObject. */ mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, field.name, field.type.getDescriptor()); mv.visitVarInsn(ALOAD, 2); if (i <= Byte.MAX_VALUE) { mv.visitIntInsn(BIPUSH, i); } else { mv.visitLdcInsn(new Integer(i)); } mv.visitInsn(AALOAD); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeKeyObject", "(Ljava/lang/Object;" + "Lcom/sleepycat/persist/impl/Format;)V"); } } } mv.visitInsn(RETURN); mv.visitMaxs(3, 3); mv.visitEnd(); } /** * public void bdbReadCompositeKeyFields(EntityInput input, * Format[] formats) { * compositeKeyField1 = input.readInt(); * compositeKeyField2 = input.readKeyObject(formats[1]); * } */ private void genBdbReadCompositeKeyFields() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbReadCompositeKeyFields", "(Lcom/sleepycat/persist/impl/EntityInput;" + "[Lcom/sleepycat/persist/impl/Format;)V", null, null); mv.visitCode(); if (isCompositeKey) { for (int i = 0; i < nonKeyFields.size(); i += 1) { FieldInfo field = nonKeyFields.get(i); /* Ignore non-simple (illegal) types for composite key. */ if (!genReadSimpleKeyField(mv, field)) { /* For a non-simple type, call readKeyObject. */ mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); if (i <= Byte.MAX_VALUE) { mv.visitIntInsn(BIPUSH, i); } else { mv.visitLdcInsn(new Integer(i)); } mv.visitInsn(AALOAD); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readKeyObject", "(Lcom/sleepycat/persist/impl/Format;)" + "Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, getTypeInstName(field.type)); mv.visitFieldInsn (PUTFIELD, className, field.name, field.type.getDescriptor()); } } } mv.visitInsn(RETURN); mv.visitMaxs(5, 5); mv.visitEnd(); } /** * output.writeInt(field); // and other primitives * // or * output.writeObject(field, null); */ private void genWriteField(MethodVisitor mv, FieldInfo field) { mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, field.name, field.type.getDescriptor()); int sort = field.type.getSort(); if (field.isString) { /* * In JE 5.0, we treat String as primitive, and will not store * format ID for String data. [#19247] */ mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeString", "(Ljava/lang/String;)Lcom/sleepycat/bind/tuple/TupleOutput;"); mv.visitInsn(POP); } else if (sort == Type.OBJECT || sort == Type.ARRAY) { mv.visitInsn(ACONST_NULL); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeObject", "(Ljava/lang/Object;Lcom/sleepycat/persist/impl/Format;)V"); } else { genWritePrimitive(mv, sort); } } /** * Generates writing of a simple type key field, or returns false if the * key field is not a simple type (i.e., it is a composite key type). * * output.writeInt(theField); // and other primitives * // or * output.writeInt(theField.intValue()); // and other simple types * // or returns false */ private boolean genWriteSimpleKeyField(MethodVisitor mv, FieldInfo field) { if (genWritePrimitiveField(mv, field)) { return true; } String fieldClassName = field.type.getClassName(); if (!isSimpleRefType(fieldClassName)) { return false; } mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, field.name, field.type.getDescriptor()); Integer sort = PRIMITIVE_WRAPPERS.get(fieldClassName); if (sort != null) { genUnwrapPrimitive(mv, sort); genWritePrimitive(mv, sort); } else if (fieldClassName.equals(Date.class.getName())) { mv.visitMethodInsn (INVOKEVIRTUAL, "java/util/Date", "getTime", "()J"); genWritePrimitive(mv, Type.LONG); } else if (fieldClassName.equals(String.class.getName())) { mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeString", "(Ljava/lang/String;)Lcom/sleepycat/bind/tuple/TupleOutput;"); mv.visitInsn(POP); } else if (fieldClassName.equals(BigInteger.class.getName())) { mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeBigInteger", "(Ljava/math/BigInteger;)Lcom/sleepycat/bind/tuple/TupleOutput;"); mv.visitInsn(POP); } else if (fieldClassName.equals(BigDecimal.class.getName())) { mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeSortedBigDecimal", "(Ljava/math/BigDecimal;)Lcom/sleepycat/bind/tuple/TupleOutput;"); mv.visitInsn(POP); } else { throw DbCompat.unexpectedState(fieldClassName); } return true; } private boolean genWritePrimitiveField(MethodVisitor mv, FieldInfo field) { int sort = field.type.getSort(); if (sort == Type.OBJECT || sort == Type.ARRAY) { return false; } mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, field.name, field.type.getDescriptor()); genWritePrimitive(mv, sort); return true; } /** * // if has super: * if (superLevel != 0) { * super.bdbReadXxxKeyFields(..., superLevel - 1); * } */ private void genReadSuperKeyFields(MethodVisitor mv, boolean areSecKeyFields) { if (hasPersistentSuperclass) { Label next = new Label(); mv.visitVarInsn(ILOAD, 4); mv.visitJumpInsn(IFEQ, next); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(ILOAD, 3); mv.visitVarInsn(ILOAD, 4); mv.visitInsn(ICONST_1); mv.visitInsn(ISUB); String name = areSecKeyFields ? "bdbReadSecKeyFields" : "bdbReadNonKeyFields"; mv.visitMethodInsn (INVOKESPECIAL, superclassName, name, "(Lcom/sleepycat/persist/impl/EntityInput;III)V"); mv.visitLabel(next); } } /** * public void bdbReadXxxKeyFields(EntityInput input, * int startField, * int endField, * int superLevel) { * // ... * if (superLevel <= 0) { * switch (startField) { * case 0: * keyField1 = input.readInt(); * if (endField == 0) break; * case 1: * keyField2 = (String) input.readObject(); * if (endField == 1) break; * case 2: * keyField3 = input.readInt(); * } * } */ private void genReadFieldSwitch(MethodVisitor mv, List fields) { int nFields = fields.size(); if (nFields > 0) { mv.visitVarInsn(ILOAD, 4); Label pastSwitch = new Label(); mv.visitJumpInsn(IFGT, pastSwitch); Label[] labels = new Label[nFields]; for (int i = 0; i < nFields; i += 1) { labels[i] = new Label(); } mv.visitVarInsn(ILOAD, 2); mv.visitTableSwitchInsn(0, nFields - 1, pastSwitch, labels); for (int i = 0; i < nFields; i += 1) { FieldInfo field = fields.get(i); mv.visitLabel(labels[i]); genReadField(mv, field); if (i < nFields - 1) { Label nextCase = labels[i + 1]; mv.visitVarInsn(ILOAD, 3); if (i == 0) { mv.visitJumpInsn(IFNE, nextCase); } else { switch (i) { case 1: mv.visitInsn(ICONST_1); break; case 2: mv.visitInsn(ICONST_2); break; case 3: mv.visitInsn(ICONST_3); break; case 4: mv.visitInsn(ICONST_4); break; case 5: mv.visitInsn(ICONST_5); break; default: mv.visitIntInsn(BIPUSH, i); } mv.visitJumpInsn(IF_ICMPNE, nextCase); } mv.visitJumpInsn(GOTO, pastSwitch); } } mv.visitLabel(pastSwitch); } } /** * field = input.readInt(); // and other primitives * // or * field = (FieldClass) input.readObject(); */ private void genReadField(MethodVisitor mv, FieldInfo field) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); if (field.isString) { /* * In JE 5.0, we treat String as primitive, and will not store * format ID for String data. [#19247] */ mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readStringObject", "()Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, getTypeInstName(field.type)); } else if (isRefType(field.type)) { mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readObject", "()Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, getTypeInstName(field.type)); } else { genReadPrimitive(mv, field.type.getSort()); } mv.visitFieldInsn (PUTFIELD, className, field.name, field.type.getDescriptor()); } /** * Generates reading of a simple type key field, or returns false if the * key field is not a simple type (i.e., it is a composite key type). * * field = input.readInt(); // and other primitives * // or * field = Integer.valueOf(input.readInt()); // and other simple types * // or returns false */ private boolean genReadSimpleKeyField(MethodVisitor mv, FieldInfo field) { if (genReadPrimitiveField(mv, field)) { return true; } String fieldClassName = field.type.getClassName(); if (!isSimpleRefType(fieldClassName)) { return false; } Integer sort = PRIMITIVE_WRAPPERS.get(fieldClassName); if (sort != null) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); genReadPrimitive(mv, sort); genWrapPrimitive(mv, sort); } else if (fieldClassName.equals(Date.class.getName())) { /* Date is a special case because we use NEW instead of valueOf. */ mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(NEW, "java/util/Date"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); genReadPrimitive(mv, Type.LONG); mv.visitMethodInsn (INVOKESPECIAL, "java/util/Date", "", "(J)V"); } else if (fieldClassName.equals(String.class.getName())) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readString", "()Ljava/lang/String;"); } else if (fieldClassName.equals(BigInteger.class.getName())) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readBigInteger", "()Ljava/math/BigInteger;"); } else if (fieldClassName.equals(BigDecimal.class.getName())) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readSortedBigDecimal", "()Ljava/math/BigDecimal;"); } else { throw DbCompat.unexpectedState(fieldClassName); } mv.visitFieldInsn (PUTFIELD, className, field.name, field.type.getDescriptor()); return true; } private boolean genReadPrimitiveField(MethodVisitor mv, FieldInfo field) { int sort = field.type.getSort(); if (sort == Type.OBJECT || sort == Type.ARRAY) { return false; } mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); genReadPrimitive(mv, sort); mv.visitFieldInsn (PUTFIELD, className, field.name, field.type.getDescriptor()); return true; } /** * public Object bdbGetField(Object o, * int field, * int superLevel, * boolean isSecField) { * if (superLevel > 0) { * // if has superclass: * return super.bdbGetField * (o, field, superLevel - 1, isSecField); * } else if (isSecField) { * switch (field) { * case 0: * return Integer.valueOf(f2); * case 1: * return f3; * case 2: * return f4; * } * } else { * switch (field) { * case 0: * return Integer.valueOf(f5); * case 1: * return f6; * case 2: * return f7; * } * } * return null; * } */ private void genBdbGetField() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbGetField", "(Ljava/lang/Object;IIZ)Ljava/lang/Object;", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 3); Label l0 = new Label(); mv.visitJumpInsn(IFLE, l0); Label l1 = new Label(); if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(ILOAD, 3); mv.visitInsn(ICONST_1); mv.visitInsn(ISUB); mv.visitVarInsn(ILOAD, 4); mv.visitMethodInsn (INVOKESPECIAL, className, "bdbGetField", "(Ljava/lang/Object;IIZ)Ljava/lang/Object;"); mv.visitInsn(ARETURN); } else { mv.visitJumpInsn(GOTO, l1); } mv.visitLabel(l0); mv.visitVarInsn(ILOAD, 4); Label l2 = new Label(); mv.visitJumpInsn(IFEQ, l2); genGetFieldSwitch(mv, secKeyFields, l1); mv.visitLabel(l2); genGetFieldSwitch(mv, nonKeyFields, l1); mv.visitLabel(l1); mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); mv.visitMaxs(1, 5); mv.visitEnd(); } /** * mv.visitVarInsn(ILOAD, 2); * Label l0 = new Label(); * Label l1 = new Label(); * Label l2 = new Label(); * mv.visitTableSwitchInsn(0, 2, TheDefLabel, new Label[] { l0, l1, l2 }); * mv.visitLabel(l0); * mv.visitVarInsn(ALOAD, 0); * mv.visitFieldInsn(GETFIELD, TheClassName, "f2", "I"); * mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", * "(I)Ljava/lang/Integer;"); * mv.visitInsn(ARETURN); * mv.visitLabel(l1); * mv.visitVarInsn(ALOAD, 0); * mv.visitFieldInsn(GETFIELD, TheClassName, "f3", "Ljava/lang/String;"); * mv.visitInsn(ARETURN); * mv.visitLabel(l2); * mv.visitVarInsn(ALOAD, 0); * mv.visitFieldInsn(GETFIELD, TheClassName, "f4", "Ljava/lang/String;"); * mv.visitInsn(ARETURN); */ private void genGetFieldSwitch(MethodVisitor mv, List fields, Label defaultLabel) { int nFields = fields.size(); if (nFields == 0) { mv.visitJumpInsn(GOTO, defaultLabel); return; } Label[] labels = new Label[nFields]; for (int i = 0; i < nFields; i += 1) { labels[i] = new Label(); } mv.visitVarInsn(ILOAD, 2); mv.visitTableSwitchInsn(0, nFields - 1, defaultLabel, labels); for (int i = 0; i < nFields; i += 1) { FieldInfo field = fields.get(i); mv.visitLabel(labels[i]); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn (GETFIELD, className, field.name, field.type.getDescriptor()); if (!isRefType(field.type)) { genWrapPrimitive(mv, field.type.getSort()); } mv.visitInsn(ARETURN); } } /** * public void bdbSetField(Object o, * int field, * int superLevel, * boolean isSecField, * Object value) { * if (superLevel > 0) { * // if has superclass: * super.bdbSetField * (o, field, superLevel - 1, isSecField, value); * } else if (isSecField) { * switch (field) { * case 0: * f2 = ((Integer) value).intValue(); * case 1: * f3 = (String) value; * case 2: * f4 = (String) value; * } * } else { * switch (field) { * case 0: * f5 = ((Integer) value).intValue(); * case 1: * f6 = (String) value; * case 2: * f7 = (String) value; * } * } * } */ private void genBdbSetField() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbSetField", "(Ljava/lang/Object;IIZLjava/lang/Object;)V", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 3); Label l0 = new Label(); mv.visitJumpInsn(IFLE, l0); if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(ILOAD, 3); mv.visitInsn(ICONST_1); mv.visitInsn(ISUB); mv.visitVarInsn(ILOAD, 4); mv.visitVarInsn(ALOAD, 5); mv.visitMethodInsn (INVOKESPECIAL, className, "bdbSetField", "(Ljava/lang/Object;IIZLjava/lang/Object;)V"); } mv.visitInsn(RETURN); mv.visitLabel(l0); mv.visitVarInsn(ILOAD, 4); Label l2 = new Label(); mv.visitJumpInsn(IFEQ, l2); Label l1 = new Label(); genSetFieldSwitch(mv, secKeyFields, l1); mv.visitLabel(l2); genSetFieldSwitch(mv, nonKeyFields, l1); mv.visitLabel(l1); mv.visitInsn(RETURN); mv.visitMaxs(2, 6); mv.visitEnd(); } /** * public void bdbSetPriField(Object o, Object value) { * if (priKeyField != null) { * thisField = (TheFieldClass) value; * } else if (super != null) { * // if has superclass: * super.bdbSetPriField(o, value) * } * } */ private void genBdbSetPriField() { MethodVisitor mv = cv.visitMethod (ACC_PUBLIC, "bdbSetPriField", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null); mv.visitCode(); if (priKeyField != null) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 2); if (isRefType(priKeyField.type)) { mv.visitTypeInsn(CHECKCAST, getTypeInstName(priKeyField.type)); } else { int sort = priKeyField.type.getSort(); mv.visitTypeInsn (CHECKCAST, getPrimitiveWrapperClass(sort).replace('.', '/')); genUnwrapPrimitive(mv, sort); } mv.visitFieldInsn (PUTFIELD, className, priKeyField.name, priKeyField.type.getDescriptor()); } else if (hasPersistentSuperclass) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn (INVOKESPECIAL, superclassName, "bdbSetPriField", "(Ljava/lang/Object;Ljava/lang/Object;)V"); } mv.visitInsn(RETURN); mv.visitMaxs(3, 3); mv.visitEnd(); } /** * mv.visitVarInsn(ILOAD, 2); * Label l0 = new Label(); * Label l1 = new Label(); * Label l2 = new Label(); * mv.visitTableSwitchInsn(0, 2, TheDefLabel, new Label[] { l0, l1, l2 }); * mv.visitLabel(l0); * mv.visitVarInsn(ALOAD, 0); * mv.visitVarInsn(ALOAD, 5); * mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); * mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", * "()I"); * mv.visitFieldInsn(PUTFIELD, TheClassName, "f2", "I"); * mv.visitLabel(l1); * mv.visitVarInsn(ALOAD, 0); * mv.visitVarInsn(ALOAD, 5); * mv.visitTypeInsn(CHECKCAST, "java/lang/String"); * mv.visitFieldInsn(PUTFIELD, TheClassName, "f3", "Ljava/lang/String;"); * mv.visitLabel(l2); * mv.visitVarInsn(ALOAD, 0); * mv.visitVarInsn(ALOAD, 5); * mv.visitTypeInsn(CHECKCAST, "java/lang/String"); * mv.visitFieldInsn(PUTFIELD, TheClassName, "f4", "Ljava/lang/String;"); */ private void genSetFieldSwitch(MethodVisitor mv, List fields, Label defaultLabel) { int nFields = fields.size(); if (nFields == 0) { mv.visitJumpInsn(GOTO, defaultLabel); return; } Label[] labels = new Label[nFields]; for (int i = 0; i < nFields; i += 1) { labels[i] = new Label(); } mv.visitVarInsn(ILOAD, 2); mv.visitTableSwitchInsn(0, nFields - 1, defaultLabel, labels); for (int i = 0; i < nFields; i += 1) { FieldInfo field = fields.get(i); mv.visitLabel(labels[i]); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 5); if (isRefType(field.type)) { mv.visitTypeInsn(CHECKCAST, getTypeInstName(field.type)); } else { int sort = field.type.getSort(); mv.visitTypeInsn (CHECKCAST, getPrimitiveWrapperClass(sort).replace('.', '/')); genUnwrapPrimitive(mv, sort); } mv.visitFieldInsn (PUTFIELD, className, field.name, field.type.getDescriptor()); mv.visitInsn(RETURN); } } private void genWritePrimitive(MethodVisitor mv, int sort) { switch (sort) { case Type.BOOLEAN: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeBoolean", "(Z)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.CHAR: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeChar", "(I)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.BYTE: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeByte", "(I)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.SHORT: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeShort", "(I)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.INT: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeInt", "(I)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.LONG: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeLong", "(J)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.FLOAT: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeSortedFloat", "(F)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; case Type.DOUBLE: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityOutput", "writeSortedDouble", "(D)Lcom/sleepycat/bind/tuple/TupleOutput;"); break; default: throw DbCompat.unexpectedState(String.valueOf(sort)); } /* The write methods always return 'this' and we always discard it. */ mv.visitInsn(POP); } private void genReadPrimitive(MethodVisitor mv, int sort) { switch (sort) { case Type.BOOLEAN: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readBoolean", "()Z"); break; case Type.CHAR: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readChar", "()C"); break; case Type.BYTE: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readByte", "()B"); break; case Type.SHORT: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readShort", "()S"); break; case Type.INT: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readInt", "()I"); break; case Type.LONG: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readLong", "()J"); break; case Type.FLOAT: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readSortedFloat", "()F"); break; case Type.DOUBLE: mv.visitMethodInsn (INVOKEINTERFACE, "com/sleepycat/persist/impl/EntityInput", "readSortedDouble", "()D"); break; default: throw DbCompat.unexpectedState(String.valueOf(sort)); } } private void genWrapPrimitive(MethodVisitor mv, int sort) { switch (sort) { case Type.BOOLEAN: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); break; case Type.CHAR: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); break; case Type.BYTE: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); break; case Type.SHORT: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); break; case Type.INT: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); break; case Type.LONG: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); break; case Type.FLOAT: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); break; case Type.DOUBLE: mv.visitMethodInsn (INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); break; default: throw DbCompat.unexpectedState(String.valueOf(sort)); } } private void genUnwrapPrimitive(MethodVisitor mv, int sort) { switch (sort) { case Type.BOOLEAN: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); break; case Type.CHAR: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); break; case Type.BYTE: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B"); break; case Type.SHORT: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); break; case Type.INT: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); break; case Type.LONG: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); break; case Type.FLOAT: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); break; case Type.DOUBLE: mv.visitMethodInsn (INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); break; default: throw DbCompat.unexpectedState(String.valueOf(sort)); } } /** * Returns the type name for a visitTypeInsn operand, which is the internal * name for an object type and the descriptor for an array type. Must not * be called for a non-reference type. */ private static String getTypeInstName(Type type) { if (type.getSort() == Type.OBJECT) { return type.getInternalName(); } else if (type.getSort() == Type.ARRAY) { return type.getDescriptor(); } else { throw DbCompat.unexpectedState(); } } /** * Call this method before comparing a non-reference operand to zero as an * int, for example, with IFNE, IFEQ, IFLT, etc. If the operand is a long, * float or double, this method will compare it to zero and leave the * result as an int operand. */ private static void genBeforeCompareToZero(MethodVisitor mv, Type type) { switch (type.getSort()) { case Type.LONG: mv.visitInsn(LCONST_0); mv.visitInsn(LCMP); break; case Type.FLOAT: mv.visitInsn(FCONST_0); mv.visitInsn(FCMPL); break; case Type.DOUBLE: mv.visitInsn(DCONST_0); mv.visitInsn(DCMPL); break; } } /** * Returns true if the given class is a primitive wrapper, Date or String. */ static boolean isSimpleRefType(String className) { return (PRIMITIVE_WRAPPERS.containsKey(className) || className.equals(BigInteger.class.getName()) || className.equals(BigDecimal.class.getName()) || className.equals(Date.class.getName()) || className.equals(String.class.getName())); } /** * Returns the wrapper class for a primitive. */ static String getPrimitiveWrapperClass(int primitiveSort) { for (Map.Entry entry : PRIMITIVE_WRAPPERS.entrySet()) { if (entry.getValue() == primitiveSort) { return entry.getKey(); } } throw DbCompat.unexpectedState(String.valueOf(primitiveSort)); } /** * Returns true if the given type is an object or array. */ private static boolean isRefType(Type type) { int sort = type.getSort(); return (sort == Type.OBJECT || sort == Type.ARRAY); } /** * Returns whether a string array contains a given string. */ private static boolean containsString(String[] a, String s) { if (a != null) { for (String t : a) { if (s.equals(t)) { return true; } } } return false; } /** * Appends a string to a string array. */ private static String[] appendString(String[] a, String s) { if (a != null) { int len = a.length; String[] a2 = new String[len + 1]; System.arraycopy(a, 0, a2, 0, len); a2[len] = s; return a2; } else { return new String[] { s }; } } /** * Aborts the enhancement process when we determine that enhancement is * unnecessary or not possible. */ private NotPersistentException abort() { return NOT_PERSISTENT; } private static class FieldInfo extends FieldVisitor { FieldVisitor parent; String name; Type type; OrderInfo order; boolean isPriKey; boolean isSecKey; boolean isTransient; boolean isString = false; FieldInfo(FieldVisitor parent, String name, String desc, boolean isTransient) { super(ASM4); this.parent = parent; this.name = name; this.isTransient = isTransient; type = Type.getType(desc); if (type.getClassName().equals(String.class.getName())) { isString = true; } } public AnnotationVisitor visitAnnotation(String desc, boolean visible) { AnnotationVisitor ret = parent.visitAnnotation(desc, visible); if (desc.equals ("Lcom/sleepycat/persist/model/KeyField;")) { order = new OrderInfo(ret); ret = order; } else if (desc.equals ("Lcom/sleepycat/persist/model/PrimaryKey;")) { isPriKey = true; } else if (desc.equals ("Lcom/sleepycat/persist/model/SecondaryKey;")) { isSecKey = true; } else if (desc.equals ("Lcom/sleepycat/persist/model/NotPersistent;")) { isTransient = true; } else if (desc.equals ("Lcom/sleepycat/persist/model/NotTransient;")) { isTransient = false; } return ret; } public void visitAttribute(Attribute attr) { parent.visitAttribute(attr); } public void visitEnd() { parent.visitEnd(); } @Override public String toString() { String label; if (isPriKey) { label = "PrimaryKey"; } else if (isSecKey) { label = "SecondaryKey"; } else if (order != null) { label = "CompositeKeyField " + order.value; } else { label = "NonKeyField"; } return "[" + label + ' ' + name + ' ' + type + ']'; } } private static class OrderInfo extends AnnotationInfo { int value; OrderInfo(AnnotationVisitor parent) { super(parent); } @Override public void visit(String name, Object value) { if (name.equals("value")) { this.value = (Integer) value; } parent.visit(name, value); } } private static abstract class AnnotationInfo extends AnnotationVisitor { AnnotationVisitor parent; AnnotationInfo(AnnotationVisitor parent) { super(ASM4); this.parent = parent; } public void visit(String name, Object value) { parent.visit(name, value); } public AnnotationVisitor visitAnnotation(String name, String desc) { return parent.visitAnnotation(name, desc); } public AnnotationVisitor visitArray(String name) { return parent.visitArray(name); } public void visitEnum(String name, String desc, String value) { parent.visitEnum(name, desc, value); } public void visitEnd() { parent.visitEnd(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy