0001: /*
0002: * Copyright (c) 1998 - 2005 Versant Corporation
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * Versant Corporation - initial API and implementation
0010: */
0011: package com.versant.core.jdo.tools.enhancer;
0012:
0013: import com.versant.lib.bcel.Constants;
0014: import com.versant.lib.bcel.classfile.*;
0015: import com.versant.lib.bcel.generic.*;
0016: import com.versant.core.common.Debug;
0017: import com.versant.core.jdo.tools.enhancer.info.ClassInfo;
0018: import com.versant.core.jdo.tools.enhancer.info.FieldInfo;
0019: import com.versant.core.jdo.tools.enhancer.utils.SerialUIDHelper;
0020: import com.versant.core.jdo.tools.enhancer.utils.SwapFieldHelper;
0021: import com.versant.core.jdo.tools.enhancer.utils.TableSwitchHelper;
0022: import com.versant.core.metadata.ClassMetaData;
0023: import com.versant.core.metadata.MDStatics;
0024:
0025: import javax.jdo.JDOUserException;
0026: import java.io.File;
0027: import java.io.IOException;
0028: import java.io.InputStream;
0029: import java.util.*;
0030: import java.net.URL;
0031:
0032: /**
0033: * This class does the enhancement on class files
0034: *
0035: */
0036: public class ClassEnhancer {
0037:
0038: private ClassGen classGen;
0039: private ConstantPoolGen constantPoolGen;
0040: private InstructionFactory instructionFactory;
0041: private ClassInfo classInfo;
0042: private Set fieldSet;
0043: private File outputDir;
0044: private ClassLoader loader;
0045: private static int javaVersion;
0046:
0047: private boolean isEmpty = false;
0048: private boolean didWeAddADefaultConstructor = false;
0049:
0050: public static final int JAVA_1_0 = 10;
0051: public static final int JAVA_1_1 = 11;
0052: public static final int JAVA_1_2 = 12;
0053: public static final int JAVA_1_3 = 13;
0054: public static final int JAVA_1_4 = 14;
0055: public static final int JAVA_1_5 = 15;
0056:
0057: private static final String getField = com.versant.lib.bcel.generic.GETFIELD.class
0058: .getName();
0059: private static final String putField = com.versant.lib.bcel.generic.PUTFIELD.class
0060: .getName();
0061: private static final String invokeSpecial = com.versant.lib.bcel.generic.INVOKESPECIAL.class
0062: .getName();
0063: private static final String aload = com.versant.lib.bcel.generic.ALOAD.class
0064: .getName();
0065: private static final String dup = com.versant.lib.bcel.generic.DUP.class
0066: .getName();
0067:
0068: private HashMap getAndSettersMap;
0069: private HashMap typeToReturnType;
0070: private HashMap typeToSetField;
0071: private HashMap typeToFieldProvider;
0072: private HashMap typeToProvidedField;
0073: private HashMap typeToReplacingField;
0074: private HashMap typeToGetField;
0075: private HashMap typeToLoadType;
0076: private HashMap typeToFieldReplacer;
0077:
0078: private HashMap primativeTypesToWrapper;
0079:
0080: private String fileSeparator;
0081: private char charfileSeparator; //
0082: private static final String VERSANT_STATE_MANAGER = com.versant.core.jdo.VersantStateManager.class
0083: .getName();
0084:
0085: private final static String PERSISTENCE_CAPABLE = javax.jdo.spi.PersistenceCapable.class
0086: .getName();
0087: private final static ObjectType PC_OBJECT_TYPE = new ObjectType(
0088: PERSISTENCE_CAPABLE);
0089: private final static String STATE_MANAGER = javax.jdo.spi.StateManager.class
0090: .getName();
0091: private final static ObjectType SM_OBJECT_TYPE = new ObjectType(
0092: STATE_MANAGER);
0093: private int CHECK_WRITE = javax.jdo.spi.PersistenceCapable.CHECK_WRITE;
0094: private int CHECK_READ_WRITE = javax.jdo.spi.PersistenceCapable.CHECK_READ
0095: + javax.jdo.spi.PersistenceCapable.CHECK_WRITE;
0096: private int MEDIATE_READ_WRITE = javax.jdo.spi.PersistenceCapable.MEDIATE_READ
0097: + javax.jdo.spi.PersistenceCapable.MEDIATE_WRITE;
0098: private int synthetic;
0099: private String vendorName = "jdoVersant";
0100:
0101: private long currentSerialVersionUID;
0102: private static final String DIRTY_FIELD_NAME = "jdoVersantDirty";
0103: private static final String LOADED_FIELD_NAME = "jdoVersantLoaded";
0104: private static final String OID_FIELD_NAME = "jdoVersantOID";
0105: private static final String VERSION_FIELD_NAME = "jdoVersantVersion";
0106: private static final String DETACHABLE_INTERFASE = com.versant.core.jdo.VersantDetachable.class
0107: .getName();
0108: private static final String DETACHED_STATE_MANAGER = com.versant.core.jdo.VersantDetachedStateManager.class
0109: .getName();
0110: private int totlalManagedFields = 0;
0111: private boolean detach;
0112: private File currentOutputFile;
0113:
0114: public static final ObjectType INTEGER_TYPE = new ObjectType(
0115: "java.lang.Integer");
0116: public static final ObjectType BYTE_TYPE = new ObjectType(
0117: "java.lang.Byte");
0118: public static final ObjectType CHARACTER_TYPE = new ObjectType(
0119: "java.lang.Character");
0120: public static final ObjectType SHORT_TYPE = new ObjectType(
0121: "java.lang.Short");
0122: public static final ObjectType FLOAT_TYPE = new ObjectType(
0123: "java.lang.Float");
0124: public static final ObjectType DOUBLE_TYPE = new ObjectType(
0125: "java.lang.Double");
0126: public static final ObjectType LONG_TYPE = new ObjectType(
0127: "java.lang.Long");
0128: public static final ObjectType BOOLEAN_TYPE = new ObjectType(
0129: "java.lang.Boolean");
0130:
0131: // private static final String MAKE_HOLLOW_INTERFASE = com.versant.core.jdo.test.model.versantMakeHollow.class.getName();
0132:
0133: static {
0134:
0135: // Determine the Java version by looking at available classes
0136: // java.lang.StrictMath was introduced in JDK 1.3
0137: // java.lang.ThreadLocal was introduced in JDK 1.2
0138: // java.lang.Void was introduced in JDK 1.1
0139: // Count up version until a NoClassDefFoundError ends the try
0140:
0141: try {
0142: javaVersion = JAVA_1_0;
0143: Class.forName("java.lang.Void");
0144: javaVersion = JAVA_1_1;
0145: Class.forName("java.lang.ThreadLocal");
0146: javaVersion = JAVA_1_2;
0147: Class.forName("java.lang.StrictMath");
0148: javaVersion = JAVA_1_3;
0149: Class.forName("java.lang.CharSequence");
0150: javaVersion = JAVA_1_4;
0151: // Class.forName("java.lang.StringBuilder");
0152: // javaVersion = JAVA_1_5;
0153: } catch (ClassNotFoundException cnfe) {
0154: // swallow as we've hit the max class version that
0155: // we have
0156: }
0157: }
0158:
0159: public ClassEnhancer(File outputDir, ClassLoader loader) {
0160: this .outputDir = outputDir;
0161: this .loader = loader;
0162: fileSeparator = System.getProperty("file.separator");
0163: charfileSeparator = fileSeparator.charAt(0);
0164:
0165: typeToSetField = new HashMap();
0166: typeToSetField.put(Type.INT, "setIntField");
0167: typeToSetField.put(Type.BYTE, "setByteField");
0168: typeToSetField.put(Type.LONG, "setLongField");
0169: typeToSetField.put(Type.CHAR, "setCharField");
0170: typeToSetField.put(Type.SHORT, "setShortField");
0171: typeToSetField.put(Type.FLOAT, "setFloatField");
0172: typeToSetField.put(Type.DOUBLE, "setDoubleField");
0173: typeToSetField.put(Type.STRING, "setStringField");
0174: typeToSetField.put(Type.BOOLEAN, "setBooleanField");
0175:
0176: typeToFieldProvider = new HashMap();
0177: typeToFieldProvider.put(Type.INT, "fetchIntField");
0178: typeToFieldProvider.put(Type.BYTE, "fetchByteField");
0179: typeToFieldProvider.put(Type.CHAR, "fetchCharField");
0180: typeToFieldProvider.put(Type.SHORT, "fetchShortField");
0181: typeToFieldProvider.put(Type.FLOAT, "fetchFloatField");
0182: typeToFieldProvider.put(Type.DOUBLE, "fetchDoubleField");
0183: typeToFieldProvider.put(Type.LONG, "fetchLongField");
0184: typeToFieldProvider.put(Type.BOOLEAN, "fetchBooleanField");
0185: typeToFieldProvider.put(Type.STRING, "fetchStringField");
0186:
0187: typeToProvidedField = new HashMap();
0188: typeToProvidedField.put(Type.INT, "providedIntField");
0189: typeToProvidedField.put(Type.BYTE, "providedByteField");
0190: typeToProvidedField.put(Type.CHAR, "providedCharField");
0191: typeToProvidedField.put(Type.SHORT, "providedShortField");
0192: typeToProvidedField.put(Type.FLOAT, "providedFloatField");
0193: typeToProvidedField.put(Type.DOUBLE, "providedDoubleField");
0194: typeToProvidedField.put(Type.LONG, "providedLongField");
0195: typeToProvidedField.put(Type.BOOLEAN, "providedBooleanField");
0196: typeToProvidedField.put(Type.STRING, "providedStringField");
0197:
0198: typeToReplacingField = new HashMap();
0199: typeToReplacingField.put(Type.INT, "replacingIntField");
0200: typeToReplacingField.put(Type.BYTE, "replacingByteField");
0201: typeToReplacingField.put(Type.CHAR, "replacingCharField");
0202: typeToReplacingField.put(Type.SHORT, "replacingShortField");
0203: typeToReplacingField.put(Type.FLOAT, "replacingFloatField");
0204: typeToReplacingField.put(Type.DOUBLE, "replacingDoubleField");
0205: typeToReplacingField.put(Type.LONG, "replacingLongField");
0206: typeToReplacingField.put(Type.BOOLEAN, "replacingBooleanField");
0207: typeToReplacingField.put(Type.STRING, "replacingStringField");
0208:
0209: typeToFieldReplacer = new HashMap();
0210: typeToFieldReplacer.put(Type.INT, "storeIntField");
0211: typeToFieldReplacer.put(Type.BYTE, "storeByteField");
0212: typeToFieldReplacer.put(Type.CHAR, "storeCharField");
0213: typeToFieldReplacer.put(Type.SHORT, "storeShortField");
0214: typeToFieldReplacer.put(Type.FLOAT, "storeFloatField");
0215: typeToFieldReplacer.put(Type.DOUBLE, "storeDoubleField");
0216: typeToFieldReplacer.put(Type.LONG, "storeLongField");
0217: typeToFieldReplacer.put(Type.BOOLEAN, "storeBooleanField");
0218: typeToFieldReplacer.put(Type.STRING, "storeStringField");
0219:
0220: typeToGetField = new HashMap();
0221: typeToGetField.put(Type.INT, "getIntField");
0222: typeToGetField.put(Type.BYTE, "getByteField");
0223: typeToGetField.put(Type.CHAR, "getCharField");
0224: typeToGetField.put(Type.SHORT, "getShortField");
0225: typeToGetField.put(Type.FLOAT, "getFloatField");
0226: typeToGetField.put(Type.DOUBLE, "getDoubleField");
0227: typeToGetField.put(Type.LONG, "getLongField");
0228: typeToGetField.put(Type.BOOLEAN, "getBooleanField");
0229: typeToGetField.put(Type.STRING, "getStringField");
0230:
0231: typeToReturnType = new HashMap();
0232: typeToReturnType.put(Type.INT, new IRETURN());
0233: typeToReturnType.put(Type.BYTE, new IRETURN());
0234: typeToReturnType.put(Type.CHAR, new IRETURN());
0235: typeToReturnType.put(Type.SHORT, new IRETURN());
0236: typeToReturnType.put(Type.FLOAT, new FRETURN());
0237: typeToReturnType.put(Type.DOUBLE, new DRETURN());
0238: typeToReturnType.put(Type.LONG, new LRETURN());
0239: typeToReturnType.put(Type.BOOLEAN, new IRETURN());
0240: typeToReturnType.put(Type.STRING, new ARETURN());
0241:
0242: typeToLoadType = new HashMap();
0243: typeToLoadType.put(Type.INT, new ILOAD(1));
0244: typeToLoadType.put(Type.BYTE, new ILOAD(1));
0245: typeToLoadType.put(Type.CHAR, new ILOAD(1));
0246: typeToLoadType.put(Type.SHORT, new ILOAD(1));
0247: typeToLoadType.put(Type.FLOAT, new FLOAD(1));
0248: typeToLoadType.put(Type.DOUBLE, new DLOAD(1));
0249: typeToLoadType.put(Type.LONG, new LLOAD(1));
0250: typeToLoadType.put(Type.BOOLEAN, new ILOAD(1));
0251: typeToLoadType.put(Type.STRING, new ALOAD(1));
0252:
0253: primativeTypesToWrapper = new HashMap(8);
0254: primativeTypesToWrapper.put(Type.INT, INTEGER_TYPE);
0255: primativeTypesToWrapper.put(Type.BYTE, BYTE_TYPE);
0256: primativeTypesToWrapper.put(Type.CHAR, CHARACTER_TYPE);
0257: primativeTypesToWrapper.put(Type.SHORT, SHORT_TYPE);
0258: primativeTypesToWrapper.put(Type.FLOAT, FLOAT_TYPE);
0259: primativeTypesToWrapper.put(Type.DOUBLE, DOUBLE_TYPE);
0260: primativeTypesToWrapper.put(Type.LONG, LONG_TYPE);
0261: primativeTypesToWrapper.put(Type.BOOLEAN, BOOLEAN_TYPE);
0262:
0263: }
0264:
0265: public void setGetAndSettersMap(HashMap map) {
0266: getAndSettersMap = map;
0267: }
0268:
0269: private JavaClass getJavaClass(String className) throws IOException {
0270: String classFileName = className.replace('.', '/') + ".class";
0271: InputStream inputStream = loader
0272: .getResourceAsStream(classFileName);
0273: if (inputStream == null) {
0274: inputStream = loader.getResourceAsStream("/"
0275: + classFileName);
0276: if (inputStream == null) {
0277: throw new javax.jdo.JDOFatalUserException(
0278: "Class not found: " + className);
0279: }
0280: }
0281: ClassParser parser = new ClassParser(inputStream, classFileName);
0282: return parser.parse();
0283: }
0284:
0285: private JavaClass getOrigJavaClass(String className)
0286: throws IOException {
0287: String classFileName = className.replace('.', '/') + ".class";
0288: InputStream inputStream = loader
0289: .getResourceAsStream(classFileName);
0290: URL currentFileURL = loader.getResource(classFileName);
0291: if (currentFileURL.toString().startsWith("jar:")
0292: && outputDir == null) {
0293: throw new javax.jdo.JDOFatalUserException(
0294: "Can not write class "
0295: + className
0296: + " into a jar. Please specify a output directory.");
0297: }
0298: currentOutputFile = new File(currentFileURL.getFile());
0299: if (inputStream == null) {
0300: inputStream = loader.getResourceAsStream("/"
0301: + classFileName);
0302: currentFileURL = loader.getResource("/" + classFileName);
0303: if (currentFileURL.toString().startsWith("jar:")
0304: && outputDir == null) {
0305: throw new javax.jdo.JDOFatalUserException(
0306: "Can not write class "
0307: + className
0308: + " into a jar. Please specify a output directory.");
0309: }
0310: currentOutputFile = new File(currentFileURL.getFile());
0311: if (inputStream == null) {
0312: throw new javax.jdo.JDOFatalUserException(
0313: "Class not found: " + className);
0314: }
0315: }
0316: ClassParser parser = new ClassParser(inputStream, classFileName);
0317: return parser.parse();
0318: }
0319:
0320: public boolean enhance(ClassInfo classInfo, ClassMetaData cmd,
0321: boolean makeFieldsPrivate, boolean detached) {
0322: try {
0323: this .detach = detached;
0324: this .classInfo = classInfo;
0325: fieldSet = classInfo.getFieldList();
0326: if (fieldSet.isEmpty()) {
0327: isEmpty = true;
0328: } else {
0329: isEmpty = false;
0330: }
0331: JavaClass javaClass = getOrigJavaClass(classInfo
0332: .getClassName());
0333: classGen = new ClassGen(javaClass);
0334: // ConstantPoolGen is used to represent the constant pool of a Classfile ll
0335: constantPoolGen = classGen.getConstantPool();
0336: // used to create objects representing VM instructions
0337: instructionFactory = new InstructionFactory(constantPoolGen);
0338:
0339: if (implements PC()) { //if the class already implements PC, don't enhance
0340: return false;
0341: }
0342: currentSerialVersionUID = SerialUIDHelper
0343: .computeSerialVersionUID(javaClass);
0344: synthetic = classGen.getConstantPool().addUtf8("Synthetic");
0345:
0346: boolean topClass = classInfo.getTopPCSuperClass() == null;
0347: boolean appIdentity = classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION;
0348: didWeAddADefaultConstructor = false;
0349:
0350: //Tasks
0351: rewriteStaticConstructor();
0352: setDefaultConstructor();
0353: setClass$();
0354: addSerialVersionUID();
0355: addJdoFieldNames();
0356: addJdoFieldFlags();
0357: if (topClass)
0358: addJdoStateManager(); //super
0359: if (topClass)
0360: addJdoFlags(); //super
0361: addJdoInheritedFieldCount();
0362: addJdoPersistenceCapableSuperclass();
0363: addJdoFieldTypes();
0364: addJdoGetManagedFieldCount();
0365: if (topClass)
0366: addInterrogatives(); //super
0367: addFieldGetters();
0368: addFieldSetters();
0369: addJdoReplaceField();
0370: addJdoReplaceFields(); //super??????????????/
0371: addJdoProvideField();
0372: addJdoProvideFields(); //super??????????????/
0373: addJdoCopyFields();
0374: addJdoCopyField();
0375: if (topClass)
0376: addJdoPreSerialize(); //super
0377: addWriteObject();
0378: addReadObject();
0379: addRegisterClass();
0380: addJdoNewInstance1();
0381: addJdoNewInstance2();
0382: if (topClass || appIdentity)
0383: addJdoNewObjectIdInstance1();
0384: if (topClass || appIdentity)
0385: addJdoNewObjectIdInstance2();
0386: if (topClass)
0387: addJdoGetObjectId(); //super
0388: if (topClass)
0389: addJdoGetTransactionalObjectId(); //super
0390: if (topClass)
0391: addJdoReplaceStateManager(); //super
0392: if (topClass)
0393: addJdoCopyKeyFieldsToObjectId1();
0394: if (topClass)
0395: addJdoCopyKeyFieldsToObjectId2();
0396: if (topClass)
0397: addJdoCopyKeyFieldsFromObjectId1();
0398: if (topClass)
0399: addJdoCopyKeyFieldsFromObjectId2();
0400: if (topClass)
0401: addJdoReplaceFlags(); //super
0402:
0403: addJdoInterface();
0404: if (makeFieldsPrivate) {
0405: setEnhancedFieldsPrivate();
0406: }
0407: swapGetterAndSetter();
0408: swapClone();
0409:
0410: // addVersantMakeHollow(); // put it in later
0411: totlalManagedFields = 0;
0412: if (detach) {
0413: if (topClass) {
0414: ClassMetaData[] hier = cmd.pcHeirachy;
0415: for (int i = 0; i < hier.length; i++) {
0416: ClassMetaData classMetaData = hier[i];
0417: totlalManagedFields += classMetaData.managedFields.length;
0418: }
0419: addFields();
0420: addSetLoadedInt("versantSetLoaded"); //public void versantSetLoaded(int i);
0421: addIsLoadedInt("versantIsLoaded"); //boolean versantIsLoaded(int i);
0422: addIsDirty("versantIsDirty"); //boolean versantIsDirty();
0423: addMakeDirtyInt("versantMakeDirty");
0424: addIsDirtyInt("versantIsDirty"); //public boolean versantIsDirty(int fieldNo);
0425: addSetOid("versantSetOID"); //public void versantSetOID(Object id);
0426: addGetOid("versantGetOID"); //public Object versantGetOID();
0427: addGetVersion("versantGetVersion"); //public Object versantGetVersion();
0428: addSetVersion("versantSetVersion"); //public void versantSetVersion(Object version);
0429: addGetStateManager("versantGetDetachedStateManager"); //StateManager versantGetDetachedStateManager();
0430: addDetachInterfase();
0431: }
0432: addMakeDirtyString("versantMakeDirty"); //void versantMakeDirty(String s);// if the names change, change this method.
0433: }
0434:
0435: if (didWeAddADefaultConstructor) {
0436: isOurConstructorValid();
0437: }
0438: dumpClass();
0439:
0440: System.out.println("Persistence Capable = "
0441: + classInfo.getClassName());
0442:
0443: } catch (Exception e) {
0444: e.printStackTrace();
0445: if (Debug.DEBUG) {
0446: Debug.ERR.println("Error in Enhancer");
0447: e.printStackTrace(Debug.ERR);
0448: }
0449: }
0450: return true;
0451: }
0452:
0453: private void isOurConstructorValid() {
0454: //this gets done only for the least-derived persistence capable class.
0455: if (classInfo.getPersistenceCapableSuperclass() != null) {
0456: return;
0457: }
0458: String super Name = classGen.getSuperclassName();
0459: try {
0460: JavaClass javaClass = getJavaClass(super Name);
0461: ClassGen classGen = new ClassGen(javaClass);
0462: Method[] methods = classGen.getMethods();
0463: for (int i = 0; i < methods.length; i++) {
0464: Method m = methods[i];
0465: // native and abstract methods don't have any code
0466: // so continue with next method
0467: if (m.isNative() || m.isAbstract()) {
0468: continue;
0469: }
0470: if (m.getName().equals("<init>")) { //is constructor
0471: if (m.getSignature().equals("()V")) { //is no args constructor
0472: if (!m.isPrivate()) {
0473: return;
0474: }
0475: }
0476: }
0477: }
0478: throw new JDOUserException(
0479: "Could not create a valid default constructor for class "
0480: + this .classGen.getClassName());
0481: } catch (IOException e) {
0482: // hide exception, this class is not on our classpath
0483: }
0484: }
0485:
0486: private void addDefaultConstructorToNonPersistantSuperClasses(
0487: String super Name) {
0488: //this gets done only for the least-derived persistence capable class.
0489: if (super Name == null) {
0490: if (classInfo.getPersistenceCapableSuperclass() != null) {
0491: return;
0492: }
0493: super Name = classGen.getSuperclassName();
0494: }
0495:
0496: try {
0497: JavaClass javaClass = getJavaClass(super Name);
0498: ClassGen classGen = new ClassGen(javaClass);
0499: // ConstantPoolGen is used to represent the constant pool of a Classfile ll
0500: ConstantPoolGen constantPoolGen = classGen
0501: .getConstantPool();
0502:
0503: Method[] methods = classGen.getMethods();
0504: for (int i = 0; i < methods.length; i++) {
0505: Method m = methods[i];
0506: // native and abstract methods don't have any code
0507: // so continue with next method
0508: if (m.isNative() || m.isAbstract()) {
0509: continue;
0510: }
0511:
0512: if (m.getName().equals("<init>")) { //is constructor
0513: if (m.getSignature().equals("()V")) { //is no args constructor
0514: if (m.isPublic()) {
0515: return;
0516: } else { //there is a default constructor but access is wrong
0517: m.isPublic(true);
0518: m.isProtected(false); //change access to protected
0519: m.isPrivate(false); //take away private access
0520: String fileName = classGen.getClassName()
0521: .replace('.', charfileSeparator)
0522: + ".class";
0523: File dumpFile = new File(outputDir,
0524: fileName);
0525: try {
0526: classGen.getJavaClass().dump(dumpFile);
0527: } catch (IOException e) {
0528: //hide, we could not write out the class
0529: }
0530: return;
0531: }
0532: }
0533: }
0534: }
0535:
0536: InstructionList il = new InstructionList();
0537: il.append(InstructionConstants.THIS); // Push `this'
0538: il.append(new INVOKESPECIAL(constantPoolGen.addMethodref(
0539: classGen.getSuperclassName(), "<init>", "()V")));
0540: il.append(InstructionConstants.RETURN);
0541:
0542: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC, // todo this is not to spec it should be protected
0543: Type.VOID, Type.NO_ARGS, null, "<init>", classGen
0544: .getClassName(), il, constantPoolGen);
0545: methodGen.setMaxLocals();
0546: methodGen.setMaxStack();
0547:
0548: classGen.addMethod(methodGen.getMethod());
0549:
0550: String fileName = classGen.getClassName().replace('.',
0551: charfileSeparator)
0552: + ".class";
0553: File dumpFile = new File(outputDir, fileName);
0554: boolean error = false;
0555: try {
0556: classGen.getJavaClass().dump(dumpFile);
0557: } catch (IOException e) {
0558: //hide, we could not write out the class
0559: error = true;
0560:
0561: }
0562:
0563: if (!error) {
0564: // set our next class
0565: // Print warning
0566: if (this .classGen.getSuperclassName().equals(
0567: classGen.getClassName())) {
0568: System.out
0569: .println("WARNING: persistence capable class '"
0570: + this .classGen.getClassName()
0571: + "' has a non persistence super class \n'"
0572: + classGen.getClassName()
0573: + "', that does not have a default constructor, will add one.");
0574: }
0575:
0576: addDefaultConstructorToNonPersistantSuperClasses(classGen
0577: .getSuperclassName());
0578: }
0579:
0580: } catch (IOException e) {
0581: // hide exception, this class is not on our classpath
0582: }
0583: }
0584:
0585: private void swapClone() {
0586: // representation of methods in the class
0587: Method[] methods = classGen.getMethods();
0588: for (int i = 0; i < methods.length; i++) {
0589: Method m = methods[i];
0590:
0591: // native and abstract methods don't have any code
0592: // so continue with next method
0593: if (m.isNative() || m.isAbstract()) {
0594: continue;
0595: }
0596: //we do not want to enhance our enhanced methods
0597: if (m.getName().startsWith("<cl")) {
0598: continue;
0599: }
0600:
0601: boolean changed = false;
0602:
0603: MethodGen mg = new MethodGen(m, classGen.getClassName(),
0604: constantPoolGen);
0605:
0606: // get the code in form of an InstructionList object
0607: InstructionList il = mg.getInstructionList();
0608:
0609: // get the first instruction
0610: InstructionHandle ih = il.getStart();
0611:
0612: while (ih != null) {
0613: Instruction ins = ih.getInstruction();
0614: if (ins.getClass().getName().equals(invokeSpecial)) {
0615: INVOKESPECIAL is = (INVOKESPECIAL) ins;
0616: if (is.getClassName(constantPoolGen).equals(
0617: "java.lang.Object")
0618: && is.getMethodName(constantPoolGen)
0619: .equals("clone")
0620: && is.getSignature(constantPoolGen).equals(
0621: "()Ljava/lang/Object;")) {
0622:
0623: il.append(is, getCloneIL());
0624: il.setPositions();
0625: il.update();
0626: changed = true;
0627:
0628: }
0629: }
0630: // next instruction
0631: ih = ih.getNext();
0632: }
0633: // don't forget to write the code
0634: if (changed) {
0635: il.setPositions();
0636: il.update();
0637: mg.setMaxLocals();
0638: mg.setMaxStack();
0639: classGen.replaceMethod(m, mg.getMethod());
0640: }
0641: }
0642: }
0643:
0644: private InstructionList getCloneIL() {
0645: InstructionList il = new InstructionList();
0646: il.append(new DUP());
0647: il.append(instructionFactory.createCheckCast(new ObjectType(
0648: classGen.getClassName())));
0649: il.append(new ACONST_NULL());
0650: if (javaVersion >= JAVA_1_4) {
0651: il
0652: .append(instructionFactory.createPutField(classGen
0653: .getClassName(), "jdoStateManager",
0654: SM_OBJECT_TYPE));
0655: } else {
0656: il.append(instructionFactory.createPutField(
0657: getTopPCSuperOrCurrentClassName(),
0658: "jdoStateManager", SM_OBJECT_TYPE));
0659: }
0660: il.append(new DUP());
0661: il.append(instructionFactory.createCheckCast(new ObjectType(
0662: classGen.getClassName())));
0663: il.append(new ICONST(0));
0664: if (javaVersion >= JAVA_1_4) {
0665: il.append(instructionFactory.createPutField(classGen
0666: .getClassName(), "jdoFlags", Type.BYTE));
0667: } else {
0668: il.append(instructionFactory.createPutField(
0669: getTopPCSuperOrCurrentClassName(), "jdoFlags",
0670: Type.BYTE));
0671: }
0672: return il;
0673:
0674: }
0675:
0676: // private void addJdogenieMakeHollow() {
0677: //
0678: // InstructionList il = new InstructionList();
0679: // MethodGen methodGen = new MethodGen(
0680: // Constants.ACC_PUBLIC ,
0681: // Type.VOID,
0682: // new Type[]{},
0683: // new String[]{},
0684: // vendorName+"MakeHollow",
0685: // classGen.getClassName(),
0686: // il,
0687: // constantPoolGen);
0688: //
0689: // for (Iterator iterator = fieldSet.iterator();iterator.hasNext();) {
0690: // FieldInfo fieldInfo = (FieldInfo) iterator.next();
0691: // if (fieldInfo.isPrimative() && !fieldInfo.isArray()){
0692: // continue;
0693: // }
0694: // il.append(new ALOAD(0));
0695: // il.append(new ACONST_NULL());
0696: // il.append(instructionFactory.createPutField(
0697: // classGen.getClassName(),
0698: // fieldInfo.getFieldName(),
0699: // fieldInfo.getType()));
0700: //
0701: // }
0702: // if (classInfo.getPersistenceCapableSuperclass() != null){
0703: // il.append(new ALOAD(0));
0704: // il.append(instructionFactory.createInvoke(
0705: // classInfo.getPersistenceCapableSuperclass() ,
0706: // vendorName+"MakeHollow" ,
0707: // Type.VOID ,
0708: // new Type[]{} ,
0709: // Constants.INVOKESPECIAL));
0710: // il.append(new RETURN());
0711: // } else {
0712: // il.append(new RETURN());
0713: // }
0714: //
0715: // methodGen.setMaxLocals();
0716: // methodGen.setMaxStack();
0717: // classGen.addMethod(methodGen.getMethod());
0718: // il.dispose();
0719: //// classGen.addInterface(MAKE_HOLLOW_INTERFASE);
0720: // }
0721:
0722: private void dumpClass() throws VerifyException {
0723: String fileName = classGen.getClassName().replace('.',
0724: charfileSeparator)
0725: + ".class";
0726: File dumpFile;
0727: if (outputDir != null) {
0728: dumpFile = new File(outputDir, fileName);
0729: } else {
0730: dumpFile = currentOutputFile;
0731: }
0732: try {
0733: classGen.getJavaClass().dump(dumpFile);
0734: } catch (IOException e) {
0735: throw new VerifyException(e);
0736: }
0737:
0738: }
0739:
0740: /** Copy fields to an outside source from the key fields in the ObjectId.
0741: * This method is generated in the PersistenceCapable class to generate
0742: * a call to the field manager for each key field in the ObjectId. For
0743: * example, an ObjectId class that has three key fields (int id,
0744: * String name, and Float salary) would have the method generated:
0745: * <P>void copyKeyFieldsFromObjectId
0746: * <P> (PersistenceCapable oid, ObjectIdFieldManager fm) {
0747: * <P> fm.storeIntField (0, oid.id);
0748: * <P> fm.storeStringField (1, oid.name);
0749: * <P> fm.storeObjectField (2, oid.salary);
0750: * <P>}
0751: * <P>The implementation is responsible for implementing the
0752: * ObjectIdFieldManager to store the values for the key fields.
0753: * private void jdoCopyKeyFieldsFromObjectId(PersistenceCapable.ObjectIdFieldReplacer fm, Object oid){
0754: */
0755: private void addJdoCopyKeyFieldsFromObjectId1() {
0756: if (classInfo.getTopPCSuperClass() == null
0757: || (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION && classInfo
0758: .getObjectidClass() != null)) {
0759: InstructionList il = new InstructionList();
0760: MethodGen methodGen = new MethodGen(
0761: Constants.ACC_PUBLIC,
0762: Type.VOID,
0763: new Type[] {
0764: new ObjectType(
0765: "javax.jdo.spi.PersistenceCapable$ObjectIdFieldConsumer"),
0766: Type.OBJECT },
0767: new String[] { "fc", "oid" },
0768: "jdoCopyKeyFieldsFromObjectId", classGen
0769: .getClassName(), il, constantPoolGen);
0770: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION
0771: && classInfo.getObjectidClass() != null) {
0772: Iterator iter = classInfo.getFieldList().iterator();
0773: int count = 0;
0774: boolean isObject = false;
0775: while (iter.hasNext()) {
0776: FieldInfo info = (FieldInfo) iter.next();
0777: if (info.primaryKey()) {
0778: String fieldReplacerMethod = null;
0779: if (typeToFieldReplacer.containsKey(info
0780: .getType())) {
0781: fieldReplacerMethod = (String) typeToFieldReplacer
0782: .get(info.getType());
0783: isObject = false;
0784: } else {
0785: isObject = true;
0786: }
0787: il.append(new ALOAD(1));
0788: il.append(instructionFactory.createGetStatic(
0789: classGen.getClassName(),
0790: "jdoInheritedFieldCount", Type.INT));
0791: il.append(new PUSH(constantPoolGen, count));
0792: il.append(new IADD());
0793: il.append(new ALOAD(2));
0794: il.append(instructionFactory
0795: .createCheckCast(new ObjectType(
0796: classInfo.getObjectidClass())));
0797: il
0798: .append(instructionFactory
0799: .createGetField(classInfo
0800: .getObjectidClass(),
0801: info.getFieldName(),
0802: info.getType()));
0803:
0804: if (isObject) {
0805: il
0806: .append(instructionFactory
0807: .createInvoke(
0808: "javax.jdo.spi.PersistenceCapable$ObjectIdFieldConsumer",
0809: "storeObjectField",
0810: Type.VOID,
0811: new Type[] {
0812: Type.INT,
0813: Type.OBJECT },
0814: Constants.INVOKEINTERFACE));
0815: } else {
0816: il
0817: .append(instructionFactory
0818: .createInvoke(
0819: "javax.jdo.spi.PersistenceCapable$ObjectIdFieldConsumer",
0820: fieldReplacerMethod,
0821: Type.VOID,
0822: new Type[] {
0823: Type.INT,
0824: info
0825: .getType() },
0826: Constants.INVOKEINTERFACE));
0827: }
0828: }
0829: count++;
0830: }
0831: }
0832: il.append(new RETURN());
0833: // makeSynthetic(methodGen);
0834: methodGen.setMaxLocals();
0835: methodGen.setMaxStack();
0836: classGen.addMethod(methodGen.getMethod());
0837: il.dispose();
0838: }
0839: }
0840:
0841: private void addJdoCopyKeyFieldsFromObjectId2() {
0842: if (classInfo.getTopPCSuperClass() == null
0843: || (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION && classInfo
0844: .getObjectidClass() != null)) {
0845:
0846: InstructionList il = new InstructionList();
0847: MethodGen methodGen = new MethodGen(
0848: Constants.ACC_PROTECTED, Type.VOID,
0849: new Type[] { Type.OBJECT }, new String[] { "oid" },
0850: "jdoCopyKeyFieldsFromObjectId", classGen
0851: .getClassName(), il, constantPoolGen);
0852: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION
0853: && classInfo.getObjectidClass() != null) {
0854:
0855: il.append(new ALOAD(1));
0856: il.append(instructionFactory
0857: .createCheckCast(new ObjectType(classInfo
0858: .getObjectidClass())));
0859: il.append(new ASTORE(2));
0860: InstructionHandle pckStartHandle = null;
0861: boolean first = true;
0862: ClassInfo currentClass = getTopPCSuperOrCurrentClass();
0863: Iterator iter = currentClass.getFieldList().iterator();
0864: while (iter.hasNext()) {
0865: FieldInfo info = (FieldInfo) iter.next();
0866: if (info.primaryKey()) {
0867: if (first) {
0868: pckStartHandle = il.append(new ALOAD(0));
0869: first = false;
0870: } else {
0871: il.append(new ALOAD(0));
0872: }
0873: il.append(new ALOAD(2));
0874: il
0875: .append(instructionFactory
0876: .createGetField(classInfo
0877: .getObjectidClass(),
0878: info.getFieldName(),
0879: info.getType()));
0880: il
0881: .append(instructionFactory
0882: .createPutField(classInfo
0883: .getClassName(), info
0884: .getFieldName(), info
0885: .getType()));
0886: }
0887: }
0888: il.append(new RETURN());
0889: methodGen.addLocalVariable("pck", new ObjectType(
0890: classInfo.getObjectidClass()), 2,
0891: pckStartHandle, il.getEnd());
0892: } else {
0893: il.append(new RETURN());
0894: }
0895: // makeSynthetic(methodGen);
0896: methodGen.setMaxLocals();
0897: methodGen.setMaxStack();
0898: classGen.addMethod(methodGen.getMethod());
0899: il.dispose();
0900: }
0901: }
0902:
0903: private String getTopPCSuperOrCurrentClassName() {
0904: if (classInfo.getTopPCSuperClass() == null) {
0905: return classInfo.getClassName();
0906: } else {
0907: return classInfo.getTopPCSuperClass().getClassName();
0908: }
0909: }
0910:
0911: private ClassInfo getTopPCSuperOrCurrentClass() {
0912: if (classInfo.getTopPCSuperClass() == null) {
0913: return classInfo;
0914: } else {
0915: return classInfo.getTopPCSuperClass();
0916: }
0917: }
0918:
0919: private void addJdoReplaceFlags() {
0920: if (classInfo.getTopPCSuperClass() == null) {
0921: InstructionList il = new InstructionList();
0922: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
0923: Type.VOID, new Type[] {}, new String[] {},
0924: "jdoReplaceFlags", classGen.getClassName(), il,
0925: constantPoolGen);
0926:
0927: il.append(new ALOAD(0));
0928: il.append(instructionFactory.createGetField(
0929: getTopPCSuperOrCurrentClassName(),
0930: "jdoStateManager", SM_OBJECT_TYPE));
0931: IFNULL ifnull = new IFNULL(null);
0932: il.append(ifnull);
0933: il.append(new ALOAD(0));
0934: il.append(new ALOAD(0));
0935: il.append(instructionFactory.createGetField(
0936: getTopPCSuperOrCurrentClassName(),
0937: "jdoStateManager", SM_OBJECT_TYPE));
0938: il.append(new ALOAD(0));
0939: il.append(instructionFactory.createInvoke(STATE_MANAGER,
0940: "replacingFlags", Type.BYTE,
0941: new Type[] { PC_OBJECT_TYPE },
0942: Constants.INVOKEINTERFACE));
0943: il.append(instructionFactory.createPutField(
0944: getTopPCSuperOrCurrentClassName(), "jdoFlags",
0945: Type.BYTE));
0946: InstructionHandle handle = il.append(new RETURN());
0947: ifnull.setTarget(handle);
0948: // makeSynthetic(methodGen);
0949: methodGen.setMaxLocals();
0950: methodGen.setMaxStack();
0951:
0952: classGen.addMethod(methodGen.getMethod());
0953: il.dispose();
0954: }
0955: }
0956:
0957: private boolean mustEnhance(Method m) {
0958: String name = m.getName();
0959: if (name.startsWith(vendorName + "MakeHollow")) {
0960: return false;
0961: }
0962: if (name.startsWith(vendorName)) {
0963: return true;
0964: } else if (name.startsWith("jdo")) {
0965: if (classInfo.isInstanceCallbacks()
0966: && (name.equals("jdoPreStore") || name
0967: .equals("jdoPreDelete"))
0968: && m.getSignature().equals("()V")) {
0969: return true;
0970: }
0971: } else {
0972: return true;
0973: }
0974: return false;
0975: }
0976:
0977: private void swapGetterAndSetter() {
0978:
0979: // representation of methods in the class
0980: Method[] methods = classGen.getMethods();
0981: for (int i = 0; i < methods.length; i++) {
0982: Method m = methods[i];
0983:
0984: // native and abstract methods don't have any code
0985: // so continue with next method
0986: if (m.isNative() || m.isAbstract()) {
0987: continue;
0988: }
0989: //we do not want to enhance our enhanced methods
0990: if (m.getName().startsWith("<cl")) {
0991: continue;
0992: }
0993:
0994: if (!mustEnhance(m)) {
0995: continue;
0996: }
0997:
0998: boolean changed = false;
0999:
1000: MethodGen mg = new MethodGen(m, classGen.getClassName(),
1001: constantPoolGen);
1002:
1003: // get the code in form of an InstructionList object
1004: InstructionList il = mg.getInstructionList();
1005:
1006: // get the first instruction
1007: InstructionHandle ih = il.getStart();
1008: while (ih != null) {
1009: Instruction ins = ih.getInstruction();
1010: if (ins.getClass().getName().equals(getField)) {//if (ins instanceof GETFIELD)
1011: GETFIELD is = (GETFIELD) ins;
1012: String key = is.getClassName(constantPoolGen) + "|"
1013: + is.getFieldName(constantPoolGen);
1014: if (getAndSettersMap.containsKey(key)) {
1015: SwapFieldHelper helper = (SwapFieldHelper) getAndSettersMap
1016: .get(key);
1017: // replace it with our static replacement method
1018: ih.setInstruction(instructionFactory
1019: .createInvoke(helper.className,
1020: helper.jdoGetName, helper.type,
1021: new Type[] { new ObjectType(
1022: helper.className) },
1023: Constants.INVOKESTATIC));
1024: il.setPositions();
1025: il.update();
1026:
1027: changed = true;
1028: InstructionHandle prevIhDUP = ih.getPrev();
1029: Instruction iffyDup = prevIhDUP
1030: .getInstruction();
1031: if (iffyDup.getClass().getName().equals(dup)) { // The previos ist was a DUP
1032: ih = ih.getPrev();
1033: InstructionHandle prevIhALOAD = ih
1034: .getPrev();
1035: Instruction iffyAload = prevIhALOAD
1036: .getInstruction();
1037: if (iffyAload.getClass().getName().equals(
1038: aload)) { // The ist before that was a ALOAD
1039: ALOAD aLoad = (ALOAD) iffyAload;
1040: ih.setInstruction(aLoad); // Swap ref out
1041: il.setPositions();
1042: il.update();
1043: } else {
1044: ih = ih.getNext();
1045: }
1046: }
1047: }
1048: } else if (ins.getClass().getName().equals(putField)) {
1049: PUTFIELD is = (PUTFIELD) ins;
1050: String key = is.getClassName(constantPoolGen) + "|"
1051: + is.getFieldName(constantPoolGen);
1052: if (getAndSettersMap.containsKey(key)) {
1053: SwapFieldHelper helper = (SwapFieldHelper) getAndSettersMap
1054: .get(key);
1055: // replace it with our static replacement method
1056: ih
1057: .setInstruction(instructionFactory
1058: .createInvoke(
1059: helper.className,
1060: helper.jdoSetName,
1061: Type.VOID,
1062: new Type[] {
1063: new ObjectType(
1064: helper.className),
1065: helper.type },
1066: Constants.INVOKESTATIC));
1067: il.setPositions();
1068: il.update();
1069: changed = true;
1070: }
1071: }
1072: // next instruction
1073: ih = ih.getNext();
1074: }
1075: if (changed) {
1076: il.setPositions();
1077: il.update();
1078: mg.setMaxLocals();
1079: mg.setMaxStack();
1080: Method method = mg.getMethod();
1081: classGen.replaceMethod(m, method);
1082: }
1083: }
1084: }
1085:
1086: private void setEnhancedFieldsPrivate() {
1087: Field[] fields = classGen.getFields();
1088: Iterator iter = fieldSet.iterator();
1089: while (iter.hasNext()) {
1090: FieldInfo info = (FieldInfo) iter.next();
1091: String fieldname = info.getFieldName();
1092: for (int i = 0; i < fields.length; i++) {
1093: Field f = fields[i];
1094: if (f.getName().equals(fieldname)) {
1095: if (!f.isPrivate()) {
1096: f.isProtected(false);
1097: f.isPublic(false);
1098: f.isPrivate(true);
1099: }
1100: }
1101: }
1102: }
1103: }
1104:
1105: private void addJdoInterface() {
1106: classGen.addInterface(PERSISTENCE_CAPABLE);
1107: }
1108:
1109: private void addJdoCopyKeyFieldsToObjectId2() {
1110: if (classInfo.getTopPCSuperClass() == null
1111: || (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION && classInfo
1112: .getObjectidClass() != null)) {
1113: InstructionList il = new InstructionList();
1114: MethodGen methodGen = new MethodGen(
1115: Constants.ACC_PUBLIC,
1116: Type.VOID,
1117: new Type[] {
1118: new ObjectType(
1119: "javax.jdo.spi.PersistenceCapable$ObjectIdFieldSupplier"),
1120: Type.OBJECT },
1121: new String[] { "fs", "oid" },
1122: "jdoCopyKeyFieldsToObjectId", classGen
1123: .getClassName(), il, constantPoolGen);
1124: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION
1125: && classInfo.getObjectidClass() != null) {
1126: Iterator iter = classInfo.getFieldList().iterator();
1127: int count = 0;
1128: boolean isObject = false;
1129: while (iter.hasNext()) {
1130: FieldInfo info = (FieldInfo) iter.next();
1131: if (info.primaryKey()) {
1132: String fieldProviderMethod = null;
1133: if (typeToFieldProvider.containsKey(info
1134: .getType())) {
1135: fieldProviderMethod = (String) typeToFieldProvider
1136: .get(info.getType());
1137: isObject = false;
1138: } else {
1139: isObject = true;
1140: }
1141: il.append(new ALOAD(2));
1142: il.append(instructionFactory
1143: .createCheckCast(new ObjectType(
1144: classInfo.getObjectidClass())));
1145: il.append(new ALOAD(1));
1146: il.append(instructionFactory.createGetStatic(
1147: classGen.getClassName(),
1148: "jdoInheritedFieldCount", Type.INT));
1149: il.append(new PUSH(constantPoolGen, count));
1150: il.append(new IADD());
1151: if (isObject) {
1152: il
1153: .append(instructionFactory
1154: .createInvoke(
1155: "javax.jdo.spi.PersistenceCapable$ObjectIdFieldSupplier",
1156: "fetchObjectField",
1157: Type.OBJECT,
1158: new Type[] { Type.INT },
1159: Constants.INVOKEINTERFACE));
1160: il
1161: .append(instructionFactory
1162: .createCheckCast((ReferenceType) info
1163: .getType()));
1164: } else {
1165: il
1166: .append(instructionFactory
1167: .createInvoke(
1168: "javax.jdo.spi.PersistenceCapable$ObjectIdFieldSupplier",
1169: fieldProviderMethod,
1170: info.getType(),
1171: new Type[] { Type.INT },
1172: Constants.INVOKEINTERFACE));
1173:
1174: }
1175: il
1176: .append(instructionFactory
1177: .createPutField(classInfo
1178: .getObjectidClass(),
1179: info.getFieldName(),
1180: info.getType()));
1181:
1182: }
1183: count++;
1184: }
1185: }
1186: il.append(new RETURN());
1187:
1188: // makeSynthetic(methodGen);
1189: methodGen.setMaxLocals();
1190: methodGen.setMaxStack();
1191: classGen.addMethod(methodGen.getMethod());
1192: il.dispose();
1193: }
1194: }
1195:
1196: // not cool, maybe ???????? test
1197: private void addJdoCopyKeyFieldsToObjectId1() {
1198: if (classInfo.getTopPCSuperClass() == null
1199: || (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION && classInfo
1200: .getObjectidClass() != null)) {
1201: InstructionList il = new InstructionList();
1202: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1203: Type.VOID, new Type[] { Type.OBJECT },
1204: new String[] { "oid" },
1205: "jdoCopyKeyFieldsToObjectId", classGen
1206: .getClassName(), il, constantPoolGen);
1207: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION
1208: && classInfo.getObjectidClass() != null) {
1209: Iterator iter = classInfo.getFieldList().iterator();
1210: while (iter.hasNext()) {
1211: FieldInfo info = (FieldInfo) iter.next();
1212: if (info.primaryKey()) {
1213: il.append(new ALOAD(1));
1214: il.append(instructionFactory
1215: .createCheckCast(new ObjectType(
1216: classInfo.getObjectidClass())));
1217: il.append(new ALOAD(0));
1218: il
1219: .append(instructionFactory
1220: .createGetField(classInfo
1221: .getClassName(), info
1222: .getFieldName(), info
1223: .getType()));
1224: il
1225: .append(instructionFactory
1226: .createPutField(classInfo
1227: .getObjectidClass(),
1228: info.getFieldName(),
1229: info.getType()));
1230: }
1231: }
1232: }
1233: il.append(new RETURN());
1234: // makeSynthetic(methodGen);
1235: methodGen.setMaxLocals();
1236: methodGen.setMaxStack();
1237: classGen.addMethod(methodGen.getMethod());
1238: il.dispose();
1239: }
1240: }
1241:
1242: private void addJdoNewObjectIdInstance1() {
1243: if (classInfo.getTopPCSuperClass() == null
1244: || (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION && classInfo
1245: .getObjectidClass() != null)) {
1246: InstructionList il = new InstructionList();
1247: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1248: Type.OBJECT, null, null, "jdoNewObjectIdInstance",
1249: classGen.getClassName(), il, constantPoolGen);
1250: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION
1251: && classInfo.getObjectidClass() != null) {
1252: il.append(instructionFactory.createNew(classInfo
1253: .getObjectidClass()));
1254: il.append(new DUP());
1255: il.append(instructionFactory.createInvoke(classInfo
1256: .getObjectidClass(), "<init>", Type.VOID,
1257: new Type[] {}, Constants.INVOKESPECIAL));
1258: } else {
1259: il.append(new ACONST_NULL());
1260: }
1261: il.append(new ARETURN());
1262:
1263: methodGen.setMaxLocals();
1264: methodGen.setMaxStack();
1265: classGen.addMethod(methodGen.getMethod());
1266: il.dispose();
1267: }
1268: }
1269:
1270: private void addJdoNewObjectIdInstance2() {
1271: if (classInfo.getTopPCSuperClass() == null
1272: || (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION && classInfo
1273: .getObjectidClass() != null)) {
1274: InstructionList il = new InstructionList();
1275: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1276: Type.OBJECT, new Type[] { Type.STRING },
1277: new String[] { "str" }, "jdoNewObjectIdInstance",
1278: classGen.getClassName(), il, constantPoolGen);
1279: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION
1280: && classInfo.getObjectidClass() != null) {
1281: il.append(instructionFactory.createNew(classInfo
1282: .getObjectidClass()));
1283: il.append(new DUP());
1284: il.append(new ALOAD(1));
1285: il.append(instructionFactory.createInvoke(classInfo
1286: .getObjectidClass(), "<init>", Type.VOID,
1287: new Type[] { Type.STRING },
1288: Constants.INVOKESPECIAL));
1289: } else {
1290: il.append(new ACONST_NULL());
1291: }
1292: il.append(new ARETURN());
1293:
1294: methodGen.setMaxLocals();
1295: methodGen.setMaxStack();
1296: classGen.addMethod(methodGen.getMethod());
1297: il.dispose();
1298: }
1299: }
1300:
1301: private void addJdoReplaceStateManager() {
1302: if (classInfo.getTopPCSuperClass() == null) {
1303: InstructionList il = new InstructionList();
1304: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC
1305: | Constants.ACC_SYNCHRONIZED, Type.VOID,
1306: new Type[] { SM_OBJECT_TYPE },
1307: new String[] { "sm" }, "jdoReplaceStateManager",
1308: classGen.getClassName(), il, constantPoolGen);
1309:
1310: il.append(new ALOAD(0));
1311: il.append(instructionFactory.createGetField(
1312: getTopPCSuperOrCurrentClassName(),
1313: "jdoStateManager", SM_OBJECT_TYPE));
1314: IFNULL ifnullInst1 = new IFNULL(null);
1315: il.append(ifnullInst1);
1316: il.append(new ALOAD(0));
1317: il.append(new ALOAD(0));
1318: il.append(instructionFactory.createGetField(
1319: getTopPCSuperOrCurrentClassName(),
1320: "jdoStateManager", SM_OBJECT_TYPE));
1321: il.append(new ALOAD(0));
1322: il.append(new ALOAD(1));
1323: il.append(instructionFactory.createInvoke(STATE_MANAGER,
1324: "replacingStateManager", SM_OBJECT_TYPE,
1325: new Type[] { PC_OBJECT_TYPE, SM_OBJECT_TYPE },
1326: Constants.INVOKEINTERFACE));
1327: il.append(instructionFactory.createPutField(
1328: getTopPCSuperOrCurrentClassName(),
1329: "jdoStateManager", SM_OBJECT_TYPE));
1330: GOTO gotoInst = new GOTO(null);
1331: il.append(gotoInst);
1332: InstructionHandle secManHandle = il
1333: .append(instructionFactory
1334: .createInvoke(
1335: "java.lang.System",
1336: "getSecurityManager",
1337: new ObjectType(
1338: "java.lang.SecurityManager"),
1339: new Type[] {},
1340: Constants.INVOKESTATIC));
1341: ifnullInst1.setTarget(secManHandle);
1342: il.append(new ASTORE(2));
1343: InstructionHandle startSecHandle = il.append(new ALOAD(2));
1344: IFNULL ifnullInst2 = new IFNULL(null);
1345: il.append(ifnullInst2);
1346: il.append(new ALOAD(2));
1347: il.append(instructionFactory.createGetStatic(
1348: "javax.jdo.spi.JDOPermission", "SET_STATE_MANAGER",
1349: new ObjectType("javax.jdo.spi.JDOPermission")));
1350: il.append(instructionFactory.createInvoke(
1351: "java.lang.SecurityManager", "checkPermission",
1352: Type.VOID, new Type[] { new ObjectType(
1353: "java.security.Permission") },
1354: Constants.INVOKEVIRTUAL));
1355: InstructionHandle ifnullHandle = il.append(new ALOAD(0));
1356: ifnullInst2.setTarget(ifnullHandle);
1357: il.append(new ALOAD(1));
1358: il.append(instructionFactory.createPutField(
1359: getTopPCSuperOrCurrentClassName(),
1360: "jdoStateManager", SM_OBJECT_TYPE));
1361: InstructionHandle gotoHandle = il.append(new RETURN());
1362: gotoInst.setTarget(gotoHandle);
1363: methodGen.addLocalVariable("sec", new ObjectType(
1364: "java.lang.SecurityManager"), 2, startSecHandle, il
1365: .getEnd());
1366:
1367: methodGen.setMaxLocals();
1368: methodGen.setMaxStack();
1369: classGen.addMethod(methodGen.getMethod());
1370: il.dispose();
1371: }
1372:
1373: }
1374:
1375: private void addJdoGetTransactionalObjectId() {
1376: if (classInfo.getTopPCSuperClass() == null) {
1377: InstructionList il = new InstructionList();
1378: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1379: Type.OBJECT, new Type[] {}, new String[] {},
1380: "jdoGetTransactionalObjectId", classGen
1381: .getClassName(), il, constantPoolGen);
1382: il.append(new ALOAD(0));
1383: il.append(instructionFactory.createGetField(
1384: getTopPCSuperOrCurrentClassName(),
1385: "jdoStateManager", SM_OBJECT_TYPE));
1386: IFNONNULL ifnonnullInst = new IFNONNULL(null);
1387: il.append(ifnonnullInst);
1388: il.append(new ACONST_NULL());
1389: GOTO gotoInst = new GOTO(null);
1390: il.append(gotoInst);
1391: InstructionHandle ifnonnullHandle = il.append(new ALOAD(0));
1392: il.append(instructionFactory.createGetField(
1393: getTopPCSuperOrCurrentClassName(),
1394: "jdoStateManager", SM_OBJECT_TYPE));
1395: il.append(new ALOAD(0));
1396: il.append(instructionFactory.createInvoke(STATE_MANAGER,
1397: "getTransactionalObjectId", Type.OBJECT,
1398: new Type[] { PC_OBJECT_TYPE },
1399: Constants.INVOKEINTERFACE));
1400: InstructionHandle gotoHandle = il.append(new ARETURN());
1401: gotoInst.setTarget(gotoHandle);
1402: ifnonnullInst.setTarget(ifnonnullHandle);
1403:
1404: // makeSynthetic(methodGen);
1405: methodGen.setMaxLocals();
1406: methodGen.setMaxStack();
1407: classGen.addMethod(methodGen.getMethod());
1408: il.dispose();
1409: }
1410: }
1411:
1412: private void addJdoGetObjectId() {
1413: if (classInfo.getTopPCSuperClass() == null) {
1414: InstructionList il = new InstructionList();
1415: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1416: Type.OBJECT, new Type[] {}, new String[] {},
1417: "jdoGetObjectId", classGen.getClassName(), il,
1418: constantPoolGen);
1419:
1420: il.append(new ALOAD(0));
1421: il.append(instructionFactory.createGetField(
1422: getTopPCSuperOrCurrentClassName(),
1423: "jdoStateManager", SM_OBJECT_TYPE));
1424: IFNONNULL ifnonnullInst = new IFNONNULL(null);
1425: il.append(ifnonnullInst);
1426: il.append(new ACONST_NULL());
1427: GOTO gotoInst = new GOTO(null);
1428: il.append(gotoInst);
1429: InstructionHandle ifnonnullHandle = il.append(new ALOAD(0));
1430: il.append(instructionFactory.createGetField(
1431: getTopPCSuperOrCurrentClassName(),
1432: "jdoStateManager", SM_OBJECT_TYPE));
1433: il.append(new ALOAD(0));
1434: il.append(instructionFactory.createInvoke(STATE_MANAGER,
1435: "getObjectId", Type.OBJECT,
1436: new Type[] { PC_OBJECT_TYPE },
1437: Constants.INVOKEINTERFACE));
1438: InstructionHandle gotoHandle = il.append(new ARETURN());
1439: gotoInst.setTarget(gotoHandle);
1440: ifnonnullInst.setTarget(ifnonnullHandle);
1441:
1442: // makeSynthetic(methodGen);
1443: methodGen.setMaxLocals();
1444: methodGen.setMaxStack();
1445: classGen.addMethod(methodGen.getMethod());
1446: il.dispose();
1447: }
1448: }
1449:
1450: private void addJdoNewInstance2() {
1451: InstructionList il = new InstructionList();
1452: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1453: PC_OBJECT_TYPE, new Type[] { SM_OBJECT_TYPE,
1454: Type.OBJECT }, new String[] { "sm", "oid" },
1455: "jdoNewInstance", classGen.getClassName(), il,
1456: constantPoolGen);
1457: if (classGen.isAbstract()) {
1458: il.append(instructionFactory
1459: .createNew("javax.jdo.JDOFatalInternalException"));
1460: il.append(new DUP());
1461: il.append(instructionFactory.createInvoke(
1462: "javax.jdo.JDOFatalInternalException", "<init>",
1463: Type.VOID, new Type[] {}, Constants.INVOKESPECIAL));
1464: il.append(new ATHROW());
1465:
1466: } else {
1467: if (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_DATASTORE) { // datastore
1468: il.append(instructionFactory.createNew(classGen
1469: .getClassName()));
1470: il.append(new DUP());
1471: il.append(instructionFactory.createInvoke(classGen
1472: .getClassName(), "<init>", Type.VOID,
1473: new Type[] {}, Constants.INVOKESPECIAL));
1474: il.append(new ASTORE(3));
1475: InstructionHandle pcStartHandle = il
1476: .append(new ALOAD(3));
1477: il.append(new ALOAD(1));
1478: il.append(instructionFactory.createPutField(
1479: getTopPCSuperOrCurrentClassName(),
1480: "jdoStateManager", SM_OBJECT_TYPE));
1481: il.append(new ALOAD(3));
1482: il.append(new ICONST(1));
1483: il.append(instructionFactory.createPutField(
1484: getTopPCSuperOrCurrentClassName(), "jdoFlags",
1485: Type.BYTE));
1486: il.append(new ALOAD(3));
1487: InstructionHandle returnHandle = il
1488: .append(new ARETURN());
1489: methodGen.addLocalVariable("pc", new ObjectType(
1490: classGen.getClassName()), 3, pcStartHandle,
1491: returnHandle);
1492: } else {// this class has application Identity
1493: il.append(instructionFactory.createNew(classGen
1494: .getClassName()));
1495: il.append(new DUP());
1496: il.append(instructionFactory.createInvoke(classGen
1497: .getClassName(), "<init>", Type.VOID,
1498: new Type[] {}, Constants.INVOKESPECIAL));
1499: il.append(new ASTORE(3));
1500: InstructionHandle pcStartHandle = il
1501: .append(new ALOAD(3));
1502: il.append(new ALOAD(1));
1503: il.append(instructionFactory.createPutField(
1504: getTopPCSuperOrCurrentClassName(),
1505: "jdoStateManager", SM_OBJECT_TYPE));
1506: il.append(new ALOAD(3));
1507: il.append(new ICONST(1));
1508: il.append(instructionFactory.createPutField(
1509: getTopPCSuperOrCurrentClassName(), "jdoFlags",
1510: Type.BYTE));
1511: il.append(new ALOAD(0));
1512: il.append(new ALOAD(2));
1513: il.append(instructionFactory.createInvoke(
1514: getTopPCSuperOrCurrentClass().getClassName(),
1515: "jdoCopyKeyFieldsFromObjectId", Type.VOID,
1516: new Type[] { Type.OBJECT },
1517: Constants.INVOKEVIRTUAL));
1518:
1519: il.append(new ALOAD(3));
1520: il.append(new ARETURN());
1521: methodGen.addLocalVariable("pc", new ObjectType(
1522: classGen.getClassName()), 3, pcStartHandle, il
1523: .getEnd());
1524: }
1525: }
1526:
1527: // makeSynthetic(methodGen);
1528: methodGen.setMaxLocals();
1529: methodGen.setMaxStack();
1530: classGen.addMethod(methodGen.getMethod());
1531: il.dispose();
1532: }
1533:
1534: private void addJdoNewInstance1() {
1535: InstructionList il = new InstructionList();
1536: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1537: PC_OBJECT_TYPE, new Type[] { SM_OBJECT_TYPE },
1538: new String[] { "sm" }, "jdoNewInstance", classGen
1539: .getClassName(), il, constantPoolGen);
1540: if (classGen.isAbstract()) {
1541: il.append(instructionFactory
1542: .createNew("javax.jdo.JDOFatalInternalException"));
1543: il.append(new DUP());
1544: il.append(instructionFactory.createInvoke(
1545: "javax.jdo.JDOFatalInternalException", "<init>",
1546: Type.VOID, new Type[] {}, Constants.INVOKESPECIAL));
1547: il.append(new ATHROW());
1548: } else {
1549: il.append(instructionFactory.createNew(classGen
1550: .getClassName()));
1551: il.append(new DUP());
1552: il.append(instructionFactory.createInvoke(classGen
1553: .getClassName(), "<init>", Type.VOID,
1554: new Type[] {}, Constants.INVOKESPECIAL));
1555: il.append(new ASTORE(2));
1556: InstructionHandle pcStartHandle = il.append(new ALOAD(2));
1557: il.append(new ALOAD(1));
1558: il.append(instructionFactory.createPutField(
1559: getTopPCSuperOrCurrentClassName(),
1560: "jdoStateManager", SM_OBJECT_TYPE));
1561: il.append(new ALOAD(2));
1562: il.append(new ICONST(1));
1563: il.append(instructionFactory.createPutField(
1564: getTopPCSuperOrCurrentClassName(), "jdoFlags",
1565: Type.BYTE));
1566: il.append(new ALOAD(2));
1567: InstructionHandle returnHandle = il.append(new ARETURN());
1568: methodGen.addLocalVariable("pc", new ObjectType(classGen
1569: .getClassName()), 2, pcStartHandle, returnHandle);
1570: }
1571:
1572: // makeSynthetic(methodGen);
1573: methodGen.setMaxLocals();
1574: methodGen.setMaxStack();
1575: classGen.addMethod(methodGen.getMethod());
1576: il.dispose();
1577: }
1578:
1579: private void addRegisterClass() {
1580: Method m = getStaticConstructor();
1581: MethodGen methodGen = new MethodGen(m, classGen.getClassName(),
1582: constantPoolGen);
1583: InstructionList il = methodGen.getInstructionList();
1584: InstructionHandle returnHandle = il.getEnd();//The last instruction of <clinit> will always be the return
1585:
1586: String className = getSetClass$Field(classGen.getClassName());
1587: InstructionHandle nopTarget = il.append(new NOP());
1588: il.append(instructionFactory.createGetStatic(classGen
1589: .getClassName(), className, new ObjectType(
1590: "java.lang.Class")));
1591: IFNONNULL ifnonnull = new IFNONNULL(null);
1592: il.append(ifnonnull);
1593: il.append(new PUSH(constantPoolGen, classGen.getClassName()));
1594: il.append(instructionFactory.createInvoke(classGen
1595: .getClassName(), "class$", new ObjectType(
1596: "java.lang.Class"), new Type[] { Type.STRING },
1597: Constants.INVOKESTATIC));
1598: il.append(new DUP());
1599: il.append(instructionFactory.createPutStatic(classGen
1600: .getClassName(), className, new ObjectType(
1601: "java.lang.Class")));
1602: GOTO gotoIns = new GOTO(null);
1603: il.append(gotoIns);
1604: InstructionHandle ifnonnullHandle = il
1605: .append(instructionFactory.createGetStatic(classGen
1606: .getClassName(), className, new ObjectType(
1607: "java.lang.Class")));
1608: ifnonnull.setTarget(ifnonnullHandle);
1609: InstructionHandle gotoHandle = il.append(instructionFactory
1610: .createGetStatic(classGen.getClassName(),
1611: "jdoFieldNames", new ArrayType(
1612: "java.lang.String", 1)));
1613: gotoIns.setTarget(gotoHandle);
1614: il.append(instructionFactory.createGetStatic(classGen
1615: .getClassName(), "jdoFieldTypes", new ArrayType(
1616: "java.lang.Class", 1)));
1617: il.append(instructionFactory.createGetStatic(classGen
1618: .getClassName(), "jdoFieldFlags", new ArrayType(
1619: Type.BYTE, 1)));
1620: il.append(instructionFactory.createGetStatic(classGen
1621: .getClassName(), "jdoPersistenceCapableSuperclass",
1622: new ObjectType("java.lang.Class")));
1623: if (classGen.isAbstract()) {
1624: il.append(new ACONST_NULL());
1625: } else {
1626: il.append(instructionFactory.createNew(classGen
1627: .getClassName()));
1628: il.append(new DUP());
1629: il.append(instructionFactory.createInvoke(classGen
1630: .getClassName(), "<init>", Type.VOID,
1631: new Type[] {}, Constants.INVOKESPECIAL));
1632: }
1633: il.append(instructionFactory.createInvoke(
1634: "javax.jdo.spi.JDOImplHelper", "registerClass",
1635: Type.VOID, new Type[] {
1636: new ObjectType("java.lang.Class"),
1637: new ArrayType(Type.STRING, 1),
1638: new ArrayType("java.lang.Class", 1),
1639: new ArrayType(Type.BYTE, 1),
1640: new ObjectType("java.lang.Class"),
1641: PC_OBJECT_TYPE }, Constants.INVOKESTATIC));
1642: il.append(new RETURN());
1643: try {
1644: il.delete(returnHandle);
1645: } catch (TargetLostException e) {
1646: InstructionHandle[] targets = e.getTargets();
1647: for (int i = 0; i < targets.length; i++) {
1648: InstructionTargeter[] targeters = targets[i]
1649: .getTargeters();
1650: for (int j = 0; j < targeters.length; j++) {
1651: targeters[j].updateTarget(targets[i], nopTarget);
1652: }
1653: }
1654: }
1655: methodGen.removeNOPs();
1656: methodGen.setMaxLocals();
1657: methodGen.setMaxStack();
1658: classGen.replaceMethod(m, methodGen.getMethod());
1659: il.dispose();
1660: }
1661:
1662: private boolean writeObjectExist() {
1663: Method[] methods = classGen.getMethods();
1664: for (int i = 0; i < methods.length; i++) {
1665: Method m = methods[i];
1666: if (m.getName().equals("writeObject")
1667: && m.getSignature().equals(
1668: "(Ljava/io/ObjectOutputStream;)V")) {
1669: return true;
1670: }
1671: }
1672: return false;
1673:
1674: }
1675:
1676: private Method getWriteObject() {
1677: Method[] methods = classGen.getMethods();
1678: for (int i = 0; i < methods.length; i++) {
1679: Method m = methods[i];
1680: if (m.getName().equals("writeObject")
1681: && m.getSignature().equals(
1682: "(Ljava/io/ObjectOutputStream;)V")) {
1683: return m;
1684: }
1685: }
1686: return null;
1687:
1688: }
1689:
1690: private boolean readObjectExist() {
1691: Method[] methods = classGen.getMethods();
1692: for (int i = 0; i < methods.length; i++) {
1693: Method m = methods[i];
1694: if (m.getName().equals("readObject")
1695: && m.getSignature().equals(
1696: "(Ljava/io/ObjectInputStream;)V")) {
1697: return true;
1698: }
1699: }
1700: return false;
1701:
1702: }
1703:
1704: private Method getReadObject() {
1705: Method[] methods = classGen.getMethods();
1706: for (int i = 0; i < methods.length; i++) {
1707: Method m = methods[i];
1708: if (m.getName().equals("readObject")
1709: && m.getSignature().equals(
1710: "(Ljava/io/ObjectInputStream;)V")) {
1711: return m;
1712: }
1713: }
1714: return null;
1715:
1716: }
1717:
1718: private void addWriteObject() {
1719: boolean rename = false;
1720: if (writeObjectExist()
1721: && classInfo.getTopPCSuperClass() == null) {
1722: // we must rename this method
1723: Method m = getWriteObject();
1724: MethodGen mg = new MethodGen(m, classGen.getClassName(),
1725: constantPoolGen);
1726: mg.setName("versantWriteObject");
1727: classGen.replaceMethod(m, mg.getMethod());
1728: rename = true;
1729: } else if (writeObjectExist()
1730: && classInfo.getTopPCSuperClass() != null) {
1731: return;
1732: }
1733: InstructionList il = new InstructionList();
1734: MethodGen methodGen = new MethodGen(Constants.ACC_PRIVATE,
1735: Type.VOID, new Type[] { new ObjectType(
1736: "java.io.ObjectOutputStream") },
1737: new String[] { "out" }, "writeObject", classGen
1738: .getClassName(), il, constantPoolGen);
1739: if (classInfo.getTopPCSuperClass() == null) {
1740: il.append(new ALOAD(0));
1741: il.append(instructionFactory.createInvoke(
1742: getTopPCSuperOrCurrentClass().getClassName(),
1743: "jdoPreSerialize", Type.VOID, new Type[] {},
1744: Constants.INVOKESPECIAL));
1745: }
1746: if (rename) {
1747: il.append(new ALOAD(0));
1748: il.append(new ALOAD(1));
1749: il.append(instructionFactory.createInvoke(classGen
1750: .getClassName(), "versantWriteObject", Type.VOID,
1751: new Type[] { new ObjectType(
1752: "java.io.ObjectOutputStream") },
1753: Constants.INVOKESPECIAL));
1754: } else {
1755: il.append(new ALOAD(1));
1756: il.append(instructionFactory.createInvoke(
1757: "java.io.ObjectOutputStream", "defaultWriteObject",
1758: Type.VOID, new Type[] {}, Constants.INVOKEVIRTUAL));
1759: }
1760:
1761: if (classInfo.getTopPCSuperClass() == null && detach) {
1762: il.append(new ALOAD(0));
1763: il.append(instructionFactory.createGetField(classGen
1764: .getClassName(), "jdoStateManager", new ObjectType(
1765: STATE_MANAGER)));
1766: il.append(new INSTANCEOF(constantPoolGen
1767: .addClass(DETACHED_STATE_MANAGER)));
1768: IFEQ ifeq = new IFEQ(null);
1769: il.append(ifeq);
1770: il.append(new ALOAD(1));
1771: il.append(new ICONST(1));
1772: il.append(instructionFactory.createInvoke(
1773: "java.io.ObjectOutputStream", "writeBoolean",
1774: Type.VOID, new Type[] { Type.BOOLEAN },
1775: Constants.INVOKEVIRTUAL));
1776: il.append(new ALOAD(1));
1777: il.append(new ALOAD(0));
1778: il.append(instructionFactory.createGetField(classGen
1779: .getClassName(), "jdoStateManager", new ObjectType(
1780: STATE_MANAGER)));
1781: il.append(instructionFactory.createInvoke(
1782: "java.io.ObjectOutputStream", "writeObject",
1783: Type.VOID, new Type[] { Type.OBJECT },
1784: Constants.INVOKEVIRTUAL));
1785: il.append(new ALOAD(1));
1786: il.append(new ALOAD(0));
1787: il.append(instructionFactory.createGetField(classGen
1788: .getClassName(), "jdoFlags", Type.BYTE));
1789: il.append(instructionFactory.createInvoke(
1790: "java.io.ObjectOutputStream", "writeByte",
1791: Type.VOID, new Type[] { Type.INT },
1792: Constants.INVOKEVIRTUAL));
1793: GOTO aGoto = new GOTO(null);
1794: il.append(aGoto);
1795: InstructionHandle aload1Handle = il.append(new ALOAD(1));
1796: ifeq.setTarget(aload1Handle);
1797: il.append(new ICONST(0));
1798: il.append(instructionFactory.createInvoke(
1799: "java.io.ObjectOutputStream", "writeBoolean",
1800: Type.VOID, new Type[] { Type.BOOLEAN },
1801: Constants.INVOKEVIRTUAL));
1802: InstructionHandle returnHandle = il.append(new RETURN());
1803: aGoto.setTarget(returnHandle);
1804: } else {
1805: il.append(new RETURN());
1806: }
1807:
1808: methodGen.addException("java.io.IOException");
1809: methodGen.setMaxLocals();
1810: methodGen.setMaxStack();
1811: classGen.addMethod(methodGen.getMethod());
1812: il.dispose();
1813:
1814: }
1815:
1816: private void addReadObject() {
1817: if (classInfo.getTopPCSuperClass() == null && detach) {
1818: boolean rename = false;
1819: if (readObjectExist()) {
1820: // we must rename this method
1821: Method m = getReadObject();
1822: MethodGen mg = new MethodGen(m,
1823: classGen.getClassName(), constantPoolGen);
1824: mg.setName("versantReadObject");
1825: classGen.replaceMethod(m, mg.getMethod());
1826: rename = true;
1827: }
1828:
1829: InstructionList il = new InstructionList();
1830: MethodGen methodGen = new MethodGen(Constants.ACC_PRIVATE,
1831: Type.VOID, new Type[] { new ObjectType(
1832: "java.io.ObjectInputStream") },
1833: new String[] { "in" }, "readObject", classGen
1834: .getClassName(), il, constantPoolGen);
1835:
1836: if (rename) {
1837: il.append(new ALOAD(0));
1838: il.append(new ALOAD(1));
1839: il.append(instructionFactory.createInvoke(classGen
1840: .getClassName(), "versantReadObject",
1841: Type.VOID, new Type[] { new ObjectType(
1842: "java.io.ObjectInputStream") },
1843: Constants.INVOKESPECIAL));
1844:
1845: } else {
1846: il.append(new ALOAD(1));
1847: il.append(instructionFactory.createInvoke(
1848: "java.io.ObjectInputStream",
1849: "defaultReadObject", Type.VOID, new Type[] {},
1850: Constants.INVOKEVIRTUAL));
1851: }
1852: il.append(new ALOAD(1));
1853: il.append(instructionFactory.createInvoke(
1854: "java.io.ObjectInputStream", "readBoolean",
1855: Type.BOOLEAN, new Type[] {},
1856: Constants.INVOKEVIRTUAL));
1857: IFEQ ifeq = new IFEQ(null);
1858: il.append(ifeq);//22
1859: il.append(new ALOAD(0));
1860: il.append(new ALOAD(1));
1861: il.append(instructionFactory
1862: .createInvoke("java.io.ObjectInputStream",
1863: "readObject", Type.OBJECT, new Type[] {},
1864: Constants.INVOKEVIRTUAL));
1865: il.append(instructionFactory
1866: .createCheckCast(new ObjectType(
1867: DETACHED_STATE_MANAGER)));
1868: il.append(instructionFactory.createPutField(classGen
1869: .getClassName(), "jdoStateManager", new ObjectType(
1870: STATE_MANAGER)));
1871: il.append(new ALOAD(0));
1872: il.append(new ALOAD(1));
1873: il.append(instructionFactory.createInvoke(
1874: "java.io.ObjectInputStream", "readByte", Type.BYTE,
1875: new Type[] {}, Constants.INVOKEVIRTUAL));
1876: il.append(instructionFactory.createPutField(classGen
1877: .getClassName(), "jdoFlags", Type.BYTE));
1878:
1879: InstructionHandle returnHandle = il.append(new RETURN());
1880: ifeq.setTarget(returnHandle);
1881:
1882: methodGen.addException("java.io.IOException");
1883: methodGen.addException("java.lang.ClassNotFoundException");
1884: methodGen.setMaxLocals();
1885: methodGen.setMaxStack();
1886: classGen.addMethod(methodGen.getMethod());
1887: il.dispose();
1888: }
1889: }
1890:
1891: private void addJdoPreSerialize() {
1892: if (classInfo.getTopPCSuperClass() == null) {
1893: InstructionList il = new InstructionList();
1894: MethodGen methodGen = new MethodGen(Constants.ACC_PRIVATE,
1895: Type.VOID, new Type[] {}, new String[] {},
1896: "jdoPreSerialize", classGen.getClassName(), il,
1897: constantPoolGen);
1898:
1899: InstructionHandle returnHandle = il.insert(new RETURN());
1900: il.insert(instructionFactory.createInvoke(STATE_MANAGER,
1901: "preSerialize", Type.VOID,
1902: new Type[] { PC_OBJECT_TYPE },
1903: Constants.INVOKEINTERFACE));
1904: il.insert(new ALOAD(0));
1905: il.insert(instructionFactory.createGetField(
1906: getTopPCSuperOrCurrentClassName(),
1907: "jdoStateManager", SM_OBJECT_TYPE));
1908: il.insert(new ALOAD(0));
1909: il.insert(new IFNULL(returnHandle));
1910: il.insert(instructionFactory.createGetField(
1911: getTopPCSuperOrCurrentClassName(),
1912: "jdoStateManager", SM_OBJECT_TYPE));
1913: il.insert(new ALOAD(0));
1914:
1915: // makeSynthetic(methodGen);
1916: methodGen.setMaxLocals();
1917: methodGen.setMaxStack();
1918: classGen.addMethod(methodGen.getMethod());
1919: il.dispose();
1920: }
1921: }
1922:
1923: private void addJdoCopyFields() {
1924: InstructionList il = new InstructionList();
1925: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
1926: Type.VOID, new Type[] { Type.OBJECT,
1927: new ArrayType(Type.INT, 1) }, new String[] {
1928: "pc", "fieldNumbers" }, "jdoCopyFields",
1929: classGen.getClassName(), il, constantPoolGen);
1930:
1931: il.append(new ALOAD(1));
1932: il.append(instructionFactory.createCheckCast(new ObjectType(
1933: classGen.getClassName())));
1934: il.append(new ASTORE(3));
1935: InstructionHandle otherStartHandle = il.append(new ALOAD(3));
1936: il.append(instructionFactory.createGetField(
1937: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
1938: SM_OBJECT_TYPE));
1939: il.append(new ALOAD(0));
1940: il.append(instructionFactory.createGetField(
1941: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
1942: SM_OBJECT_TYPE));
1943: IF_ACMPEQ if_acmpeq = new IF_ACMPEQ(null);
1944: il.append(if_acmpeq);
1945: il.append(instructionFactory
1946: .createNew("java.lang.IllegalArgumentException"));
1947: il.append(new DUP());
1948: il.append(new PUSH(constantPoolGen,
1949: "this.jdoStateManager != other.jdoStateManager"));
1950: il.append(instructionFactory.createInvoke(
1951: "java.lang.IllegalArgumentException", "<init>",
1952: Type.VOID, new Type[] { Type.STRING },
1953: Constants.INVOKESPECIAL));
1954: il.append(new ATHROW());
1955: InstructionHandle if_acmpeqHandle = il.append(new ALOAD(0));
1956: if_acmpeq.setTarget(if_acmpeqHandle);
1957: il.append(instructionFactory.createGetField(
1958: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
1959: SM_OBJECT_TYPE));
1960: IFNONNULL ifnonnull = new IFNONNULL(null);
1961: il.append(ifnonnull);
1962: il.append(instructionFactory
1963: .createNew("java.lang.IllegalArgumentException"));
1964: il.append(new DUP());
1965: il.append(new PUSH(constantPoolGen,
1966: "this.jdoStateManager == null"));
1967: il.append(instructionFactory.createInvoke(
1968: "java.lang.IllegalArgumentException", "<init>",
1969: Type.VOID, new Type[] { Type.STRING },
1970: Constants.INVOKESPECIAL));
1971: il.append(new ATHROW());
1972: InstructionHandle ifnonnullHandle = il.append(new ICONST(0));
1973: ifnonnull.setTarget(ifnonnullHandle);
1974: il.append(new ISTORE(4));
1975: GOTO aGoto = new GOTO(null);
1976: InstructionHandle iStartHandle = il.append(aGoto);
1977: InstructionHandle if_icmpltHandle = il.append(new ALOAD(0));
1978: il.append(new ALOAD(3));
1979: il.append(new ALOAD(2));
1980: il.append(new ILOAD(4));
1981: il.append(new IALOAD());
1982: il.append(instructionFactory.createInvoke(classGen
1983: .getClassName(), "jdoCopyField", Type.VOID, new Type[] {
1984: new ObjectType(classGen.getClassName()), Type.INT },
1985: Constants.INVOKEVIRTUAL));
1986: il.append(new IINC(4, 1));
1987: InstructionHandle aGotoHandle = il.append(new ILOAD(4));
1988: aGoto.setTarget(aGotoHandle);
1989: il.append(new ALOAD(2));
1990: il.append(new ARRAYLENGTH());
1991: il.append(new IF_ICMPLT(if_icmpltHandle));
1992: il.append(new RETURN());
1993:
1994: methodGen.addLocalVariable("other", new ObjectType(classGen
1995: .getClassName()), 3, otherStartHandle, il.getEnd());
1996: methodGen.addLocalVariable("i", Type.INT, 4, iStartHandle, il
1997: .getEnd());
1998: // makeSynthetic(methodGen);
1999: methodGen.setMaxLocals();
2000: methodGen.setMaxStack();
2001: classGen.addMethod(methodGen.getMethod());
2002: il.dispose();
2003: }
2004:
2005: private void addJdoCopyField() {
2006: InstructionList il = new InstructionList();
2007: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
2008: Type.VOID, new Type[] {
2009: new ObjectType(classGen.getClassName()),
2010: Type.INT }, new String[] { "other",
2011: "fieldNumber" }, "jdoCopyField", classGen
2012: .getClassName(), il, constantPoolGen);
2013:
2014: il.append(new ILOAD(2));
2015: il.append(instructionFactory.createGetStatic(classGen
2016: .getClassName(), "jdoInheritedFieldCount", Type.INT));
2017: il.append(new ISUB());
2018: il.append(new ISTORE(3));
2019: InstructionHandle relativeFieldStartHandle = il
2020: .append(new ILOAD(3));
2021:
2022: int switchCount = fieldSet.size();
2023: int[] match = new int[switchCount];
2024: InstructionHandle[] targets = new InstructionHandle[switchCount];
2025: ArrayList tempInsLists = new ArrayList(switchCount + 1);
2026: int i = 0;
2027: ArrayList tempList = new ArrayList(fieldSet);
2028: for (Iterator fieldIter = tempList.iterator(); fieldIter
2029: .hasNext(); i++) {
2030: FieldInfo fieldInfo = (FieldInfo) fieldIter.next();
2031: InstructionList tempIL = new InstructionList();
2032: match[i] = fieldInfo.getFieldNo();
2033: targets[i] = tempIL.append(new ALOAD(0));
2034: tempIL.append(new ALOAD(1));
2035: tempIL.append(instructionFactory.createGetField(classGen
2036: .getClassName(), fieldInfo.getFieldName(),
2037: fieldInfo.getType()));
2038: tempIL.append(instructionFactory.createPutField(classGen
2039: .getClassName(), fieldInfo.getFieldName(),
2040: fieldInfo.getType()));
2041: tempIL.append(new RETURN());
2042: tempInsLists.add(tempIL);
2043: }
2044: // Do default
2045: InstructionList tempIL = new InstructionList();
2046: InstructionHandle defaultHandle = null;
2047: if (classInfo.getTopPCSuperClass() == null) {
2048: defaultHandle = tempIL.append(instructionFactory
2049: .createNew("java.lang.IllegalArgumentException"));
2050: tempIL.append(new DUP());
2051: tempIL.append(new PUSH(constantPoolGen, "fieldNumber"));
2052: tempIL.append(instructionFactory.createInvoke(
2053: "java.lang.IllegalArgumentException", "<init>",
2054: Type.VOID, new Type[] { Type.STRING },
2055: Constants.INVOKESPECIAL));
2056: tempIL.append(new ATHROW());
2057: } else {
2058: defaultHandle = tempIL.append(new ALOAD(0));
2059: tempIL.append(new ALOAD(1));
2060: tempIL.append(new ILOAD(2));
2061: tempIL.append(instructionFactory.createInvoke(classInfo
2062: .getTopPCSuperClass().getClassName(),
2063: "jdoCopyField", Type.VOID, new Type[] {
2064: new ObjectType(classInfo
2065: .getTopPCSuperClass()
2066: .getClassName()), Type.INT },
2067: Constants.INVOKESPECIAL));
2068: }
2069: tempInsLists.add(tempIL);
2070: // start the lookupSwitch
2071: il.append(new LOOKUPSWITCH(match, targets, defaultHandle));
2072: for (Iterator tempIlIter = tempInsLists.iterator(); tempIlIter
2073: .hasNext();) { // add all instructions
2074: InstructionList list = (InstructionList) tempIlIter.next();
2075: il.append(list);
2076: }
2077: il.append(new RETURN());
2078:
2079: methodGen.addLocalVariable("relativeField", Type.INT, 3,
2080: relativeFieldStartHandle, il.getEnd());
2081:
2082: // makeSynthetic(methodGen);
2083: methodGen.setMaxLocals();
2084: methodGen.setMaxStack();
2085: classGen.addMethod(methodGen.getMethod());
2086: il.dispose();
2087: }
2088:
2089: private void addJdoProvideFields() {
2090:
2091: InstructionList il = new InstructionList();
2092: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
2093: Type.VOID, new Type[] { new ArrayType(Type.INT, 1) },
2094: new String[] { "fieldNumbers" }, "jdoProvideFields",
2095: classGen.getClassName(), il, constantPoolGen);
2096: il.append(new ICONST(0));
2097: il.append(new ISTORE(2));
2098: InstructionHandle iloadHandle = il.append(new ILOAD(2));
2099: il.append(new ALOAD(1));
2100: il.append(new ARRAYLENGTH());
2101: IF_ICMPGE if_icmpge = new IF_ICMPGE(null);
2102: il.append(if_icmpge);
2103: il.append(new ALOAD(1));
2104: il.append(new ILOAD(2));
2105: il.append(new IALOAD());
2106: il.append(new ISTORE(3));
2107: InstructionHandle aloadHandle = il.append(new ALOAD(0));
2108: il.append(new ILOAD(3));
2109: il.append(instructionFactory.createInvoke(classGen
2110: .getClassName(), "jdoProvideField", Type.VOID,
2111: new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
2112: InstructionHandle iincHandle = il.append(new IINC(2, 1));
2113: il.append(new GOTO(iloadHandle));
2114: InstructionHandle returnHandle = il.append(new RETURN());
2115: if_icmpge.setTarget(returnHandle);
2116: methodGen.addLocalVariable("i", Type.INT, 2, iloadHandle,
2117: returnHandle);
2118: methodGen.addLocalVariable("fieldNumber", Type.INT, 3,
2119: aloadHandle, iincHandle);
2120: // makeSynthetic(methodGen);
2121: methodGen.setMaxLocals();
2122: methodGen.setMaxStack();
2123: classGen.addMethod(methodGen.getMethod());
2124: il.dispose();
2125: }
2126:
2127: private void addJdoProvideField() {
2128:
2129: ArrayList myList = new ArrayList(fieldSet);
2130: ListIterator fieldIter = myList.listIterator();
2131:
2132: while (fieldIter.hasNext()) {
2133: fieldIter.next();
2134: }
2135:
2136: InstructionList il = new InstructionList();
2137:
2138: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
2139: Type.VOID, new Type[] { Type.INT },
2140: new String[] { "fieldNumber" }, "jdoProvideField",
2141: classGen.getClassName(), il, constantPoolGen);
2142:
2143: if (!isEmpty) {
2144: int size = fieldSet.size();
2145: int[] match = new int[size];
2146: int fieldNum = size;
2147: InstructionHandle[] targets = new InstructionHandle[size];
2148: InstructionHandle defaultHandle = null;
2149: InstructionHandle returnHandel = null;
2150: Set switchList = new TreeSet();
2151: if (classInfo.getPersistenceCapableSuperclass() == null) {
2152: defaultHandle = il
2153: .append(instructionFactory
2154: .createNew("java.lang.IllegalArgumentException"));
2155: il.append(new DUP());
2156:
2157: il.append(instructionFactory
2158: .createNew("java.lang.StringBuffer"));
2159: il.append(new DUP());
2160: il.append(instructionFactory.createInvoke(
2161: "java.lang.StringBuffer", "<init>", Type.VOID,
2162: new Type[] {}, Constants.INVOKESPECIAL));
2163: il.append(new PUSH(constantPoolGen, "Class "
2164: + classGen.getClassName()
2165: + " called with invalid fieldNumber = "));
2166: il.append(instructionFactory.createInvoke(
2167: "java.lang.StringBuffer", "append",
2168: Type.STRINGBUFFER, new Type[] { Type.STRING },
2169: Constants.INVOKEVIRTUAL));
2170: il.append(new ILOAD(1));
2171: il.append(instructionFactory.createInvoke(
2172: "java.lang.StringBuffer", "append",
2173: Type.STRINGBUFFER, new Type[] { Type.INT },
2174: Constants.INVOKEVIRTUAL));
2175: il.append(instructionFactory.createInvoke(
2176: "java.lang.StringBuffer", "toString",
2177: Type.STRING, new Type[] {},
2178: Constants.INVOKEVIRTUAL));
2179:
2180: il.append(instructionFactory.createInvoke(
2181: "java.lang.IllegalArgumentException", "<init>",
2182: Type.VOID, new Type[] { Type.STRING },
2183: Constants.INVOKESPECIAL));
2184: il.append(new ATHROW());
2185: returnHandel = il.append(new RETURN());
2186: } else {
2187: returnHandel = il.insert(new RETURN());
2188: il.insert(new ATHROW());
2189: il.insert(instructionFactory.createInvoke(
2190: "java.lang.IllegalArgumentException", "<init>",
2191: Type.VOID, new Type[] { Type.STRING },
2192: Constants.INVOKESPECIAL));
2193: // il.insert(new PUSH(constantPoolGen,"fieldNumber"));
2194:
2195: il.insert(instructionFactory.createInvoke(
2196: "java.lang.StringBuffer", "toString",
2197: Type.STRING, new Type[] {},
2198: Constants.INVOKEVIRTUAL));
2199: il.insert(instructionFactory.createInvoke(
2200: "java.lang.StringBuffer", "append",
2201: Type.STRINGBUFFER, new Type[] { Type.INT },
2202: Constants.INVOKEVIRTUAL));
2203: il.insert(new ILOAD(1));
2204: il.insert(instructionFactory.createInvoke(
2205: "java.lang.StringBuffer", "append",
2206: Type.STRINGBUFFER, new Type[] { Type.STRING },
2207: Constants.INVOKEVIRTUAL));
2208: il.insert(new PUSH(constantPoolGen, "Class "
2209: + classGen.getClassName()
2210: + " called with invalid fieldNumber = "));
2211: il.insert(instructionFactory.createInvoke(
2212: "java.lang.StringBuffer", "<init>", Type.VOID,
2213: new Type[] {}, Constants.INVOKESPECIAL));
2214: il.insert(new DUP());
2215: il.insert(instructionFactory
2216: .createNew("java.lang.StringBuffer"));
2217:
2218: il.insert(new DUP());
2219: InstructionHandle newHandel = il
2220: .insert(instructionFactory
2221: .createNew("java.lang.IllegalArgumentException"));
2222: il.insert(new GOTO(returnHandel));
2223: il.insert(instructionFactory.createInvoke(classInfo
2224: .getPersistenceCapableSuperclass(),
2225: "jdoProvideField", Type.VOID,
2226: new Type[] { Type.INT },
2227: Constants.INVOKESPECIAL));
2228: il.insert(new ILOAD(1));
2229: il.insert(new ALOAD(0));
2230: il.insert(new IFGE(newHandel));
2231: defaultHandle = il.insert(new ILOAD(2));
2232: }
2233:
2234: while (fieldIter.hasPrevious()) {
2235: FieldInfo fieldInfo = (FieldInfo) fieldIter.previous();
2236: fieldNum--;
2237: Type fieldType = fieldInfo.getType();
2238: String stateManagerProvidedField = null;
2239: boolean isObject = false;
2240: if (typeToProvidedField
2241: .containsKey(fieldInfo.getType())) {
2242: stateManagerProvidedField = (String) typeToProvidedField
2243: .get(fieldInfo.getType());
2244: isObject = false;
2245: } else {
2246: isObject = true;
2247: }
2248:
2249: il.insert(new GOTO(returnHandel));
2250:
2251: if (isObject) {
2252: il.insert(instructionFactory.createInvoke(
2253: STATE_MANAGER, "providedObjectField",
2254: Type.VOID, new Type[] { PC_OBJECT_TYPE,
2255: Type.INT, Type.OBJECT },
2256: Constants.INVOKEINTERFACE));
2257: } else {
2258: il.insert(instructionFactory.createInvoke(
2259: STATE_MANAGER, stateManagerProvidedField,
2260: Type.VOID, new Type[] { PC_OBJECT_TYPE,
2261: Type.INT, fieldType },
2262: Constants.INVOKEINTERFACE));
2263: }
2264: il.insert(instructionFactory.createGetField(classGen
2265: .getClassName(), fieldInfo.getFieldName(),
2266: fieldType));
2267:
2268: il.insert(new ALOAD(0));
2269: il.insert(new ILOAD(1));
2270: il.insert(new ALOAD(0));
2271: il.insert(instructionFactory.createGetField(
2272: getTopPCSuperOrCurrentClassName(),
2273: "jdoStateManager", SM_OBJECT_TYPE));
2274: InstructionHandle switchHandel = il
2275: .insert(new ALOAD(0));
2276: TableSwitchHelper tsh = new TableSwitchHelper();
2277: tsh.match = fieldNum;
2278: tsh.target = switchHandel;
2279: switchList.add(tsh);
2280:
2281: }
2282: Iterator sIter = switchList.iterator();
2283: int count = 0;
2284: while (sIter.hasNext()) {
2285: TableSwitchHelper tsh = (TableSwitchHelper) sIter
2286: .next();
2287: match[count] = tsh.match;
2288: targets[count] = tsh.target;
2289: count++;
2290: }
2291:
2292: il.insert(new TABLESWITCH(match, targets, defaultHandle));
2293: InstructionHandle relativeFieldFromHandle = il
2294: .insert(new ILOAD(2));
2295: il.insert(new ISTORE(2));
2296: il.insert(new ISUB());
2297: il.insert(instructionFactory
2298: .createGetStatic(classGen.getClassName(),
2299: "jdoInheritedFieldCount", Type.INT));
2300: il.insert(new ILOAD(1));
2301: methodGen.addLocalVariable("relativeField", Type.INT, 2,
2302: relativeFieldFromHandle, returnHandel);
2303: } else if (classInfo.getPersistenceCapableSuperclass() != null) {
2304:
2305: il.append(new ILOAD(1));
2306: il.append(instructionFactory
2307: .createGetStatic(classGen.getClassName(),
2308: "jdoInheritedFieldCount", Type.INT));
2309: il.append(new ISUB());
2310: il.append(new ISTORE(2));
2311: InstructionHandle relativeField_Start = il
2312: .append(new ILOAD(2));
2313: IFGE ifge = new IFGE(null);
2314: il.append(ifge);
2315: il.append(new ALOAD(0));
2316: il.append(new ILOAD(1));
2317: il.append(instructionFactory.createInvoke(classInfo
2318: .getPersistenceCapableSuperclass(),
2319: "jdoProvideField", Type.VOID,
2320: new Type[] { Type.INT }, Constants.INVOKESPECIAL));
2321: GOTO aGoto = new GOTO(null);
2322: il.append(aGoto);
2323: InstructionHandle newHandel = il.append(instructionFactory
2324: .createNew("java.lang.IllegalArgumentException"));
2325: ifge.setTarget(newHandel);
2326: il.append(new DUP());
2327: // il.append(new PUSH(constantPoolGen,"fieldNumber"));
2328: il.append(instructionFactory
2329: .createNew("java.lang.StringBuffer"));
2330: il.append(new DUP());
2331: il.append(instructionFactory.createInvoke(
2332: "java.lang.StringBuffer", "<init>", Type.VOID,
2333: new Type[] {}, Constants.INVOKESPECIAL));
2334: il.append(new PUSH(constantPoolGen, "Class "
2335: + classGen.getClassName()
2336: + " called with invalid fieldNumber = "));
2337: il.append(instructionFactory.createInvoke(
2338: "java.lang.StringBuffer", "append",
2339: Type.STRINGBUFFER, new Type[] { Type.STRING },
2340: Constants.INVOKEVIRTUAL));
2341: il.append(new ILOAD(1));
2342: il.append(instructionFactory.createInvoke(
2343: "java.lang.StringBuffer", "append",
2344: Type.STRINGBUFFER, new Type[] { Type.INT },
2345: Constants.INVOKEVIRTUAL));
2346: il.append(instructionFactory.createInvoke(
2347: "java.lang.StringBuffer", "toString", Type.STRING,
2348: new Type[] {}, Constants.INVOKEVIRTUAL));
2349:
2350: il.append(instructionFactory.createInvoke(
2351: "java.lang.IllegalArgumentException", "<init>",
2352: Type.VOID, new Type[] { Type.STRING },
2353: Constants.INVOKESPECIAL));
2354: il.append(new ATHROW());
2355: il.append(new RETURN());
2356: aGoto.setTarget(il.getEnd());
2357:
2358: methodGen.addLocalVariable("relativeField", Type.INT, 2,
2359: relativeField_Start, il.getEnd());
2360:
2361: } else {
2362: il.append(new RETURN());
2363: }
2364: // makeSynthetic(methodGen);
2365: methodGen.setMaxLocals();
2366: methodGen.setMaxStack();
2367: classGen.addMethod(methodGen.getMethod());
2368: il.dispose();
2369: }
2370:
2371: private void addJdoReplaceFields() {
2372: InstructionList il = new InstructionList();
2373: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
2374: Type.VOID, new Type[] { new ArrayType(Type.INT, 1) },
2375: new String[] { "fieldNumbers" }, "jdoReplaceFields",
2376: classGen.getClassName(), il, constantPoolGen);
2377: il.append(new ICONST(0));
2378: il.append(new ISTORE(2));
2379: InstructionHandle iloadHandle = il.append(new ILOAD(2));
2380: il.append(new ALOAD(1));
2381: il.append(new ARRAYLENGTH());
2382: IF_ICMPGE if_icmpge = new IF_ICMPGE(null);
2383: il.append(if_icmpge);
2384: il.append(new ALOAD(1));
2385: il.append(new ILOAD(2));
2386: il.append(new IALOAD());
2387: il.append(new ISTORE(3));
2388: InstructionHandle aloadHandle = il.append(new ALOAD(0));
2389: il.append(new ILOAD(3));
2390: il.append(instructionFactory.createInvoke(classGen
2391: .getClassName(), "jdoReplaceField", Type.VOID,
2392: new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
2393: InstructionHandle iincHandle = il.append(new IINC(2, 1));
2394: il.append(new GOTO(iloadHandle));
2395: InstructionHandle returnHandle = il.append(new RETURN());
2396: if_icmpge.setTarget(returnHandle);
2397: methodGen.addLocalVariable("i", Type.INT, 2, iloadHandle,
2398: returnHandle);
2399: methodGen.addLocalVariable("fieldNumber", Type.INT, 3,
2400: aloadHandle, iincHandle);
2401: // makeSynthetic(methodGen);
2402: methodGen.setMaxLocals();
2403: methodGen.setMaxStack();
2404: classGen.addMethod(methodGen.getMethod());
2405: il.dispose();
2406: }
2407:
2408: private void addJdoReplaceField() {
2409:
2410: int size = fieldSet.size();
2411: int[] match = new int[size];
2412: InstructionHandle[] targets = new InstructionHandle[size];
2413: InstructionHandle defaultHandle = null;
2414: InstructionHandle returnHandel = null;
2415: Set switchList = new TreeSet();
2416: ArrayList myList = new ArrayList(fieldSet);
2417: ListIterator fieldIter = myList.listIterator();
2418: int fieldNum = size;
2419: while (fieldIter.hasNext()) {
2420: fieldIter.next();
2421: }
2422: InstructionList il = new InstructionList();
2423:
2424: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
2425: Type.VOID, new Type[] { Type.INT },
2426: new String[] { "fieldNumber" }, "jdoReplaceField",
2427: classGen.getClassName(), il, constantPoolGen);
2428: if (!isEmpty) {
2429: if (classInfo.getPersistenceCapableSuperclass() == null) {
2430: defaultHandle = il
2431: .append(instructionFactory
2432: .createNew("java.lang.IllegalArgumentException"));
2433: il.append(new DUP());
2434: il.append(new PUSH(constantPoolGen, "fieldNumber"));
2435: il.append(instructionFactory.createInvoke(
2436: "java.lang.IllegalArgumentException", "<init>",
2437: Type.VOID, new Type[] { Type.STRING },
2438: Constants.INVOKESPECIAL));
2439: il.append(new ATHROW());
2440: returnHandel = il.append(new RETURN());
2441: } else {
2442: returnHandel = il.insert(new RETURN());
2443: il.insert(new ATHROW());
2444: il.insert(instructionFactory.createInvoke(
2445: "java.lang.IllegalArgumentException", "<init>",
2446: Type.VOID, new Type[] { Type.STRING },
2447: Constants.INVOKESPECIAL));
2448: il.insert(new PUSH(constantPoolGen, "fieldNumber"));
2449: il.insert(new DUP());
2450: InstructionHandle newHandel = il
2451: .insert(instructionFactory
2452: .createNew("java.lang.IllegalArgumentException"));
2453: il.insert(new GOTO(returnHandel));
2454: il.insert(instructionFactory.createInvoke(classInfo
2455: .getPersistenceCapableSuperclass(),
2456: "jdoReplaceField", Type.VOID,
2457: new Type[] { Type.INT },
2458: Constants.INVOKESPECIAL));
2459: il.insert(new ILOAD(1));
2460: il.insert(new ALOAD(0));
2461: il.insert(new IFGE(newHandel));
2462: defaultHandle = il.insert(new ILOAD(2));
2463: }
2464:
2465: while (fieldIter.hasPrevious()) {
2466: FieldInfo fieldInfo = (FieldInfo) fieldIter.previous();
2467: fieldNum--;
2468: Type fieldType = fieldInfo.getType();
2469: String stateManagerReplaceField = null;
2470: boolean isObject = false;
2471: if (typeToReplacingField.containsKey(fieldInfo
2472: .getType())) {
2473: stateManagerReplaceField = (String) typeToReplacingField
2474: .get(fieldInfo.getType());
2475: isObject = false;
2476: } else {
2477: isObject = true;
2478: }
2479:
2480: il.insert(new GOTO(returnHandel));
2481: il.insert(instructionFactory.createPutField(classGen
2482: .getClassName(), fieldInfo.getFieldName(),
2483: fieldType));
2484: if (isObject) {
2485: if (fieldInfo.isArray()) {
2486: il.insert(instructionFactory
2487: .createCheckCast(new ObjectType(
2488: fieldInfo.getSignature())));
2489: } else {
2490: il.insert(instructionFactory
2491: .createCheckCast(new ObjectType(
2492: fieldInfo.getReturnType())));
2493: }
2494: il.insert(instructionFactory.createInvoke(
2495: STATE_MANAGER, "replacingObjectField",
2496: Type.OBJECT, new Type[] { PC_OBJECT_TYPE,
2497: Type.INT },
2498: Constants.INVOKEINTERFACE));
2499: } else {
2500: il.insert(instructionFactory.createInvoke(
2501: STATE_MANAGER, stateManagerReplaceField,
2502: fieldType, new Type[] { PC_OBJECT_TYPE,
2503: Type.INT },
2504: Constants.INVOKEINTERFACE));
2505: }
2506: il.insert(new ILOAD(1));
2507: il.insert(new ALOAD(0));
2508: il.insert(instructionFactory.createGetField(
2509: getTopPCSuperOrCurrentClassName(),
2510: "jdoStateManager", SM_OBJECT_TYPE));
2511: il.insert(new ALOAD(0));
2512: InstructionHandle switchHandel = il
2513: .insert(new ALOAD(0));
2514: TableSwitchHelper tsh = new TableSwitchHelper();
2515: tsh.match = fieldNum;
2516: tsh.target = switchHandel;
2517: switchList.add(tsh);
2518: }
2519: Iterator sIter = switchList.iterator();
2520: int count = 0;
2521: while (sIter.hasNext()) {
2522: TableSwitchHelper tsh = (TableSwitchHelper) sIter
2523: .next();
2524: match[count] = tsh.match;
2525: targets[count] = tsh.target;
2526: count++;
2527: }
2528:
2529: il.insert(new TABLESWITCH(match, targets, defaultHandle));
2530: InstructionHandle relativeFieldFromHandle = il
2531: .insert(new ILOAD(2));
2532: il.insert(new ISTORE(2));
2533: il.insert(new ISUB());
2534: il.insert(instructionFactory
2535: .createGetStatic(classGen.getClassName(),
2536: "jdoInheritedFieldCount", Type.INT));
2537: il.insert(new ILOAD(1));
2538: methodGen.addLocalVariable("relativeField", Type.INT, 2,
2539: relativeFieldFromHandle, returnHandel);
2540: } else if (classInfo.getPersistenceCapableSuperclass() != null) {
2541: il.append(new ILOAD(1));
2542: il.append(instructionFactory
2543: .createGetStatic(classGen.getClassName(),
2544: "jdoInheritedFieldCount", Type.INT));
2545: il.append(new ISUB());
2546: il.append(new ISTORE(2));
2547: InstructionHandle relativeField_Start = il
2548: .append(new ILOAD(2));
2549: IFGE ifge = new IFGE(null);
2550: il.append(ifge);
2551: il.append(new ALOAD(0));
2552: il.append(new ILOAD(1));
2553:
2554: il.append(instructionFactory.createInvoke(classInfo
2555: .getPersistenceCapableSuperclass(),
2556: "jdoReplaceField", Type.VOID,
2557: new Type[] { Type.INT }, Constants.INVOKESPECIAL));
2558: GOTO aGoto = new GOTO(null);
2559: il.append(aGoto);
2560: InstructionHandle newHandel = il.append(instructionFactory
2561: .createNew("java.lang.IllegalArgumentException"));
2562: ifge.setTarget(newHandel);
2563: il.append(new DUP());
2564: il.append(new PUSH(constantPoolGen, "fieldNumber"));
2565: il.append(instructionFactory.createInvoke(
2566: "java.lang.IllegalArgumentException", "<init>",
2567: Type.VOID, new Type[] { Type.STRING },
2568: Constants.INVOKESPECIAL));
2569: il.append(new ATHROW());
2570: il.append(new RETURN());
2571: aGoto.setTarget(il.getEnd());
2572:
2573: methodGen.addLocalVariable("relativeField", Type.INT, 2,
2574: relativeField_Start, il.getEnd());
2575: } else {
2576: il.append(new RETURN());
2577: }
2578:
2579: // makeSynthetic(methodGen);
2580: methodGen.setMaxLocals();
2581: methodGen.setMaxStack();
2582: classGen.addMethod(methodGen.getMethod());
2583: il.dispose();
2584: }
2585:
2586: private void addFieldGetters() {
2587: Iterator fieldIter = fieldSet.iterator();
2588: int fieldNum = 0;
2589:
2590: while (fieldIter.hasNext()) {
2591: FieldInfo fieldInfo = (FieldInfo) fieldIter.next();
2592: int acc = Constants.ACC_STATIC
2593: | (fieldInfo.isPrivate() ? Constants.ACC_PRIVATE
2594: : (short) 0)
2595: | (fieldInfo.isProtected() ? Constants.ACC_PROTECTED
2596: : (short) 0)
2597: | (fieldInfo.isPublic() ? Constants.ACC_PUBLIC
2598: : (short) 0);
2599: Type returnType = fieldInfo.getType();
2600: ReturnInstruction returnInstruction;
2601: String stateManagerGetField = null;
2602: boolean isObject = false;
2603: if (typeToGetField.containsKey(returnType)) {
2604: stateManagerGetField = (String) typeToGetField
2605: .get(returnType);
2606: returnInstruction = (ReturnInstruction) typeToReturnType
2607: .get(returnType);
2608: isObject = false;
2609: } else {
2610: stateManagerGetField = "getObjectField";
2611: returnInstruction = new ARETURN();
2612: isObject = true;
2613: }
2614:
2615: InstructionList il = new InstructionList();
2616:
2617: MethodGen methodGen = new MethodGen(
2618: acc,
2619: returnType,
2620: new Type[] { new ObjectType(classGen.getClassName()) },
2621: new String[] { "x" }, fieldInfo.getJdoGetName(),
2622: classGen.getClassName(), il, constantPoolGen);
2623:
2624: if (fieldInfo.getFlag() == CHECK_READ_WRITE) {// this field is in the default fetch group
2625: il.append(new ALOAD(0));
2626: il.append(instructionFactory.createGetField(
2627: getTopPCSuperOrCurrentClassName(), "jdoFlags",
2628: Type.BYTE));
2629: IFGT ifgt = new IFGT(null);
2630: il.append(ifgt);
2631: il.append(new ALOAD(0));
2632: il.append(instructionFactory.createGetField(classGen
2633: .getClassName(), fieldInfo.getFieldName(),
2634: returnType));
2635: il.append(returnInstruction);
2636: InstructionHandle ifgtHandel = il.append(new ALOAD(0));
2637: ifgt.setTarget(ifgtHandel);
2638: il.append(instructionFactory.createGetField(
2639: getTopPCSuperOrCurrentClassName(),
2640: "jdoStateManager", SM_OBJECT_TYPE));
2641: il.append(new ASTORE(1));
2642: InstructionHandle smHandle = il.append(new ALOAD(1));
2643: IFNULL ifnull = new IFNULL(null); // null to aload_0 58
2644: il.append(ifnull);
2645: il.append(new ALOAD(1));
2646: il.append(new ALOAD(0));
2647: il.append(instructionFactory.createGetStatic(classGen
2648: .getClassName(), "jdoInheritedFieldCount",
2649: Type.INT));
2650: il.append(new PUSH(constantPoolGen, fieldNum));
2651: il.append(new IADD());
2652: il.append(instructionFactory.createInvoke(
2653: STATE_MANAGER, "isLoaded", Type.BOOLEAN,
2654: new Type[] { PC_OBJECT_TYPE, Type.INT },
2655: Constants.INVOKEINTERFACE));
2656: IFEQ ifeq = new IFEQ(null);
2657: il.append(ifeq); // null to aload_1 41
2658: il.append(new ALOAD(0));
2659: il.append(instructionFactory.createGetField(classGen
2660: .getClassName(), fieldInfo.getFieldName(),
2661: returnType));
2662: il.append(returnInstruction);
2663: InstructionHandle ifeqHandel = il.append(new ALOAD(1));
2664: ifeq.setTarget(ifeqHandel);
2665: il.append(new ALOAD(0));
2666: il.append(instructionFactory.createGetStatic(classGen
2667: .getClassName(), "jdoInheritedFieldCount",
2668: Type.INT));
2669: il.append(new PUSH(constantPoolGen, fieldNum));
2670: il.append(new IADD());
2671: il.append(new ALOAD(0));
2672: il.append(instructionFactory.createGetField(classGen
2673: .getClassName(), fieldInfo.getFieldName(),
2674: returnType));
2675: if (isObject) {//if there is a object cast it
2676: il.append(instructionFactory.createInvoke(
2677: STATE_MANAGER, stateManagerGetField,
2678: Type.OBJECT, new Type[] { PC_OBJECT_TYPE,
2679: Type.INT, Type.OBJECT },
2680: Constants.INVOKEINTERFACE));
2681: il.append(instructionFactory
2682: .createCheckCast((ReferenceType) fieldInfo
2683: .getType()));
2684: } else {
2685: il.append(instructionFactory.createInvoke(
2686: STATE_MANAGER, stateManagerGetField,
2687: returnType, new Type[] { PC_OBJECT_TYPE,
2688: Type.INT, returnType },
2689: Constants.INVOKEINTERFACE));
2690: }
2691: il.append(returnInstruction);
2692: InstructionHandle ifNullHandle = il
2693: .append(new ALOAD(0));
2694: ifnull.setTarget(ifNullHandle);
2695: il.append(instructionFactory.createGetField(classGen
2696: .getClassName(), fieldInfo.getFieldName(),
2697: returnType));
2698: il.append(returnInstruction);
2699: methodGen.addLocalVariable("sm", SM_OBJECT_TYPE, 1,
2700: smHandle, il.getEnd());
2701:
2702: } else if (fieldInfo.getFlag() == MEDIATE_READ_WRITE) {
2703:
2704: il.append(new ALOAD(0));
2705: il.append(instructionFactory.createGetField(
2706: getTopPCSuperOrCurrentClassName(),
2707: "jdoStateManager", SM_OBJECT_TYPE));
2708: il.append(new ASTORE(1));
2709: InstructionHandle smHandle = il.append(new ALOAD(1));
2710: IFNULL ifnull = new IFNULL(null); // null to aload_0 58
2711: il.append(ifnull);
2712: il.append(new ALOAD(1));
2713: il.append(new ALOAD(0));
2714: il.append(instructionFactory.createGetStatic(classGen
2715: .getClassName(), "jdoInheritedFieldCount",
2716: Type.INT));
2717: il.append(new PUSH(constantPoolGen, fieldNum));
2718: il.append(new IADD());
2719: il.append(instructionFactory.createInvoke(
2720: STATE_MANAGER, "isLoaded", Type.BOOLEAN,
2721: new Type[] { PC_OBJECT_TYPE, Type.INT },
2722: Constants.INVOKEINTERFACE));
2723: IFEQ ifeq = new IFEQ(null);
2724: il.append(ifeq); // null to aload_1 41
2725: il.append(new ALOAD(0));
2726: il.append(instructionFactory.createGetField(classGen
2727: .getClassName(), fieldInfo.getFieldName(),
2728: returnType));
2729: il.append(returnInstruction);
2730: InstructionHandle ifeqHandel = il.append(new ALOAD(1));
2731: ifeq.setTarget(ifeqHandel);
2732: il.append(new ALOAD(0));
2733: il.append(instructionFactory.createGetStatic(classGen
2734: .getClassName(), "jdoInheritedFieldCount",
2735: Type.INT));
2736: il.append(new PUSH(constantPoolGen, fieldNum));
2737: il.append(new IADD());
2738: il.append(new ALOAD(0));
2739: il.append(instructionFactory.createGetField(classGen
2740: .getClassName(), fieldInfo.getFieldName(),
2741: returnType));
2742: if (isObject) {//if there is a object cast it
2743: il.append(instructionFactory.createInvoke(
2744: STATE_MANAGER, stateManagerGetField,
2745: Type.OBJECT, new Type[] { PC_OBJECT_TYPE,
2746: Type.INT, Type.OBJECT },
2747: Constants.INVOKEINTERFACE));
2748: il.append(instructionFactory
2749: .createCheckCast((ReferenceType) fieldInfo
2750: .getType()));
2751: } else {
2752: il.append(instructionFactory.createInvoke(
2753: STATE_MANAGER, stateManagerGetField,
2754: returnType, new Type[] { PC_OBJECT_TYPE,
2755: Type.INT, returnType },
2756: Constants.INVOKEINTERFACE));
2757: }
2758: il.append(returnInstruction);
2759: InstructionHandle ifNullHandle = il
2760: .append(new ALOAD(0));
2761: ifnull.setTarget(ifNullHandle);
2762: il.append(instructionFactory.createGetField(classGen
2763: .getClassName(), fieldInfo.getFieldName(),
2764: returnType));
2765: il.append(returnInstruction);
2766: methodGen.addLocalVariable("sm", SM_OBJECT_TYPE, 1,
2767: smHandle, il.getEnd());
2768:
2769: } else {//no mediation
2770: if (fieldInfo.primaryKey()
2771: && (classInfo.getIdentityType() == MDStatics.IDENTITY_TYPE_APPLICATION)
2772: && classInfo.isKeyGen()) {
2773:
2774: il.append(new ALOAD(0));
2775: il
2776: .append(instructionFactory
2777: .createGetField(
2778: classGen.getClassName(),
2779: "jdoStateManager",
2780: new ObjectType(
2781: "javax.jdo.spi.StateManager")));
2782: il.append(new INSTANCEOF(constantPoolGen
2783: .addClass(VERSANT_STATE_MANAGER)));
2784: IFEQ ifeq = new IFEQ(null);
2785: il.append(ifeq); //25
2786: il.append(new ALOAD(0));
2787: il
2788: .append(instructionFactory
2789: .createGetField(
2790: classGen.getClassName(),
2791: "jdoStateManager",
2792: new ObjectType(
2793: "javax.jdo.spi.StateManager")));
2794: il.append(instructionFactory
2795: .createCheckCast(new ObjectType(
2796: VERSANT_STATE_MANAGER)));
2797: il.append(instructionFactory.createGetStatic(
2798: classGen.getClassName(),
2799: "jdoInheritedFieldCount", Type.INT));
2800: il.append(new PUSH(constantPoolGen, fieldInfo
2801: .getFieldNo()));
2802: il.append(new IADD());
2803: il.append(instructionFactory.createInvoke(
2804: VERSANT_STATE_MANAGER, "fillNewAppPKField",
2805: Type.VOID, new Type[] { Type.INT },
2806: Constants.INVOKEINTERFACE));
2807: InstructionHandle nopHandle = il.append(new NOP());
2808: ifeq.setTarget(nopHandle);
2809: }
2810: il.append(new ALOAD(0));
2811: il.append(instructionFactory.createGetField(classGen
2812: .getClassName(), fieldInfo.getFieldName(),
2813: returnType));
2814: il.append(returnInstruction);
2815: }
2816: methodGen.removeNOPs();
2817: makeSynthetic(methodGen);
2818: methodGen.setMaxLocals();
2819: methodGen.setMaxStack();
2820: classGen.addMethod(methodGen.getMethod());
2821: il.dispose();
2822: fieldNum++;
2823:
2824: }
2825:
2826: }
2827:
2828: private void makeSynthetic(FieldGenOrMethodGen gen) {
2829: gen.addAttribute(new Synthetic(synthetic, 0, null, gen
2830: .getConstantPool().getConstantPool()));
2831: }
2832:
2833: private void addFieldSetters() {
2834: Iterator fieldIter = fieldSet.iterator();
2835: int fieldNum = 0;
2836:
2837: while (fieldIter.hasNext()) {
2838: FieldInfo fieldInfo = (FieldInfo) fieldIter.next();
2839:
2840: int acc = Constants.ACC_STATIC
2841: | (fieldInfo.isPrivate() ? Constants.ACC_PRIVATE
2842: : (short) 0)
2843: | (fieldInfo.isProtected() ? Constants.ACC_PROTECTED
2844: : (short) 0)
2845: | (fieldInfo.isPublic() ? Constants.ACC_PUBLIC
2846: : (short) 0);
2847:
2848: Type fieldType = fieldInfo.getType();
2849: boolean isObject = false;
2850: String stateManagerSetField = null;
2851: if (typeToSetField.containsKey(fieldType)) {
2852: stateManagerSetField = (String) typeToSetField
2853: .get(fieldType);
2854: isObject = false;
2855: } else {
2856: stateManagerSetField = "setObjectField";
2857: isObject = true;
2858: }
2859:
2860: InstructionList il = new InstructionList();
2861: MethodGen methodGen = new MethodGen(acc, Type.VOID,
2862: new Type[] {
2863: new ObjectType(classGen.getClassName()),
2864: fieldType },
2865: new String[] { "x", "newValue" }, fieldInfo
2866: .getJdoSetName(), classGen.getClassName(),
2867: il, constantPoolGen);
2868:
2869: int flags = fieldInfo.getFlag();
2870: boolean isLorD = false;
2871: if (fieldType.equals(Type.LONG)
2872: || fieldType.equals(Type.DOUBLE))
2873: isLorD = true;
2874: IFNE ifne = new IFNE(null);
2875: if (flags == CHECK_READ_WRITE || flags == CHECK_WRITE) {// this field is in the default fetch group or is transient transactional
2876: il.append(new ALOAD(0));
2877: il.append(instructionFactory.createGetField(
2878: getTopPCSuperOrCurrentClassName(), "jdoFlags",
2879: Type.BYTE));
2880:
2881: il.append(ifne); // 13
2882: il.append(new ALOAD(0));
2883: if (isObject) {
2884: il.append(new ALOAD(1));
2885: } else {
2886: il.append((LoadInstruction) typeToLoadType
2887: .get(fieldType));
2888: }
2889: il.append(instructionFactory.createPutField(classGen
2890: .getClassName(), fieldInfo.getFieldName(),
2891: fieldType));
2892: il.append(new RETURN());
2893: }
2894: InstructionHandle ifneHandel = il.append(new ALOAD(0));
2895: ifne.setTarget(ifneHandel);
2896: il.append(instructionFactory.createGetField(
2897: getTopPCSuperOrCurrentClassName(),
2898: "jdoStateManager", SM_OBJECT_TYPE));
2899: il.append(new ASTORE((isLorD ? 3 : 2)));
2900: InstructionHandle smStartHandle = il.append(new ALOAD(
2901: (isLorD ? 3 : 2)));
2902: IFNULL ifnull = new IFNULL(null);
2903: il.append(ifnull);
2904: il.append(new ALOAD((isLorD ? 3 : 2)));
2905: il.append(new ALOAD(0));
2906: il.append(instructionFactory
2907: .createGetStatic(classGen.getClassName(),
2908: "jdoInheritedFieldCount", Type.INT));
2909: il.append(new PUSH(constantPoolGen, fieldNum));
2910: il.append(new IADD());
2911: il.append(new ALOAD(0));
2912: il.append(instructionFactory.createGetField(classGen
2913: .getClassName(), fieldInfo.getFieldName(),
2914: fieldType));
2915: if (isObject) {//if there is a object call it with Object's
2916: il.append(new ALOAD(1));
2917: il.append(instructionFactory.createInvoke(
2918: STATE_MANAGER, stateManagerSetField, Type.VOID,
2919: new Type[] { PC_OBJECT_TYPE, Type.INT,
2920: Type.OBJECT, Type.OBJECT },
2921: Constants.INVOKEINTERFACE));
2922: } else {
2923: il.append((LoadInstruction) typeToLoadType
2924: .get(fieldType));
2925: il.append(instructionFactory.createInvoke(
2926: STATE_MANAGER, stateManagerSetField, Type.VOID,
2927: new Type[] { PC_OBJECT_TYPE, Type.INT,
2928: fieldType, fieldType },
2929: Constants.INVOKEINTERFACE));
2930: }
2931: GOTO aGoto = new GOTO(null);
2932: il.append(aGoto);
2933: InstructionHandle ifnullHandle = il.append(new ALOAD(0));
2934: ifnull.setTarget(ifnullHandle);
2935: if (isObject) {//if there is a object call it with Object's
2936: il.append(new ALOAD(1));
2937: } else {
2938: il.append((LoadInstruction) typeToLoadType
2939: .get(fieldType));
2940: }
2941: il.append(instructionFactory.createPutField(classGen
2942: .getClassName(), fieldInfo.getFieldName(),
2943: fieldType));
2944: InstructionHandle lastHandle = il.append(new RETURN());
2945: aGoto.setTarget(lastHandle);
2946:
2947: methodGen.addLocalVariable("sm", SM_OBJECT_TYPE,
2948: (isLorD ? 3 : 2), smStartHandle, il.getEnd());
2949:
2950: makeSynthetic(methodGen);
2951: methodGen.setMaxLocals();
2952: methodGen.setMaxStack();
2953: classGen.addMethod(methodGen.getMethod());
2954: il.dispose();
2955: fieldNum++;
2956:
2957: }
2958:
2959: }
2960:
2961: private void addJdoGetManagedFieldCount() {
2962: InstructionList il = new InstructionList();
2963: MethodGen methodGen = new MethodGen(Constants.ACC_STATIC
2964: | Constants.ACC_PROTECTED, Type.INT, null, null,
2965: "jdoGetManagedFieldCount", classGen.getClassName(), il,
2966: constantPoolGen);
2967: il.append(instructionFactory.createGetStatic(classGen
2968: .getClassName(), "jdoInheritedFieldCount", Type.INT));
2969: il.append(new PUSH(constantPoolGen, fieldSet.size()));
2970: il.append(new IADD());
2971: il.append(new IRETURN());
2972:
2973: // makeSynthetic(methodGen);
2974: methodGen.setMaxLocals();
2975: methodGen.setMaxStack();
2976: classGen.addMethod(methodGen.getMethod());
2977: il.dispose();
2978: }
2979:
2980: private void addJdoInheritedFieldCount() {
2981: FieldGen fieldGen = new FieldGen(Constants.ACC_PRIVATE
2982: | Constants.ACC_STATIC,//| NEW Constants.ACC_FINAL,
2983: Type.INT, "jdoInheritedFieldCount", constantPoolGen);
2984: makeSynthetic(fieldGen);
2985: classGen.addField(fieldGen.getField());
2986: Method m = getStaticConstructor();
2987: MethodGen methodGen = new MethodGen(m, classGen.getClassName(),
2988: constantPoolGen);
2989: InstructionList il = methodGen.getInstructionList();
2990: InstructionHandle initialReturnHandle = il.getEnd();
2991: InstructionHandle nopTarget = il.append(new NOP());
2992: if (classInfo.getPersistenceCapableSuperclass() == null) {
2993: il.append(new ICONST(0));
2994: } else {
2995: il.append(instructionFactory.createInvoke(classInfo
2996: .getPersistenceCapableSuperclass(),
2997: "jdoGetManagedFieldCount", Type.INT, new Type[] {},
2998: Constants.INVOKESTATIC));
2999: }
3000: il.append(instructionFactory.createPutStatic(classGen
3001: .getClassName(), "jdoInheritedFieldCount", Type.INT));
3002: il.append(new RETURN());
3003: try {
3004: // System.out.println("initialReturnHandle that was deleted = " + initialReturnHandle);
3005: il.delete(initialReturnHandle);
3006: } catch (TargetLostException e) {
3007: InstructionHandle[] targets = e.getTargets();
3008: for (int i = 0; i < targets.length; i++) {
3009: InstructionTargeter[] targeters = targets[i]
3010: .getTargeters();
3011: for (int j = 0; j < targeters.length; j++) {
3012: targeters[j].updateTarget(targets[i], nopTarget);
3013: }
3014: }
3015: }
3016:
3017: methodGen.removeNOPs();
3018: methodGen.setMaxLocals();
3019: methodGen.setMaxStack();
3020: classGen.replaceMethod(m, methodGen.getMethod());
3021: il.dispose();
3022: }
3023:
3024: private void addJdoFieldTypes() {
3025: FieldGen fieldGen = new FieldGen(
3026: Constants.ACC_PRIVATE | Constants.ACC_STATIC,//| NEW Constants.ACC_FINAL,
3027: new ArrayType("java.lang.Class", 1), "jdoFieldTypes",
3028: constantPoolGen);
3029: makeSynthetic(fieldGen);
3030: classGen.addField(fieldGen.getField());
3031: Method m = getStaticConstructor();
3032: MethodGen methodGen = new MethodGen(m, classGen.getClassName(),
3033: constantPoolGen);
3034: InstructionList il = methodGen.getInstructionList();
3035:
3036: InstructionHandle initialReturnHandle = il.getEnd();
3037: InstructionHandle nopTarget = il.append(new NOP());
3038: il.append(new PUSH(constantPoolGen, fieldSet.size()));
3039: il.append(new ANEWARRAY(constantPoolGen
3040: .addClass(new ObjectType("java.lang.Class"))));
3041: il.append(new DUP());
3042: Iterator iter = fieldSet.iterator();
3043: int push = 0;
3044: while (iter.hasNext()) {
3045: FieldInfo field = (FieldInfo) iter.next();
3046: if (field.isPrimative()) {
3047: il.append(new PUSH(constantPoolGen, push));
3048: il.append(instructionFactory.createGetStatic(field
3049: .getPrimativeTypeObject(), "TYPE",
3050: new ObjectType("java.lang.Class")));
3051: il.append(new AASTORE());
3052: il.append(new DUP());
3053: } else {
3054: InstructionList tempIl = new InstructionList();
3055: String returnType = field.getReturnType();
3056: String fieldName = getSetClass$Field(field);
3057: tempIl.insert(new DUP());
3058: InstructionHandle gotoAASTORE = tempIl
3059: .insert(new AASTORE());
3060: InstructionHandle gotoGetStatic = tempIl
3061: .insert(instructionFactory.createGetStatic(
3062: classGen.getClassName(), fieldName,
3063: new ObjectType("java.lang.Class")));
3064: tempIl.insert(new GOTO(gotoAASTORE));
3065: tempIl.insert(instructionFactory.createPutStatic(
3066: classGen.getClassName(), fieldName,
3067: new ObjectType("java.lang.Class")));
3068: tempIl.insert(new DUP());
3069: tempIl.insert(instructionFactory
3070: .createInvoke(classGen.getClassName(),
3071: "class$", new ObjectType(
3072: "java.lang.Class"),
3073: new Type[] { new ObjectType(
3074: "java.lang.String") },
3075: Constants.INVOKESTATIC));
3076: if (field.isArray()) {
3077: tempIl.insert(new PUSH(constantPoolGen, field
3078: .getSignature().replace('/', '.')));
3079: } else {
3080: tempIl
3081: .insert(new PUSH(constantPoolGen,
3082: returnType));
3083: }
3084:
3085: tempIl.insert(new IFNONNULL(gotoGetStatic));
3086: tempIl.insert(instructionFactory.createGetStatic(
3087: classGen.getClassName(), fieldName,
3088: new ObjectType("java.lang.Class")));
3089: tempIl.insert(new PUSH(constantPoolGen, push));
3090:
3091: il.append(tempIl);
3092: }
3093: push++;
3094: }
3095: try {
3096: il.delete(il.getEnd());
3097: } catch (TargetLostException e) {//there should never be target for this instruction (DUP)
3098: e.printStackTrace();
3099: }
3100:
3101: il.append(instructionFactory.createPutStatic(classGen
3102: .getClassName(), "jdoFieldTypes", new ArrayType(
3103: new ObjectType("java.lang.Class"), 1)));
3104: il.append(new RETURN());
3105: try {
3106: il.delete(initialReturnHandle);
3107: } catch (TargetLostException e) {
3108: InstructionHandle[] targets = e.getTargets();
3109: for (int i = 0; i < targets.length; i++) {
3110: InstructionTargeter[] targeters = targets[i]
3111: .getTargeters();
3112: for (int j = 0; j < targeters.length; j++) {
3113: targeters[j].updateTarget(targets[i], nopTarget);
3114: }
3115: }
3116: }
3117: methodGen.removeNOPs();
3118: methodGen.setMaxLocals();
3119: methodGen.setMaxStack();
3120: classGen.replaceMethod(m, methodGen.getMethod());
3121: il.dispose();
3122: }
3123:
3124: private void addJdoFieldFlags() {
3125: FieldGen fieldGen = new FieldGen(
3126: Constants.ACC_PRIVATE | Constants.ACC_STATIC,//| NEW Constants.ACC_FINAL,
3127: new ArrayType(Type.BYTE, 1), "jdoFieldFlags",
3128: constantPoolGen);
3129:
3130: makeSynthetic(fieldGen);
3131: classGen.addField(fieldGen.getField());
3132: Method m = getStaticConstructor();
3133: MethodGen methodGen = new MethodGen(m, classGen.getClassName(),
3134: constantPoolGen);
3135: InstructionList il = methodGen.getInstructionList();
3136:
3137: InstructionHandle initialReturnHandle = il.getEnd();
3138: InstructionHandle nopTarget = il.append(new NOP());
3139: il.append(new PUSH(constantPoolGen, fieldSet.size()));
3140: il.append(new NEWARRAY((Type.BYTE).getType()));
3141: Iterator iter = fieldSet.iterator();
3142: int push = 0;
3143: while (iter.hasNext()) {
3144: FieldInfo field = (FieldInfo) iter.next();
3145: il.append(new DUP());
3146: il.append(new PUSH(constantPoolGen, push));
3147: il.append(new PUSH(constantPoolGen, field.getFlag()));
3148: il.append(new BASTORE());
3149: push++;
3150: }
3151: il.append(instructionFactory.createPutStatic(classGen
3152: .getClassName(), "jdoFieldFlags", new ArrayType(
3153: Type.BYTE, 1)));
3154: il.append(new RETURN());
3155: try {
3156: il.delete(initialReturnHandle);
3157: } catch (TargetLostException e) {
3158: InstructionHandle[] targets = e.getTargets();
3159: for (int i = 0; i < targets.length; i++) {
3160: InstructionTargeter[] targeters = targets[i]
3161: .getTargeters();
3162: for (int j = 0; j < targeters.length; j++) {
3163: targeters[j].updateTarget(targets[i], nopTarget);
3164: }
3165: }
3166: }
3167: methodGen.removeNOPs();
3168: methodGen.setMaxLocals();
3169: methodGen.setMaxStack();
3170: classGen.replaceMethod(m, methodGen.getMethod());
3171: il.dispose();
3172:
3173: }
3174:
3175: private void addInterrogatives() {
3176: if (classInfo.getTopPCSuperClass() == null) {
3177: setInterrogative("jdoIsPersistent", "isPersistent");
3178: setInterrogative("jdoIsTransactional", "isTransactional");
3179: setInterrogative("jdoIsNew", "isNew");
3180: setInterrogative("jdoIsDirty", "isDirty");
3181: setInterrogative("jdoIsDeleted", "isDeleted");
3182: setJdoGetPersistanceManager();
3183: setJdoMakeDirty();
3184: }
3185: }
3186:
3187: /**
3188: * Add method
3189: * public PersistenceManager jdoGetPersistenceManager(){
3190: * return jdoStateManager == null ? null : jdoStateManager.getPersistenceManager(this);
3191: * }
3192: */
3193: private void setJdoGetPersistanceManager() {
3194: InstructionList il = new InstructionList();
3195: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
3196: new ObjectType("javax.jdo.PersistenceManager"), null,
3197: null, "jdoGetPersistenceManager", classGen
3198: .getClassName(), il, constantPoolGen);
3199:
3200: InstructionHandle ireturnHandle = il.insert(new ARETURN());
3201: il.insert(instructionFactory.createInvoke(STATE_MANAGER,
3202: "getPersistenceManager", new ObjectType(
3203: "javax.jdo.PersistenceManager"),
3204: new Type[] { PC_OBJECT_TYPE },
3205: Constants.INVOKEINTERFACE));
3206: il.insert(new ALOAD(0));
3207: il.insert(instructionFactory.createGetField(
3208: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
3209: SM_OBJECT_TYPE));
3210: InstructionHandle ifNonNullHandle = il.insert(new ALOAD(0));
3211: il.insert(new GOTO(ireturnHandle));
3212: il.insert(new ACONST_NULL());
3213: il.insert(new IFNONNULL(ifNonNullHandle));
3214: il.insert(instructionFactory.createGetField(
3215: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
3216: SM_OBJECT_TYPE));
3217: il.insert(new ALOAD(0));
3218:
3219: // makeSynthetic(methodGen);
3220: methodGen.setMaxLocals();
3221: methodGen.setMaxStack();
3222: classGen.addMethod(methodGen.getMethod());
3223: il.dispose();
3224:
3225: }
3226:
3227: /**
3228: * Add method
3229: *
3230: * public void jdoMakeDirty(String fieldName){
3231: * if(jdoStateManager==null) return;
3232: * jdoStateManager.makeDirty(this, fieldName);
3233: * }
3234: *
3235: */
3236: private void setJdoMakeDirty() {
3237: InstructionList il = new InstructionList();
3238: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
3239: Type.VOID, new Type[] { Type.STRING },
3240: new String[] { "fieldName" }, "jdoMakeDirty", classGen
3241: .getClassName(), il, constantPoolGen);
3242: il.insert(new RETURN());
3243: il.insert(instructionFactory.createInvoke(STATE_MANAGER,
3244: "makeDirty", Type.VOID, new Type[] { PC_OBJECT_TYPE,
3245: Type.STRING }, Constants.INVOKEINTERFACE));
3246: il.insert(new ALOAD(1));
3247: il.insert(new ALOAD(0));
3248: il.insert(instructionFactory.createGetField(
3249: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
3250: SM_OBJECT_TYPE));
3251: InstructionHandle ifNonNullHandle = il.insert(new ALOAD(0));
3252: il.insert(new RETURN());
3253: il.insert(new IFNONNULL(ifNonNullHandle));
3254: il.insert(instructionFactory.createGetField(
3255: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
3256: SM_OBJECT_TYPE));
3257: il.insert(new ALOAD(0));
3258:
3259: // makeSynthetic(methodGen);
3260: methodGen.setMaxLocals();
3261: methodGen.setMaxStack();
3262: classGen.addMethod(methodGen.getMethod());
3263: il.dispose();
3264: }
3265:
3266: private void addJdoFieldNames() {
3267: FieldGen fieldGen = new FieldGen(
3268: Constants.ACC_PRIVATE | Constants.ACC_STATIC,// | NEW Constants.ACC_FINAL,
3269: new ArrayType(Type.STRING, 1), "jdoFieldNames",
3270: constantPoolGen);
3271: makeSynthetic(fieldGen);
3272: classGen.addField(fieldGen.getField());
3273: Method m = getStaticConstructor();
3274: MethodGen methodGen = new MethodGen(m, classGen.getClassName(),
3275: constantPoolGen);
3276: InstructionList il = methodGen.getInstructionList();
3277:
3278: InstructionHandle initialReturnHandle = il.getEnd();
3279:
3280: InstructionHandle nopTarget = il.append(new NOP());
3281: il.append(new PUSH(constantPoolGen, fieldSet.size()));
3282: il.append(new ANEWARRAY(constantPoolGen.addClass(Type.STRING)));
3283:
3284: Iterator iter = fieldSet.iterator();
3285: int push = 0;
3286: while (iter.hasNext()) {
3287: FieldInfo field = (FieldInfo) iter.next();
3288: il.append(new DUP());
3289: il.append(new PUSH(constantPoolGen, push));
3290: il.append(new PUSH(constantPoolGen, field.getFieldName()));
3291: il.append(new AASTORE());
3292: push++;
3293: }
3294: il.append(instructionFactory.createPutStatic(classGen
3295: .getClassName(), "jdoFieldNames", new ArrayType(
3296: Type.STRING, 1)));
3297: il.append(new RETURN());
3298: try {
3299: // System.out.println("initialReturnHandle that was deleted = " + initialReturnHandle);
3300: il.delete(initialReturnHandle);
3301: } catch (TargetLostException e) {
3302: InstructionHandle[] targets = e.getTargets();
3303: for (int i = 0; i < targets.length; i++) {
3304: InstructionTargeter[] targeters = targets[i]
3305: .getTargeters();
3306: for (int j = 0; j < targeters.length; j++) {
3307: targeters[j].updateTarget(targets[i], nopTarget);
3308: }
3309: }
3310: }
3311:
3312: methodGen.removeNOPs();
3313: methodGen.setMaxLocals();
3314: methodGen.setMaxStack();
3315: classGen.replaceMethod(m, methodGen.getMethod());
3316: il.dispose();
3317: }
3318:
3319: private void setInterrogative(String methodName,
3320: String callingMethodName) {
3321: InstructionList il = new InstructionList();
3322: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
3323: Type.BOOLEAN, null, null, methodName, classGen
3324: .getClassName(), il, constantPoolGen);
3325: InstructionHandle ireturnHandle = il.insert(new IRETURN());
3326: il.insert(instructionFactory.createInvoke(STATE_MANAGER,
3327: callingMethodName, Type.BOOLEAN,
3328: new Type[] { PC_OBJECT_TYPE },
3329: Constants.INVOKEINTERFACE));
3330: il.insert(new ALOAD(0));
3331: il.insert(instructionFactory.createGetField(
3332: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
3333: SM_OBJECT_TYPE));
3334: InstructionHandle ifNonNullHandle = il.insert(new ALOAD(0));
3335: il.insert(new GOTO(ireturnHandle));
3336: il.insert(new ICONST(0));
3337: il.insert(new IFNONNULL(ifNonNullHandle));
3338: il.insert(instructionFactory.createGetField(
3339: getTopPCSuperOrCurrentClassName(), "jdoStateManager",
3340: SM_OBJECT_TYPE));
3341: il.insert(new ALOAD(0));
3342:
3343: // makeSynthetic(methodGen);
3344: methodGen.setMaxLocals();
3345: methodGen.setMaxStack();
3346: classGen.addMethod(methodGen.getMethod());
3347: il.dispose();
3348:
3349: }
3350:
3351: private void addSerialVersionUID() {
3352: if (!hasSerialVersionUID()) {
3353: FieldGen fieldGen = new FieldGen(Constants.ACC_PRIVATE
3354: | Constants.ACC_STATIC | Constants.ACC_FINAL,
3355: Type.LONG, "serialVersionUID", constantPoolGen);
3356: fieldGen.setInitValue(currentSerialVersionUID);
3357: makeSynthetic(fieldGen);
3358: classGen.addField(fieldGen.getField());
3359:
3360: if (javaVersion >= JAVA_1_4) {
3361: /**
3362: * todo add serialVersionUID static constructor to for jdk 1.4
3363: */
3364: }
3365: }
3366: }
3367:
3368: /**
3369: * Check if current class has a serialVersionUID.
3370: *
3371: * @return true if it does have a serialVersionUID, else false.
3372: */
3373: private boolean hasSerialVersionUID() {
3374: Field[] fields = classGen.getFields();
3375: for (int i = 0; i < fields.length; i++) {
3376: Field f = fields[i];
3377: if (f.getName().equals("serialVersionUID")) {
3378: return true;
3379: }
3380: }
3381: return false;
3382: }
3383:
3384: /**
3385: * Addes a field jdoPersistenceCapableSuperclass and initializes it to null if there
3386: * is no persistence capable superclass else it initializes it.
3387: *
3388: */
3389: private void addJdoPersistenceCapableSuperclass() {
3390: FieldGen fieldGen = new FieldGen(
3391: Constants.ACC_PRIVATE | Constants.ACC_STATIC,//| NEW Constants.ACC_FINAL,
3392: new ObjectType("java.lang.Class"),
3393: "jdoPersistenceCapableSuperclass", constantPoolGen);
3394: makeSynthetic(fieldGen);
3395: classGen.addField(fieldGen.getField());
3396: Method m = getStaticConstructor();
3397: MethodGen methodGen = new MethodGen(m, classGen.getClassName(),
3398: constantPoolGen);
3399: InstructionList il = methodGen.getInstructionList();
3400: InstructionHandle initialReturnHandle = il.getEnd();
3401: InstructionHandle nopTarget = il.append(new NOP());
3402: if (classInfo.getPersistenceCapableSuperclass() == null) {
3403: il.append(InstructionConstants.ACONST_NULL);
3404: il.append(instructionFactory.createPutStatic(classGen
3405: .getClassName(), "jdoPersistenceCapableSuperclass",
3406: new ObjectType("java.lang.Class")));
3407: } else {
3408:
3409: String className = classInfo
3410: .getPersistenceCapableSuperclass();
3411: String fieldName = getSetClass$Field(className);
3412:
3413: il.append(instructionFactory.createGetStatic(classGen
3414: .getClassName(), fieldName, new ObjectType(
3415: "java.lang.Class")));
3416: IFNONNULL ifNonNull = new IFNONNULL(null);
3417: il.append(ifNonNull);
3418: il.append(new PUSH(constantPoolGen, className));
3419: il.append(instructionFactory.createInvoke(classGen
3420: .getClassName(), "class$", new ObjectType(
3421: "java.lang.Class"), new Type[] { new ObjectType(
3422: "java.lang.String") }, Constants.INVOKESTATIC));
3423: il.append(new DUP());
3424: il.append(instructionFactory.createPutStatic(classGen
3425: .getClassName(), fieldName, new ObjectType(
3426: "java.lang.Class")));
3427: GOTO gotoInst = new GOTO(null);
3428: il.append(gotoInst);
3429: InstructionHandle ifNonNullHandle = il
3430: .append(instructionFactory.createGetStatic(classGen
3431: .getClassName(), fieldName, new ObjectType(
3432: "java.lang.Class")));
3433: ifNonNull.setTarget(ifNonNullHandle);
3434: InstructionHandle gotoHandle = il.append(instructionFactory
3435: .createPutStatic(classGen.getClassName(),
3436: "jdoPersistenceCapableSuperclass",
3437: new ObjectType("java.lang.Class")));
3438: gotoInst.setTarget(gotoHandle);
3439: }
3440: il.append(new RETURN());
3441: try {
3442: il.delete(initialReturnHandle);
3443: } catch (TargetLostException e) {
3444: InstructionHandle[] targets = e.getTargets();
3445: for (int i = 0; i < targets.length; i++) {
3446: InstructionTargeter[] targeters = targets[i]
3447: .getTargeters();
3448: for (int j = 0; j < targeters.length; j++) {
3449: targeters[j].updateTarget(targets[i], nopTarget);
3450: }
3451: }
3452: }
3453: methodGen.removeNOPs();
3454: methodGen.setMaxLocals();
3455: methodGen.setMaxStack();
3456: classGen.replaceMethod(m, methodGen.getMethod());
3457: il.dispose();
3458: }
3459:
3460: /**
3461: * All class variables i.e. String.class has a static variable called
3462: * class$java$lang$String of type java.lang.Class, this method creates it if
3463: * it does not exist.
3464: *
3465: * @param className
3466: * @return String fieldName i.e. class$java$lang$String
3467: */
3468: private String getSetClass$Field(String className) {
3469: String fullClassName = "class." + className;
3470: String fieldName = fullClassName.replace('.', '$');
3471: Field[] fields = classGen.getFields();
3472: for (int i = 0; i < fields.length; i++) {
3473: Field f = fields[i];
3474: if (f.getName().equals(fieldName)) {
3475: return fieldName;
3476: }
3477: }
3478: FieldGen fieldGen = new FieldGen(Constants.ACC_STATIC,
3479: new ObjectType("java.lang.Class"), fieldName,
3480: constantPoolGen);
3481: classGen.addField(fieldGen.getField());
3482: return fieldName;
3483:
3484: }
3485:
3486: /**
3487: * All class variables i.e. String.class has a static variable called
3488: * class$java$lang$String of type java.lang.Class, this method creates it if
3489: * it does not exist.
3490: *
3491: * @param field
3492: * @return String fieldName i.e. class$java$lang$String
3493: */
3494: private String getSetClass$Field(FieldInfo field) {
3495: String fullClassName = null;
3496: if (field.isArray()) {
3497: fullClassName = ("array" + field.getSignature()).replace(
3498: '/', '$');
3499: fullClassName = fullClassName.replace('[', '$');
3500: fullClassName = (fullClassName.replace(';', ' ')).trim();
3501: } else {
3502: fullClassName = "class." + field.getReturnType();
3503: }
3504: String fieldName = fullClassName.replace('.', '$');
3505: Field[] fields = classGen.getFields();
3506: for (int i = 0; i < fields.length; i++) {
3507: Field f = fields[i];
3508: if (f.getName().equals(fieldName)) {
3509: return fieldName;
3510: }
3511: }
3512: FieldGen fieldGen = new FieldGen(Constants.ACC_STATIC,
3513: new ObjectType("java.lang.Class"), fieldName,
3514: constantPoolGen);
3515: makeSynthetic(fieldGen);
3516: classGen.addField(fieldGen.getField());
3517: return fieldName;
3518:
3519: }
3520:
3521: /**
3522: * Check if current class implements PersistenceCapable.
3523: *
3524: * @return true if it does implement PersistenceCapable else false.
3525: */
3526: private boolean implements PC() {
3527: String[] interfaceNames = classGen.getInterfaceNames();
3528: for (int i = 0; i < interfaceNames.length; i++) {
3529: if (interfaceNames[i].equals(PERSISTENCE_CAPABLE)) {
3530: return true;
3531: }
3532: }
3533: return false;
3534: }
3535:
3536: /**
3537: * All class variables i.e. String.class has a static class$ method that check if the class
3538: * exists by doing a class.forname() on the class and throws a NoClassDefFoundError error,
3539: * if the class does not exists
3540: *
3541: */
3542: private void setClass$() {
3543: Method[] methods = classGen.getMethods();
3544: for (int i = 0; i < methods.length; i++) {
3545: Method m = methods[i];
3546:
3547: if (m.getName().equals("class$")
3548: && "(Ljava/lang/String;)Ljava/lang/Class;".equals(m
3549: .getSignature())) {
3550: return;
3551: }
3552: }
3553: // there is no class$ method so make one
3554: InstructionList il = new InstructionList();
3555: MethodGen methodGen = new MethodGen(Constants.ACC_STATIC,
3556: new ObjectType("java.lang.Class"),
3557: new Type[] { new ObjectType("java.lang.String") },
3558: new String[] { "x0" }, "class$", classGen
3559: .getClassName(), il, constantPoolGen);
3560:
3561: InstructionHandle tryStart = il.append(new ALOAD(0));
3562: il.append(instructionFactory.createInvoke("java.lang.Class",
3563: "forName", new ObjectType("java.lang.Class"),
3564: new Type[] { new ObjectType("java.lang.String") },
3565: Constants.INVOKESTATIC));
3566: InstructionHandle tryEnd = il.append(new ARETURN());
3567: InstructionHandle handler = il.append(new ASTORE(1));
3568: InstructionHandle varStart = il.append(instructionFactory
3569: .createNew("java.lang.NoClassDefFoundError"));
3570: il.append(new DUP());
3571: il.append(new ALOAD(1));
3572: il.append(instructionFactory.createInvoke(
3573: "java.lang.Throwable", "getMessage", new ObjectType(
3574: "java.lang.String"), new Type[] {},
3575: Constants.INVOKEVIRTUAL));
3576: il.append(instructionFactory.createInvoke(
3577: "java.lang.NoClassDefFoundError", "<init>", Type.VOID,
3578: new Type[] { new ObjectType("java.lang.String") },
3579: Constants.INVOKESPECIAL));
3580: InstructionHandle varEnd = il.append(new ATHROW());
3581: methodGen.addLocalVariable("x1", new ObjectType(
3582: "java.lang.ClassNotFoundException"), varStart, varEnd);
3583: methodGen.addExceptionHandler(tryStart, tryEnd, handler,
3584: new ObjectType("java.lang.ClassNotFoundException"));
3585: makeSynthetic(methodGen);
3586: methodGen.setMaxLocals();
3587: methodGen.setMaxStack();
3588: Method class$Method = methodGen.getMethod();
3589: classGen.addMethod(class$Method);
3590: il.dispose();
3591: return;
3592:
3593: }
3594:
3595: private void rewriteStaticConstructor() {
3596: Method[] methods = classGen.getMethods();
3597: for (int k = 0; k < methods.length; k++) {
3598: Method m = methods[k];
3599: // native and abstract methods don't have any code
3600: // so continue with next method
3601: if (m.isNative() || m.isAbstract()) {
3602: continue;
3603: }
3604: if (m.getName().equals("<clinit>")) {//is static constructor
3605: boolean hasChanges = false;
3606: MethodGen mg = new MethodGen(m,
3607: classGen.getClassName(), constantPoolGen);
3608:
3609: // get the code in form of an InstructionList object
3610: InstructionList il = mg.getInstructionList();
3611: Instruction ins;
3612: InstructionHandle ih = il.getStart();
3613: while (ih != null) {
3614: ins = ih.getInstruction();
3615: if (ins instanceof LDC) {
3616: LDC ldc = (LDC) ins;
3617: Constant c = constantPoolGen.getConstantPool()
3618: .getConstant(ldc.getIndex());
3619: if (c.getTag() == Constants.CONSTANT_Class) {
3620: hasChanges = true;
3621: String name = constantPoolGen
3622: .getConstantPool()
3623: .getConstantString(ldc.getIndex(),
3624: Constants.CONSTANT_Class);
3625:
3626: if (!name.startsWith("[")) {
3627: name = "L" + name + ";";
3628: }
3629:
3630: Type type = Type.getType(name);
3631: InstructionList tempIl = pushDotClass(type);
3632: InstructionHandle startTarget = tempIl
3633: .getStart();
3634: InstructionHandle newTarget = tempIl
3635: .getEnd();
3636: il.append(ih, tempIl);
3637: try {
3638: il.delete(ih);
3639: } catch (TargetLostException e) {
3640: InstructionHandle[] targets = e
3641: .getTargets();
3642: for (int i = 0; i < targets.length; i++) {
3643: InstructionTargeter[] targeters = targets[i]
3644: .getTargeters();
3645: for (int j = 0; j < targeters.length; j++) {
3646: targeters[j].updateTarget(
3647: targets[i], newTarget);
3648: }
3649: }
3650: }
3651: il.setPositions();
3652: il.update();
3653: // Fix line numbers
3654: LineNumberGen[] numbersGen = mg
3655: .getLineNumbers();
3656: if (numbersGen != null) {
3657: for (int i = 0; i < numbersGen.length; i++) {
3658: LineNumberGen lineNumberGen = numbersGen[i];
3659: if (lineNumberGen
3660: .containsTarget(newTarget)) {
3661: lineNumberGen
3662: .setInstruction(startTarget);
3663: }
3664: }
3665: }
3666:
3667: ih = il.getStart();
3668:
3669: }
3670: }
3671: ih = ih.getNext();
3672: }
3673: if (hasChanges) {
3674: il.setPositions();
3675: il.update();
3676: mg.removeNOPs();
3677: mg.setMaxLocals();
3678: mg.setMaxStack();
3679: classGen.replaceMethod(m, mg.getMethod());
3680: }
3681: }
3682: }
3683: }
3684:
3685: /**
3686: * Returns the static constructor if it exists, else it creates it and then
3687: * returns it.
3688: *
3689: */
3690: private Method getStaticConstructor() {
3691: Method[] methods = classGen.getMethods();
3692: for (int i = 0; i < methods.length; i++) {
3693: Method m = methods[i];
3694: // native and abstract methods don't have any code
3695: // so continue with next method
3696: if (m.isNative() || m.isAbstract()) {
3697: continue;
3698: }
3699: if (m.getName().equals("<clinit>")) {//is static constructor
3700: return m;
3701: }
3702: }
3703: // there is no static constructor so make one
3704: InstructionList il = new InstructionList();
3705: MethodGen methodGen = new MethodGen(Constants.ACC_STATIC,
3706: Type.VOID, null, null, "<clinit>", classGen
3707: .getClassName(), il, constantPoolGen);
3708:
3709: il.append(new RETURN());
3710: // makeSynthetic(methodGen);
3711: methodGen.setMaxLocals();
3712: methodGen.setMaxStack();
3713: Method clMethod = methodGen.getMethod();
3714: classGen.addMethod(clMethod);
3715: il.dispose();
3716: return clMethod;
3717:
3718: }
3719:
3720: /**
3721: * Adds field jdoStateManager it does not need to be initializes.
3722: *
3723: */
3724: private void addJdoStateManager() {
3725: //this field only gets added to the least-derived persistence capable class.
3726: if (classInfo.getPersistenceCapableSuperclass() == null) {
3727: FieldGen fieldGen = new FieldGen(Constants.ACC_PROTECTED
3728: | Constants.ACC_TRANSIENT, SM_OBJECT_TYPE,
3729: "jdoStateManager", constantPoolGen);
3730: makeSynthetic(fieldGen);
3731: classGen.addField(fieldGen.getField());
3732: }
3733: }
3734:
3735: /**
3736: * Adds field jdoFlags in the top most persistence capable super class and initializes
3737: * it to javax.jdo.spi.PersistenceCapable.READ_WRITE_OK.
3738: * The initialization needs to occur in all the constructors as it is with all class fields.
3739: *
3740: */
3741: private void addJdoFlags() {
3742: //this field only gets added to the least-derived persistence capable class.
3743: if (classInfo.getPersistenceCapableSuperclass() == null) {
3744: FieldGen fieldGen = new FieldGen(Constants.ACC_PROTECTED
3745: | Constants.ACC_TRANSIENT, Type.BYTE, "jdoFlags",
3746: constantPoolGen);
3747: makeSynthetic(fieldGen);
3748: classGen.addField(fieldGen.getField());
3749: List constructors = getInitilizationConstructors();//very important to only get these constructors
3750: Iterator iter = constructors.iterator();
3751: while (iter.hasNext()) {
3752: Method constructor = (Method) iter.next();
3753: MethodGen mg = new MethodGen(constructor, classInfo
3754: .getClassName(), constantPoolGen);
3755:
3756: InstructionList il = mg.getInstructionList();
3757: // get the first instruction
3758: InstructionHandle ih = il.getStart();
3759: while (ih != null) {
3760: Instruction ins = ih.getInstruction();
3761:
3762: if (ins instanceof INVOKESPECIAL) {// found the INVOKESPECIAL call
3763: InstructionList tmpIl = new InstructionList();
3764: tmpIl.append(new ALOAD(0));
3765: tmpIl.append(new ICONST(0));//javax.jdo.spi.PersistenceCapable.READ_WRITE_OK
3766: tmpIl.append(instructionFactory.createPutField(
3767: classInfo.getClassName(), "jdoFlags",
3768: Type.BYTE));
3769: il.append(ih, tmpIl);
3770: il.setPositions();
3771: il.update();
3772:
3773: mg.setInstructionList(il);
3774: mg.setMaxLocals();
3775: mg.setMaxStack();
3776: classGen.replaceMethod(constructor, mg
3777: .getMethod());
3778: il.dispose();
3779: break;
3780: }
3781: // next instruction
3782: ih = ih.getNext();
3783: }
3784: }
3785: }
3786: }
3787:
3788: /**
3789: * Gets a list of all the constructors methods
3790: */
3791: private List getConstructors() {
3792: ArrayList constuctors = new ArrayList();
3793: Method[] methods = classGen.getMethods();
3794: for (int i = 0; i < methods.length; i++) {
3795: Method m = methods[i];
3796: // native and abstract methods don't have any code
3797: // so continue with next method
3798: if (m.isNative() || m.isAbstract()) {
3799: continue;
3800: }
3801: if (m.getName().equals("<init>")) {//is constructor
3802: constuctors.add(m);
3803: }
3804: }
3805: return constuctors;
3806: }
3807:
3808: /**
3809: * Sets a default constructor if it needs one or changes the default
3810: * constructor's scope if needed.
3811: */
3812: private void setDefaultConstructor() {
3813: // if (classGen.isAbstract())return;
3814: boolean setDefautConstructor = true;
3815: Method[] methods = classGen.getMethods();
3816: for (int i = 0; i < methods.length; i++) {
3817: Method m = methods[i];
3818: // native and abstract methods don't have any code
3819: // so continue with next method
3820: if (m.isNative() || m.isAbstract()) {
3821: continue;
3822: }
3823:
3824: if (m.getName().equals("<init>")) { //is constructor
3825: if (m.getSignature().equals("()V")) { //is no args constructor
3826: // if (m.isPublic() || m.isProtected()){ //is public or protected
3827: if (m.isPublic()) {
3828: setDefautConstructor = false; //there is a default constructor with the right access
3829: } else { //there is a default constructor but access is wrong
3830: m.isPublic(true);
3831: m.isProtected(false); //change access to protected
3832: m.isPrivate(false); //take away private access
3833: setDefautConstructor = false; //now there is a default constructor with the right access
3834: }
3835: }
3836: }
3837: }
3838: if (setDefautConstructor) {
3839: InstructionList il = new InstructionList();
3840: il.append(InstructionConstants.THIS); // Push `this'
3841: il.append(new INVOKESPECIAL(constantPoolGen.addMethodref(
3842: classGen.getSuperclassName(), "<init>", "()V")));
3843: il.append(InstructionConstants.RETURN);
3844:
3845: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC, // todo this is not to spec it should be protected
3846: Type.VOID, Type.NO_ARGS, null, "<init>", classGen
3847: .getClassName(), il, constantPoolGen);
3848: methodGen.setMaxLocals();
3849: methodGen.setMaxStack();
3850:
3851: classGen.addMethod(methodGen.getMethod());
3852: didWeAddADefaultConstructor = true;
3853: // classGen.addEmptyConstructor(Constants.ACC_PUBLIC);// todo this is not to spec it should be protected
3854: // If initialization of user-declared field are required use this method
3855: //createDefaultInitializationConstructor();
3856: }
3857: }
3858:
3859: /**
3860: * Gets a list of all the initilization constructors methods
3861: */
3862: private List getInitilizationConstructors() {
3863: ArrayList initConst = new ArrayList();
3864: List list = getConstructors();
3865: Iterator iter = list.iterator();
3866: while (iter.hasNext()) {
3867: Method m = (Method) iter.next();
3868:
3869: MethodGen mg = new MethodGen(m, classGen.getClassName(),
3870: constantPoolGen);
3871:
3872: // get the code in form of an InstructionList object
3873: InstructionList il = mg.getInstructionList();
3874:
3875: // get the first instruction
3876: InstructionHandle ih = il.getStart();
3877: while (ih != null) {
3878: Instruction ins = ih.getInstruction();
3879: if (ins.getClass().getName().equals(invokeSpecial)) {
3880: INVOKESPECIAL is = (INVOKESPECIAL) ins;
3881: if (is.getClassName(constantPoolGen).equals(
3882: classGen.getSuperclassName())
3883: && is.getMethodName(constantPoolGen)
3884: .equals("<init>")) {
3885: initConst.add(m);
3886: }
3887: }
3888: // next instruction
3889: ih = ih.getNext();
3890: }
3891: }
3892: return initConst;
3893: }
3894:
3895: /**
3896: * this method is not needed yet.
3897: */
3898: // private void createDefaultInitializationConstructor(){
3899: // List constructors = getInitilizationConstructors();
3900: // Iterator iter = constructors.iterator();
3901: // boolean wasGen = false;
3902: // while (iter.hasNext()){
3903: // Method m = (Method)iter.next();
3904: // MethodGen mg = new MethodGen(m, classInfo.getClassName() ,constantPoolGen);
3905: // LineNumberGen[] lineNumberGen = mg.getLineNumbers();
3906: // int firstLine = 0;
3907: // int nextLine = 10000;
3908: // int nextOffSet = 0;
3909: // InstructionHandle fromIH = null;
3910: // for (int i = 0; i < lineNumberGen.length ; i++){
3911: // int sourceLine = lineNumberGen[i].getSourceLine();
3912: // if (lineNumberGen[i].getLineNumber().getStartPC() == 0){
3913: // firstLine = lineNumberGen[i].getSourceLine();
3914: // }
3915: //
3916: // if (sourceLine > firstLine && sourceLine < nextLine){
3917: // if (lineNumberGen[i].getInstruction().getInstruction() instanceof RETURN) {
3918: // } else {
3919: // fromIH = lineNumberGen[i].getInstruction();
3920: // nextLine = sourceLine;
3921: // nextOffSet = lineNumberGen[i].getLineNumber().getStartPC();
3922: // }
3923: // }
3924: // }
3925: //
3926: // if (nextOffSet > 5){
3927: // InstructionList il = mg.getInstructionList();
3928: // InstructionHandle toIH = il.getEnd().getPrev();
3929: // try{
3930: // if (!fromIH.equals(il.getEnd().getPrev())){
3931: // il.delete(fromIH,il.getEnd().getPrev());
3932: // }
3933: // } catch (TargetLostException e){
3934: // InstructionHandle[] targets = e.getTargets();
3935: // for (int i = 0; i < targets.length ; i++){
3936: // InstructionTargeter[] targeters = targets[i].getTargeters();
3937: // for (int j = 0; j < targeters.length ; j++){
3938: // targeters[j].updateTarget(targets[i], il.getEnd());
3939: // }
3940: // }
3941: // }
3942: //
3943: // MethodGen newCons = new MethodGen( Constants.ACC_PROTECTED,
3944: // Type.VOID,
3945: // new Type[]{},
3946: // null,
3947: // "<init>",
3948: // classInfo.getClassName(),
3949: // il,
3950: // constantPoolGen);
3951: // newCons.getMaxLocals();
3952: // newCons.getMaxStack();
3953: // classGen.addMethod(newCons.getMethod());
3954: // wasGen = true;
3955: // break;
3956: // }
3957: // }
3958: // if (!wasGen){
3959: // classGen.addEmptyConstructor(Constants.ACC_PROTECTED);
3960: // }
3961: // }
3962:
3963: /**
3964: * All class variables i.e. String.class has a static variable called
3965: * class$java$lang$String of type java.lang.Class, this method creates it if
3966: * it does not exist.
3967: *
3968: * @param type
3969: * @return String fieldName i.e. class$java$lang$String
3970: */
3971: private InstructionList pushDotClass(Type type) {
3972: InstructionList il = new InstructionList();
3973: String signature = type.getSignature();
3974: String fieldName = null;
3975: String tempFieldName = null;
3976: String loadName = null;
3977:
3978: if (signature.startsWith("[")) {
3979: tempFieldName = ("array" + signature).replace('/', '$');
3980: tempFieldName = tempFieldName.replace('[', '$');
3981: fieldName = (tempFieldName.replace(';', ' ')).trim();
3982: loadName = signature.replace('/', '.');
3983: } else {
3984: tempFieldName = ("class/" + signature).replace('/', '$');
3985: fieldName = (tempFieldName.replace(';', ' ')).trim();
3986: loadName = type.toString();
3987: }
3988:
3989: il.append(instructionFactory.createGetStatic(classGen
3990: .getClassName(), fieldName, new ObjectType(
3991: "java.lang.Class")));
3992: IFNONNULL ifnonnull = new IFNONNULL(null);
3993: il.append(ifnonnull);
3994: il.append(new PUSH(constantPoolGen, loadName));
3995: il.append(instructionFactory.createInvoke(classGen
3996: .getClassName(), "class$", new ObjectType(
3997: "java.lang.Class"), new Type[] { Type.STRING },
3998: Constants.INVOKESTATIC));
3999: il.append(new DUP());
4000: il.append(instructionFactory.createPutStatic(classGen
4001: .getClassName(), fieldName, new ObjectType(
4002: "java.lang.Class")));
4003: GOTO aGoto = new GOTO(null);
4004: il.append(aGoto);
4005: InstructionHandle getStaticHandle = il
4006: .append(instructionFactory.createGetStatic(classGen
4007: .getClassName(), fieldName, new ObjectType(
4008: "java.lang.Class")));
4009: ifnonnull.setTarget(getStaticHandle);
4010: InstructionHandle lastHandle = il.append(new NOP());
4011: aGoto.setTarget(lastHandle);
4012:
4013: setClass$();
4014: Field[] fields = classGen.getFields();
4015: for (int i = 0; i < fields.length; i++) {
4016: Field f = fields[i];
4017: if (f.getName().equals(fieldName)) {
4018: return il;
4019: }
4020: }
4021: FieldGen fieldGen = new FieldGen(Constants.ACC_STATIC
4022: | Constants.ACC_PRIVATE, new ObjectType(
4023: "java.lang.Class"), fieldName, constantPoolGen);
4024: classGen.addField(fieldGen.getField());
4025: return il;
4026:
4027: }
4028:
4029: /**
4030: * Compute the JVM signature for the class.
4031: */
4032: static String getSignature(Class clazz) {
4033: String type = null;
4034: if (clazz.isArray()) {
4035: Class cl = clazz;
4036: int dimensions = 0;
4037: while (cl.isArray()) {
4038: dimensions++;
4039: cl = cl.getComponentType();
4040: }
4041: StringBuffer sb = new StringBuffer();
4042: for (int i = 0; i < dimensions; i++) {
4043: sb.append("[");
4044: }
4045: sb.append(getSignature(cl));
4046: type = sb.toString();
4047: } else if (clazz.isPrimitive()) {
4048: if (clazz == Integer.TYPE) {
4049: type = "I";
4050: } else if (clazz == Byte.TYPE) {
4051: type = "B";
4052: } else if (clazz == Long.TYPE) {
4053: type = "J";
4054: } else if (clazz == Float.TYPE) {
4055: type = "F";
4056: } else if (clazz == Double.TYPE) {
4057: type = "D";
4058: } else if (clazz == Short.TYPE) {
4059: type = "S";
4060: } else if (clazz == Character.TYPE) {
4061: type = "C";
4062: } else if (clazz == Boolean.TYPE) {
4063: type = "Z";
4064: } else if (clazz == Void.TYPE) {
4065: type = "V";
4066: }
4067: } else {
4068: type = "L" + clazz.getName().replace('.', '/') + ";";
4069: }
4070: return type;
4071: }
4072:
4073: // all the detach suff goes here
4074:
4075: private void addIsDirtyInt(String methodName) {
4076:
4077: InstructionList il = new InstructionList();
4078: MethodGen methodGen = new MethodGen(
4079: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4080: Type.BOOLEAN, new Type[] { Type.INT },
4081: new String[] { "fieldNo" }, methodName, classGen
4082: .getClassName(), il, constantPoolGen);
4083:
4084: int num = getNumOfControlFields();
4085: if (num == 1) {
4086: il.append(new ALOAD(0));
4087: il.append(instructionFactory.createGetField(classGen
4088: .getClassName(), getDirtyFieldName(0), Type.INT));
4089: il.append(new ICONST(1));
4090: il.append(new ILOAD(1));
4091: il.append(new ISHL());
4092: il.append(new IAND());
4093: IFNE ifne = new IFNE(null);
4094: il.append(ifne);
4095: il.append(new ICONST(0));
4096: il.append(new IRETURN());
4097: InstructionHandle handle = il.append(new ICONST(1));
4098: ifne.setTarget(handle);
4099: il.append(new IRETURN());
4100:
4101: } else {
4102: il.append(new ILOAD(1));
4103: for (int i = 0; i < num; i++) {
4104: il.append(new PUSH(constantPoolGen, ((32 * i) + 32)));
4105: IF_ICMPGE if_icmpge = new IF_ICMPGE(null);
4106: il.append(if_icmpge);
4107: il.append(new ALOAD(0));
4108: il.append(instructionFactory
4109: .createGetField(classGen.getClassName(),
4110: getDirtyFieldName(i), Type.INT));
4111: il.append(new ICONST(1));
4112: il.append(new ILOAD(1));
4113: il.append(new ISHL());
4114: il.append(new IAND());
4115: IFEQ ifeq = new IFEQ(null);
4116: il.append(ifeq);
4117: il.append(new ICONST(1));
4118: GOTO aGoto = new GOTO(null);
4119: il.append(aGoto);
4120: InstructionHandle iconst0Handle = il.append(new ICONST(
4121: 0));
4122: ifeq.setTarget(iconst0Handle);
4123: InstructionHandle gotoHandle = il.append(new IRETURN());
4124: aGoto.setTarget(gotoHandle);
4125: InstructionHandle iload1Handle = il
4126: .append(new ILOAD(1));
4127: if_icmpge.setTarget(iload1Handle);
4128: }
4129: // take last one and replace with ICONST_0
4130: InstructionHandle lastHandle = il.getEnd();
4131: InstructionHandle replaceHandle = il.append(new ICONST(0));
4132: try {
4133: il.delete(lastHandle);
4134: } catch (TargetLostException e) {
4135: InstructionHandle[] targets = e.getTargets();
4136: for (int i = 0; i < targets.length; i++) {
4137: InstructionTargeter[] targeters = targets[i]
4138: .getTargeters();
4139: for (int j = 0; j < targeters.length; j++) {
4140: targeters[j].updateTarget(targets[i],
4141: replaceHandle);
4142: }
4143: }
4144: }
4145: il.append(new IRETURN());
4146: }
4147:
4148: methodGen.setMaxLocals();
4149: methodGen.setMaxStack();
4150: classGen.addMethod(methodGen.getMethod());
4151: il.dispose();
4152: }
4153:
4154: private void addMakeDirtyInt(String methodName) {
4155:
4156: InstructionList il = new InstructionList();
4157: MethodGen methodGen = new MethodGen(
4158: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4159: Type.VOID, new Type[] { Type.INT },
4160: new String[] { "fieldNo" }, methodName, classGen
4161: .getClassName(), il, constantPoolGen);
4162:
4163: int num = getNumOfControlFields();
4164: if (num == 1) {
4165: il.append(new ALOAD(0));
4166: il.append(new DUP());
4167: il.append(instructionFactory.createGetField(classGen
4168: .getClassName(), getDirtyFieldName(0), Type.INT));
4169:
4170: il.append(new ICONST(1));
4171: il.append(new ILOAD(1));
4172: il.append(new ISHL());
4173: il.append(new IOR());
4174: il.append(instructionFactory.createPutField(classGen
4175: .getClassName(), getDirtyFieldName(0), Type.INT));
4176: il.append(new RETURN());
4177: } else {
4178: il.append(new ILOAD(1));
4179: for (int i = 0; i < num; i++) {
4180: il.append(new PUSH(constantPoolGen, ((32 * i) + 32)));
4181: IF_ICMPGE if_icmpge = new IF_ICMPGE(null);
4182: il.append(if_icmpge);
4183:
4184: il.append(new ALOAD(0));
4185: il.append(new DUP());
4186: il.append(instructionFactory
4187: .createGetField(classGen.getClassName(),
4188: getDirtyFieldName(i), Type.INT));
4189: il.append(new ICONST(1));
4190: il.append(new ILOAD(1));
4191: il.append(new ISHL());
4192: il.append(new IOR());
4193: il.append(instructionFactory
4194: .createPutField(classGen.getClassName(),
4195: getDirtyFieldName(i), Type.INT));
4196: if (i != (num - 1)) {
4197: il.append(new RETURN());
4198: InstructionHandle iloadHandle = il
4199: .append(new ILOAD(1));
4200: if_icmpge.setTarget(iloadHandle);
4201: } else {
4202: InstructionHandle returnHandle = il
4203: .append(new RETURN()); // last return
4204: if_icmpge.setTarget(returnHandle);
4205: }
4206: }
4207:
4208: }
4209: methodGen.setMaxLocals();
4210: methodGen.setMaxStack();
4211: classGen.addMethod(methodGen.getMethod());
4212: il.dispose();
4213: }
4214:
4215: private void addMakeDirtyString(String methodName) {
4216:
4217: InstructionList il = new InstructionList();
4218: MethodGen methodGen = new MethodGen(Constants.ACC_PUBLIC,
4219: Type.VOID, new Type[] { Type.STRING },
4220: new String[] { "fieldName" }, methodName, classGen
4221: .getClassName(), il, constantPoolGen);
4222:
4223: ArrayList list = new ArrayList(fieldSet);
4224: Collections.sort(list);
4225: Iterator iter = list.iterator();
4226: ArrayList gotos = new ArrayList();
4227:
4228: while (iter.hasNext()) {
4229: FieldInfo info = (FieldInfo) iter.next();
4230: String fieldname = info.getFieldName();
4231: int fieldNo = info.getFieldNo();
4232:
4233: il.append(new PUSH(constantPoolGen, fieldname));
4234: il.append(new ALOAD(1));
4235: il.append(instructionFactory
4236: .createInvoke("java.lang.String", "equals",
4237: Type.BOOLEAN, new Type[] { Type.OBJECT },
4238: Constants.INVOKEVIRTUAL));
4239: IFEQ ifeq = new IFEQ(null); //17
4240: il.append(ifeq);
4241: il.append(new ALOAD(0));
4242: il.append(new PUSH(constantPoolGen, fieldNo));
4243: il.append(instructionFactory.createInvoke(classGen
4244: .getClassName(), "versantMakeDirty", Type.VOID,
4245: new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
4246: GOTO aGoto = new GOTO(null);
4247: gotos.add(aGoto);
4248: il.append(aGoto);
4249: InstructionHandle nopHandle = il.append(new NOP());
4250: ifeq.setTarget(nopHandle);
4251: }
4252: // now we do the else part
4253: if (classInfo.getPersistenceCapableSuperclass() != null) {
4254: il.append(new ALOAD(0));
4255: il.append(new ALOAD(1));
4256: il.append(instructionFactory
4257: .createInvoke(classInfo
4258: .getPersistenceCapableSuperclass(),
4259: "versantMakeDirty", Type.VOID,
4260: new Type[] { Type.STRING },
4261: Constants.INVOKESPECIAL));
4262: } else {
4263: // todo throw exception or something
4264: }
4265:
4266: InstructionHandle lastHandle = il.append(new RETURN());
4267: for (Iterator iterator = gotos.iterator(); iterator.hasNext();) {
4268: GOTO aGoto = (GOTO) iterator.next();
4269: aGoto.setTarget(lastHandle);
4270: }
4271: methodGen.removeNOPs();
4272: methodGen.setMaxLocals();
4273: methodGen.setMaxStack();
4274: classGen.addMethod(methodGen.getMethod());
4275: il.dispose();
4276: }
4277:
4278: private void addIsDirty(String methodName) {
4279:
4280: InstructionList il = new InstructionList();
4281: MethodGen methodGen = new MethodGen(
4282: Constants.ACC_PUBLIC, //| NEW Constants.ACC_FINAL,
4283: Type.BOOLEAN, new Type[] {}, new String[] {},
4284: methodName, classGen.getClassName(), il,
4285: constantPoolGen);
4286:
4287: ArrayList list = new ArrayList();
4288: int num = getNumOfControlFields();
4289: for (int i = 0; i < num; i++) {
4290: il.append(new ALOAD(0));
4291: il.append(instructionFactory.createGetField(classGen
4292: .getClassName(), getDirtyFieldName(i), Type.INT));
4293: IFNE ifne = new IFNE(null);
4294: list.add(ifne);
4295: il.append(ifne);
4296: }
4297: il.append(new ICONST(0));
4298: il.append(new IRETURN());
4299: InstructionHandle ifne_handle = il.append(new ICONST(1));
4300: for (Iterator iter = list.iterator(); iter.hasNext();) {
4301: IFNE ifne = (IFNE) iter.next();
4302: ifne.setTarget(ifne_handle);
4303: }
4304: il.append(new IRETURN());
4305:
4306: methodGen.setMaxLocals();
4307: methodGen.setMaxStack();
4308: classGen.addMethod(methodGen.getMethod());
4309: il.dispose();
4310: }
4311:
4312: private void addIsLoadedInt(String methodName) {
4313:
4314: InstructionList il = new InstructionList();
4315: MethodGen methodGen = new MethodGen(
4316: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4317: Type.BOOLEAN, new Type[] { Type.INT },
4318: new String[] { "fieldNo" }, methodName, classGen
4319: .getClassName(), il, constantPoolGen);
4320:
4321: int num = getNumOfControlFields();
4322: if (num == 1) {
4323: il.append(new ALOAD(0));
4324: il.append(instructionFactory.createGetField(classGen
4325: .getClassName(), getLoadedFieldName(0), Type.INT));
4326: il.append(new ICONST(1));
4327: il.append(new ILOAD(1));
4328: il.append(new ISHL());
4329: il.append(new IAND());
4330: IFNE ifne = new IFNE(null);
4331: il.append(ifne);
4332: il.append(new ICONST(0));
4333: il.append(new IRETURN());
4334: InstructionHandle handle = il.append(new ICONST(1));
4335: ifne.setTarget(handle);
4336: il.append(new IRETURN());
4337:
4338: } else {
4339: il.append(new ILOAD(1));
4340: for (int i = 0; i < num; i++) {
4341: il.append(new PUSH(constantPoolGen, ((32 * i) + 32)));
4342: IF_ICMPGE if_icmpge = new IF_ICMPGE(null);
4343: il.append(if_icmpge);
4344: il.append(new ALOAD(0));
4345: il.append(instructionFactory.createGetField(classGen
4346: .getClassName(), getLoadedFieldName(i),
4347: Type.INT));
4348: il.append(new ICONST(1));
4349: il.append(new ILOAD(1));
4350: il.append(new ISHL());
4351: il.append(new IAND());
4352: IFEQ ifeq = new IFEQ(null);
4353: il.append(ifeq);
4354: il.append(new ICONST(1));
4355: GOTO aGoto = new GOTO(null);
4356: il.append(aGoto);
4357: InstructionHandle iconst0Handle = il.append(new ICONST(
4358: 0));
4359: ifeq.setTarget(iconst0Handle);
4360: InstructionHandle gotoHandle = il.append(new IRETURN());
4361: aGoto.setTarget(gotoHandle);
4362: InstructionHandle iload1Handle = il
4363: .append(new ILOAD(1));
4364: if_icmpge.setTarget(iload1Handle);
4365: }
4366: // take last one and replace with ICONST_0
4367: InstructionHandle lastHandle = il.getEnd();
4368: InstructionHandle replaceHandle = il.append(new ICONST(0));
4369: try {
4370: il.delete(lastHandle);
4371: } catch (TargetLostException e) {
4372: InstructionHandle[] targets = e.getTargets();
4373: for (int i = 0; i < targets.length; i++) {
4374: InstructionTargeter[] targeters = targets[i]
4375: .getTargeters();
4376: for (int j = 0; j < targeters.length; j++) {
4377: targeters[j].updateTarget(targets[i],
4378: replaceHandle);
4379: }
4380: }
4381: }
4382: il.append(new IRETURN());
4383: }
4384:
4385: methodGen.setMaxLocals();
4386: methodGen.setMaxStack();
4387: classGen.addMethod(methodGen.getMethod());
4388: il.dispose();
4389: }
4390:
4391: private void addSetLoadedInt(String methodName) {
4392:
4393: InstructionList il = new InstructionList();
4394: MethodGen methodGen = new MethodGen(
4395: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4396: Type.VOID, new Type[] { Type.INT },
4397: new String[] { "fieldNo" }, methodName, classGen
4398: .getClassName(), il, constantPoolGen);
4399:
4400: int num = getNumOfControlFields();
4401: if (num == 1) {
4402: il.append(new ALOAD(0));
4403: il.append(new DUP());
4404: il.append(instructionFactory.createGetField(classGen
4405: .getClassName(), getLoadedFieldName(0), Type.INT));
4406:
4407: il.append(new ICONST(1));
4408: il.append(new ILOAD(1));
4409: il.append(new ISHL());
4410: il.append(new IOR());
4411: il.append(instructionFactory.createPutField(classGen
4412: .getClassName(), getLoadedFieldName(0), Type.INT));
4413: il.append(new RETURN());
4414: } else {
4415: il.append(new ILOAD(1));
4416: for (int i = 0; i < num; i++) {
4417: il.append(new PUSH(constantPoolGen, ((32 * i) + 32)));
4418: IF_ICMPGE if_icmpge = new IF_ICMPGE(null);
4419: il.append(if_icmpge);
4420:
4421: il.append(new ALOAD(0));
4422: il.append(new DUP());
4423: il.append(instructionFactory.createGetField(classGen
4424: .getClassName(), getLoadedFieldName(i),
4425: Type.INT));
4426: il.append(new ICONST(1));
4427: il.append(new ILOAD(1));
4428: il.append(new ISHL());
4429: il.append(new IOR());
4430: il.append(instructionFactory.createPutField(classGen
4431: .getClassName(), getLoadedFieldName(i),
4432: Type.INT));
4433: if (i != (num - 1)) {
4434: il.append(new RETURN());
4435: InstructionHandle iloadHandle = il
4436: .append(new ILOAD(1));
4437: if_icmpge.setTarget(iloadHandle);
4438: } else {
4439: InstructionHandle returnHandle = il
4440: .append(new RETURN()); // last return
4441: if_icmpge.setTarget(returnHandle);
4442: }
4443: }
4444:
4445: }
4446: methodGen.setMaxLocals();
4447: methodGen.setMaxStack();
4448: classGen.addMethod(methodGen.getMethod());
4449: il.dispose();
4450: }
4451:
4452: private final int getNumOfControlFields() {
4453: return (totlalManagedFields / 32) + 1;
4454: }
4455:
4456: private final String getDirtyFieldName(int index) {
4457: return DIRTY_FIELD_NAME + index;
4458: }
4459:
4460: private final String getLoadedFieldName(int index) {
4461: return LOADED_FIELD_NAME + index;
4462: }
4463:
4464: private void addFields() {
4465: int num = getNumOfControlFields();
4466: for (int i = 0; i < num; i++) {
4467: FieldGen fieldGenFilled = new FieldGen(// Added our int LOADED_FIELD_NAME , to see what has been loaded in
4468: Constants.ACC_PRIVATE, Type.INT, LOADED_FIELD_NAME
4469: + i, constantPoolGen);
4470: makeSynthetic(fieldGenFilled);
4471: classGen.addField(fieldGenFilled.getField());
4472:
4473: FieldGen fieldGenDirtyFields = new FieldGen(// Added our int DIRTY_FIELD_NAME , to see what is dirty
4474: Constants.ACC_PRIVATE, Type.INT, DIRTY_FIELD_NAME
4475: + i, constantPoolGen);
4476: makeSynthetic(fieldGenDirtyFields);
4477: classGen.addField(fieldGenDirtyFields.getField());
4478:
4479: }
4480:
4481: FieldGen fieldGenVersionField = new FieldGen(
4482: // Added our Version field
4483: Constants.ACC_PRIVATE, Type.OBJECT, VERSION_FIELD_NAME,
4484: constantPoolGen);
4485: makeSynthetic(fieldGenVersionField);
4486: classGen.addField(fieldGenVersionField.getField());
4487:
4488: FieldGen fieldGenOIDField = new FieldGen(
4489: // Added our OID field
4490: Constants.ACC_PRIVATE, Type.OBJECT, OID_FIELD_NAME,
4491: constantPoolGen);
4492: makeSynthetic(fieldGenOIDField);
4493: classGen.addField(fieldGenOIDField.getField());
4494: }
4495:
4496: private void addGetOid(String methodName) {
4497: InstructionList il = new InstructionList();
4498: MethodGen methodGen = new MethodGen(
4499: Constants.ACC_PUBLIC,// | NEW Constants.ACC_FINAL,
4500: Type.OBJECT, new Type[] {}, new String[] {},
4501: methodName, classGen.getClassName(), il,
4502: constantPoolGen);
4503:
4504: il.append(new ALOAD(0));
4505: il.append(instructionFactory.createGetField(classGen
4506: .getClassName(), OID_FIELD_NAME, Type.OBJECT));
4507: il.append(new ARETURN());
4508:
4509: methodGen.setMaxLocals();
4510: methodGen.setMaxStack();
4511: classGen.addMethod(methodGen.getMethod());
4512: il.dispose();
4513:
4514: }
4515:
4516: private void addSetOid(String methodName) {
4517: InstructionList il = new InstructionList();
4518: MethodGen methodGen = new MethodGen(
4519: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4520: Type.VOID, new Type[] { Type.OBJECT },
4521: new String[] { "oid" }, methodName, classGen
4522: .getClassName(), il, constantPoolGen);
4523:
4524: il.append(new ALOAD(0));
4525: il.append(new ALOAD(1));
4526: il.append(instructionFactory.createPutField(classGen
4527: .getClassName(), OID_FIELD_NAME, Type.OBJECT));
4528: il.append(new RETURN());
4529:
4530: methodGen.setMaxLocals();
4531: methodGen.setMaxStack();
4532: classGen.addMethod(methodGen.getMethod());
4533: il.dispose();
4534: }
4535:
4536: private void addGetVersion(String methodName) {
4537: InstructionList il = new InstructionList();
4538: MethodGen methodGen = new MethodGen(
4539: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4540: Type.OBJECT, new Type[] {}, new String[] {},
4541: methodName, classGen.getClassName(), il,
4542: constantPoolGen);
4543:
4544: il.append(new ALOAD(0));
4545: il.append(instructionFactory.createGetField(classGen
4546: .getClassName(), VERSION_FIELD_NAME, Type.OBJECT));
4547: il.append(new ARETURN());
4548:
4549: methodGen.setMaxLocals();
4550: methodGen.setMaxStack();
4551: classGen.addMethod(methodGen.getMethod());
4552: il.dispose();
4553:
4554: }
4555:
4556: private void addGetStateManager(String methodName) {
4557: InstructionList il = new InstructionList();
4558: MethodGen methodGen = new MethodGen(
4559: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4560: new ObjectType(DETACHED_STATE_MANAGER), new Type[] {},
4561: new String[] {}, methodName, classGen.getClassName(),
4562: il, constantPoolGen);
4563:
4564: il.append(new ALOAD(0));
4565: il.append(instructionFactory.createGetField(classGen
4566: .getClassName(), "jdoStateManager", new ObjectType(
4567: STATE_MANAGER)));
4568: il.append(new INSTANCEOF(constantPoolGen
4569: .addClass(DETACHED_STATE_MANAGER)));
4570: IFEQ ifeq = new IFEQ(null);
4571: il.append(ifeq);
4572: il.append(new ALOAD(0));
4573: il.append(instructionFactory.createGetField(classGen
4574: .getClassName(), "jdoStateManager", new ObjectType(
4575: STATE_MANAGER)));
4576: il.append(instructionFactory.createCheckCast(new ObjectType(
4577: DETACHED_STATE_MANAGER)));
4578: il.append(new ARETURN());
4579: InstructionHandle nullHandle = il.append(new ACONST_NULL());
4580: ifeq.setTarget(nullHandle);
4581: il.append(new ARETURN());
4582:
4583: methodGen.setMaxLocals();
4584: methodGen.setMaxStack();
4585: classGen.addMethod(methodGen.getMethod());
4586: il.dispose();
4587:
4588: }
4589:
4590: private void addSetVersion(String methodName) {
4591: InstructionList il = new InstructionList();
4592: MethodGen methodGen = new MethodGen(
4593: Constants.ACC_PUBLIC,//| NEW Constants.ACC_FINAL,
4594: Type.VOID, new Type[] { Type.OBJECT },
4595: new String[] { "version" }, methodName, classGen
4596: .getClassName(), il, constantPoolGen);
4597:
4598: il.append(new ALOAD(0));
4599: il.append(new ALOAD(1));
4600: il.append(instructionFactory.createPutField(classGen
4601: .getClassName(), VERSION_FIELD_NAME, Type.OBJECT));
4602: il.append(new RETURN());
4603:
4604: methodGen.setMaxLocals();
4605: methodGen.setMaxStack();
4606: classGen.addMethod(methodGen.getMethod());
4607: il.dispose();
4608: }
4609:
4610: private void addDetachInterfase() {
4611: classGen.addInterface(DETACHABLE_INTERFASE);
4612: }
4613: }
|