alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (MethodBuilder.java)

This example Glassfish source code file (MethodBuilder.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

attributevector, attributevector, classaction, classmethod, classmethod, constantpool, constclass, exceptiontable, insntarget, insntarget, noi18n, noi18n, string, syntheticattribute, util

The Glassfish MethodBuilder.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.jdo.api.persistence.enhancer.impl;

import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Enumeration;

import com.sun.jdo.api.persistence.enhancer.classfile.*;

import com.sun.jdo.api.persistence.enhancer.util.Support;
import com.sun.jdo.api.persistence.enhancer.util.InternalError;
import com.sun.jdo.api.persistence.enhancer.util.ClassFileSource;

//@olsen: added import
import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData;


//@olsen: cosmetics
//@olsen: moved: this class -> package impl
//@olsen: subst: (object)state -> flags
//@olsen: subst: JDOflags -> jdoFlags
//@olsen: subst: makeJDO[gs]etFlags -> makeJDO[GS]etFlags
//@olsen: subst: JDO[gs]etFlags -> jdo[GS]etFlags
//@olsen: subst: [Nn]eedsJDORefMethods -> [Nn]eedsJDOStateManagerMethods
//@olsen: subst: JDOref -> jdoStateManager
//@olsen: subst: makeJDO[gs]etRef -> makeJDO[GS]etStateManager
//@olsen: subst: JDO[gs]etRef -> jdo[GS]etStateManager
//@olsen: subst: [iI]Persistent -> [pP]ersistenceCapable
//@olsen: subst: PersistentAux -> StateManager
//@olsen: subst: jdo/ -> com/sun/forte4j/persistence/internal/
//@olsen: subst: jdo. -> com.sun.forte4j.persistence.internal.
//@olsen: subst: /* ... */ -> // ...
//@olsen: added: final modifiers on local variables
//@olsen: subst: FilterEnv -> Environment
//@olsen: made MethodBuilder's methods non-static
//@olsen: dropped parameter 'Environment env', use association instead
//@olsen: subst: Enumeration,... -> Iterator, hasNext(), next()
//@olsen: subst: myMethodName -> methodName
//@olsen: added: support for I18N
//@olsen: subst: FilterError -> UserException, affirm()
//@olsen: removed: proprietary support for ClassInfo
//@olsen: removed: proprietary support for FieldNote
//@olsen: removed: old, disabled ODI code


/**
 * MethodBuilder is a collection of methods which
 * create the persistence methods of a persistent class
 */
class MethodBuilder
    extends Support
    implements VMConstants {

    //@olsen: fix for bug 4467428:
    // Debugging under jdk 1.3.1 shows the problem that any breakpoints
    // in PC classes are ignored if the added jdo methods do NOT have a
    // non-empty line number table attribute, no matter whether the
    // 'Synthetic' attribute is given or not.  However, this doesn't
    // seem to comply with the JVM Spec (2nd edition), which states
    // that the synthetic attribute _must_ be specified if no source
    // code information is available for the member:
    //
    //     4.7.6 The Synthetic Attribute
    //     ... A class member that does not appear in the source code must
    //     be marked using a Synthetic attribute. ...
    //
    //     4.7.8 The LineNumberTable Attribute
    //     The LineNumberTable attribute is an optional variable-length
    //     attribute in the attributes table of a Code (see 4.7.3)
    //     attribute. It may be used by debuggers to determine which
    //     part of the Java virtual machine code array corresponds to a
    //     given line number in the original source file. ... Furthermore,
    //     multiple LineNumberTable attributes may together represent a
    //     given line of a source file; that is, LineNumberTable attributes
    //     need not be one-to-one with source lines.
    //
    // Unfortunately, if we do both, adding the synthetic attribute and
    // a (dummy) line number table on generated methods, jdk's 1.3.1 javap
    // fails to disassemble the classfile with an exception:
    //
    //     sun.tools.java.CompilerError: checkOverride() synthetic
    //
    // So, to workaround these problems and to allow for both, debugging
    // and disassembling with the jdk (1.3.1) tools, we pretend that the
    // generated jdo methods have source code equivalents by
    // - not adding the synthetic code attribute
    // - providing a dummy line number table code attribute
    static private final boolean addSyntheticAttr = false;
    static private final boolean addLineNumberTableAttr = true;

    /* Central repository for the options and classes */
    //@olsen: added association
    //@olsen: made final
    private final Environment env;

    /**
     * Constructor.
     */
    //@olsen: added constructor
    //@olsen: added parameter 'env' for association
    public MethodBuilder(Environment env) {
        this.env = env;
    }

    /**
     * Build a null method named methodName for the class.
     *
     * public void methodName() {
     * }
     */
    //@olsen: moved to beginning of this class
    ClassMethod makeNullMethod(final ClassAction ca,
                               final String methodName) {
        //@olsen: added variable
        final String methodSig = "()V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass thisClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod nullMethod
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              0, // maxStack
                              1, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return nullMethod;
    }

    /**
     * Build the initializeContents method for the class
     */
//@olsen: dropped method
/*
    ClassMethod makeInitializeContents(ClassAction ca) {
        final ConstantPool pool = ca.classFile().pool();
        final ConstClass thisClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        ClassMethod initializeContentsMethod =
            new ClassMethod(ACCPublic,
                            pool.addUtf8("initializeContents"),
                            pool.addUtf8("(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V"),
                            methodAttrs);

        // begin of method body
        Insn begin = new InsnTarget();
        Insn insn = begin;

        // Allocated reg 2 as cached ClassInfo*
        insn = insn.append(
            Insn.create(opc_getstatic,
                        pool.addFieldRef(thisClass.asString(),
                                         ca.getClassInfoMember(),
                                         "Lcom/sun/forte4j/persistence/internal/ClassInfo;")));
        insn = insn.append(Insn.create(opc_astore_2));

        for (Iterator e = ca.fieldActions(); e.hasNext();) {
            FieldAction act = (FieldAction)e.next();
            if (act.isPersistent()) {
                int idx = act.index();
                // get this
                insn = insn.append(Insn.create(opc_aload_0));
                // get GenericObject
                insn = insn.append(Insn.create(opc_aload_1));
                // get field index
                insn = insn.append(InsnUtils.integerConstant(idx, pool));
                // get ClassInfo
                insn = insn.append(Insn.create(opc_aload_2));
                // call the get method
                insn = insn.append(Insn.create(opc_invokevirtual,
                                               pool.addMethodRef("com/sun/forte4j/persistence/internal/ObjectContents",
                                                                 act.getMethod(), act.getMethodSig())));

                switch(act.getMethodReturn()) {
                case T_DOUBLE:
                case T_LONG:
                case T_BOOLEAN:
                case T_CHAR:
                case T_FLOAT:
                case T_BYTE:
                case T_SHORT:
                case T_INT:
                case TC_STRING:
                    // The above types are assumed to be accurate, with no
                    // conversions required
                    break;

                case TC_OBJECT:
                case TC_INTERFACE:
                    if (!act.typeDescriptor().equals("Ljava/lang/Object;")) {
                        ConstClass fieldType = pool.addClass(act.typeName());
                        // Add a cast to the appropriate type
                        insn = insn.append(Insn.create(opc_checkcast, fieldType));
                    }
                    break;
                default:
                    throw new InternalError("Unexpected return type");
                }

                // finally, store the result
                insn = insn.append(Insn.create(opc_putfield,
                                               pool.addFieldRef(thisClass.asString(), act.fieldName(),
                                                                act.typeDescriptor())));
            }
        }

        ConstClass superClass = ca.classFile().superName();
        if (!ca.getImplementsPersistence()) {
            // Need to invoke initializeContents on super
            // get this
            insn = insn.append(Insn.create(opc_aload_0));
            // get generic object
            insn = insn.append(Insn.create(opc_aload_1));
            // do the invoke
            insn = insn.append(Insn.create(opc_invokespecial,
                                           pool.addMethodRef(superClass.asString(),
                                                             "initializeContents", "(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V")));
        }

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              4, // maxStack
                              3, // maxLocals
                              begin,
                              new ExceptionTable(),
                              new AttributeVector()));
        return initializeContentsMethod;
    }
*/

    /**
     * Build the flushContents method for the class
     */
//@olsen: dropped method
/*
    ClassMethod makeFlushContents(ClassAction ca) {
        final ConstantPool pool = ca.classFile().pool();
        final ConstClass thisClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        ClassMethod flushContentsMethod =
            new ClassMethod(ACCPublic,
                            pool.addUtf8("flushContents"),
                            pool.addUtf8("(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V"),
                            methodAttrs);

        // begin of method body
        Insn begin = new InsnTarget();
        Insn insn = begin;

        // Allocated reg 2 as cached ClassInfo*
        insn = insn.append(
            Insn.create(opc_getstatic,
                        pool.addFieldRef(thisClass.asString(),
                                         ca.getClassInfoMember(),
                                         "Lcom/sun/forte4j/persistence/internal/ClassInfo;")));
        insn = insn.append(Insn.create(opc_astore_2));

        for (Iterator e = ca.fieldActions(); e.hasNext();) {
            FieldAction act = (FieldAction)e.next();
            if (act.isPersistent()) {
                int idx = act.index();
                // get GenericObject
                insn = insn.append(Insn.create(opc_aload_1));
                // get field index
                insn = insn.append(InsnUtils.integerConstant(idx, pool));
                // get this
                insn = insn.append(Insn.create(opc_aload_0));
                // get the field value
                insn = insn = insn.append(Insn.create(opc_getfield,
                                                      pool.addFieldRef(thisClass.asString(), act.fieldName(),
                                                                       act.typeDescriptor())));
                // get ClassInfo
                insn = insn.append(Insn.create(opc_aload_2));

                // call the set method
                insn = insn.append(Insn.create(opc_invokevirtual,
                                               pool.addMethodRef("com/sun/forte4j/persistence/internal/ObjectContents",
                                                                 act.setMethod(), act.setMethodSig())));
            }
        }

        ConstClass superClass = ca.classFile().superName();
        if (!ca.getImplementsPersistence()) {
            // Need to invoke flushContents on super
            // get this
            insn = insn.append(Insn.create(opc_aload_0));
            // get generic object
            insn = insn.append(Insn.create(opc_aload_1));
            // do the invoke
            insn = insn.append(Insn.create(opc_invokespecial,
                                           pool.addMethodRef(superClass.asString(),
                                                             "flushContents", "(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V")));
        }

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              6, // maxStack (might actually be 5, but ok)
                              3, // maxLocals
                              begin,
                              new ExceptionTable(),
                              new AttributeVector()));
        return flushContentsMethod;
    }
*/

    /**
     * Build the clearContents method for the class
     */
//@olsen: dropped method
/*
    ClassMethod makeClearContents(ClassAction ca) {
        final ConstantPool pool = ca.classFile().pool();
        final ConstClass thisClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        ClassMethod clearContentsMethod =
            new ClassMethod(ACCPublic,
                            pool.addUtf8("clearContents"),
                            pool.addUtf8("()V"),
                            methodAttrs);

        // begin of method body
        Insn begin = new InsnTarget();
        Insn insn = begin;

        for (Iterator e = ca.fieldActions(); e.hasNext();) {
            FieldAction act = (FieldAction)e.next();
            if (act.isPersistent()) {
                int idx = act.index();
                // get this
                insn = insn.append(Insn.create(opc_aload_0));

                // Use the getMethodReturn type to decide how to initialize
                switch(act.getMethodReturn()) {
                case T_DOUBLE:
                    insn = insn.append(Insn.create(opc_dconst_0));
                    break;
                case T_LONG:
                    insn = insn.append(Insn.create(opc_lconst_0));
                    break;
                case T_FLOAT:
                    insn = insn.append(Insn.create(opc_fconst_0));
                    break;
                case T_BOOLEAN:
                case T_CHAR:
                case T_BYTE:
                case T_SHORT:
                case T_INT:
                    insn = insn.append(Insn.create(opc_iconst_0));
                    break;
                case TC_STRING:
                case TC_OBJECT:
                case TC_INTERFACE:
                    insn = insn.append(Insn.create(opc_aconst_null));
                    break;
                default:
                    throw new InternalError("Unexpected return type");
                }

                // finally, store the result
                insn = insn.append(Insn.create(opc_putfield,
                                               pool.addFieldRef(thisClass.asString(), act.fieldName(),
                                                                act.typeDescriptor())));
            }
        }

        ConstClass superClass = ca.classFile().superName();
        if (!ca.getImplementsPersistence()) {
            // Need to invoke clearContents on super
            // get this
            insn = insn.append(Insn.create(opc_aload_0));
            // do the invoke
            insn = insn.append(Insn.create(opc_invokespecial,
                                           pool.addMethodRef(superClass.asString(),
                                                             "clearContents", "()V")));
        }

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              3, // maxStack (maybe only 2 - ok)
                              1, // maxLocals
                              begin,
                              new ExceptionTable(),
                              new AttributeVector()));
        return clearContentsMethod;
    }
*/

    /**
     * Build an empty class initializer method for this class
     */
//@olsen: dropped method
/*
    ClassMethod makeClassInit(ClassAction ca) {
        final ConstantPool pool = ca.classFile().pool();
        final ConstClass thisClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        ClassMethod classInitMethod =
            new ClassMethod(ACCStatic,
                            pool.addUtf8("<clinit>"),
                            pool.addUtf8("()V"),
                            methodAttrs);

        // begin of method body
        Insn begin = new InsnTarget();
        Insn insn = begin;

        // return from the initializer
        // end of method body
        insn = insn.append(Insn.create(opc_return));

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              0,
                              0, // maxLocals
                              begin,
                              new ExceptionTable(),
                              new AttributeVector()));
        return classInitMethod;
    }
*/

    /**
     * Build the jdoGetStateManager method for the class.
     *
     * public StateManager jdoGetStateManager() {
     *     return this.jdoStateManager;
     * }
     */
    //@olsen: cosmetics
    ClassMethod makeJDOGetStateManager(final ClassAction ca,
                                       final String methodName) {
        //@olsen: added variable
        final String methodSig = "()" + JDOMetaData.JDOStateManagerSig;//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoGetStateManagerMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // get jdoStateManager field
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(opc_getfield,
                        pool.addFieldRef(theClass.asString(),
                                         JDOMetaData.JDOStateManagerFieldName,
                                         JDOMetaData.JDOStateManagerFieldSig)));

        // end of method body
        insn = insn.append(Insn.create(opc_areturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              1, // maxStack
                              1, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoGetStateManagerMethod;
    }

    /**
     * Build the jdoSetStateManager method for the class.
     *
     * public void jdoSetStateManager(StateManager sm) {
     *     this.jdoStateManager = sm;
     * }
     */
    //@olsen: cosmetics
    ClassMethod makeJDOSetStateManager(final ClassAction ca,
                                       final String methodName) {
        //@olsen: added variable
        final String methodSig = "(" + JDOMetaData.JDOStateManagerSig + ")V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoSetStateManagerMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // put argument value to jdoStateManager field
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            Insn.create(opc_putfield,
                        pool.addFieldRef(theClass.asString(),
                                         JDOMetaData.JDOStateManagerFieldName,
                                         JDOMetaData.JDOStateManagerFieldSig)));

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              2, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoSetStateManagerMethod;
    }

    /**
     * Build the jdoGetFlags method for the class.
     *
     * public byte jdoGetFlags() {
     *     return this.jdoFlags;
     * }
     */
    //@olsen: cosmetics
    ClassMethod makeJDOGetFlags(final ClassAction ca,
                                final String methodName) {
        //@olsen: added variable
        final String methodSig = "()B";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoGetFlagsMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // get jdoFlags field
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(opc_getfield,
                        pool.addFieldRef(theClass.asString(),
                                         JDOMetaData.JDOFlagsFieldName,
                                         JDOMetaData.JDOFlagsFieldSig)));

        // end of method body
        insn = insn.append(Insn.create(opc_ireturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              1, // maxStack
                              1, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoGetFlagsMethod;
    }

    /**
     * Build the jdoSetFlags method for the class.
     *
     * public void jdoSetFlags(byte flags) {
     *     this.jdoFlags = flags;
     * }
     */
    //@olsen: cosmetics
    ClassMethod makeJDOSetFlags(final ClassAction ca,
                                final String methodName) {
        //@olsen: added variable
        final String methodSig = "(B)V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoSetFlagsMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // put argument value to jdoFlags field
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(Insn.create(opc_iload_1));
        insn = insn.append(
            Insn.create(opc_putfield,
                        pool.addFieldRef(theClass.asString(),
                                         JDOMetaData.JDOFlagsFieldName,
                                         JDOMetaData.JDOFlagsFieldSig)));

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              2, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoSetFlagsMethod;
    }

    /**
     * Build the jdoMakeDirty method for the class.
     *
     * public void makeDirty() {
     *     final StateManager sm = this.jdoStateManager;
     *     if (sm != null)
     *         sm.makeDirty(fieldName);
     * }
     */
    //@olsen: added method for generating the jdoMakeDirty method
    ClassMethod makeJDOMakeDirtyMethod(final ClassAction ca,
                                       final String methodName) {
        //@olsen: added variable
        final String methodSig = "(Ljava/lang/String;)V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoMakeDirtyMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // fetch the jdoStateManager field into local var
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(
                opc_getfield,
                pool.addFieldRef(theClass.asString(),
                                 JDOMetaData.JDOStateManagerFieldName,
                                 JDOMetaData.JDOStateManagerFieldSig)));
        insn = insn.append(Insn.create(opc_astore_2));

        // test the jdoStateManager field and goto end if null
        InsnTarget end = new InsnTarget();
        insn = insn.append(Insn.create(opc_aload_2));
        insn = insn.append(Insn.create(opc_ifnull, end));

        // call the jdoStateManager's makeDirty method with argument
        insn = insn.append(Insn.create(opc_aload_2));
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            new InsnInterfaceInvoke(
                pool.addInterfaceMethodRef(
                    JDOMetaData.JDOStateManagerPath,
                    "makeDirty",//NOI18N
                    "(Ljava/lang/String;)V"),//NOI18N
                2));

        // end of method body
        insn = insn.append(end);
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              2, // maxStack
                              3, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoMakeDirtyMethod;
    }

    /**
     * Build an interrogative method named methodName for the class.
     *
     * public boolean isXXX() {
     *     final StateManager sm = this.jdoStateManager;
     *     if (sm == null)
     *         return false;
     *     return sm.isXXXX();
     * }
     */
    //@olsen: added method for generating an interrogative JDO method
    ClassMethod makeJDOInterrogativeMethod(final ClassAction ca,
                                           final String methodName) {
        //@olsen: added variable
        final String methodSig = "()Z";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod interrogativeMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // fetch the jdoStateManager field into local var
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(
                opc_getfield,
                pool.addFieldRef(theClass.asString(),
                                 JDOMetaData.JDOStateManagerFieldName,
                                 JDOMetaData.JDOStateManagerFieldSig)));
        insn = insn.append(Insn.create(opc_astore_1));

        // test the jdoStateManager field and return false if null
        InsnTarget call = new InsnTarget();
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(Insn.create(opc_ifnonnull, call));
        insn = insn.append(Insn.create(opc_iconst_0));
        insn = insn.append(Insn.create(opc_ireturn));

        // call the jdoStateManager's interrogative method (jdoIs... -> is...)
        final String callName = "i" + methodName.substring(4);//NOI18N
        insn = insn.append(call);
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            new InsnInterfaceInvoke(
                pool.addInterfaceMethodRef(
                    JDOMetaData.JDOStateManagerPath,
                    callName,
                    "()Z"),//NOI18N
                1));

        // end of method body
        insn = insn.append(Insn.create(opc_ireturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              1, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return interrogativeMethod;
    }

    /**
     * Build the jdoGetPersistenceManager method for the class.
     *
     * public PersistenceManager jdoGetPersistenceManager() {
     *     final StateManager sm = this.jdoStateManager;
     *     if (sm == null)
     *         return null;
     *     return sm.getPersistenceManager();
     * }
     */
    //@olsen: added method for generating the jdoGetPersistenceManager method
    ClassMethod makeJDOGetPersistenceManagerMethod(final ClassAction ca,
                                                   final String methodName) {
        //@olsen: added variable
        final String methodSig = "()" + JDOMetaData.JDOPersistenceManagerSig;//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoGetPersistenceManagerMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // fetch the jdoStateManager field into local var
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(
                opc_getfield,
                pool.addFieldRef(theClass.asString(),
                                 JDOMetaData.JDOStateManagerFieldName,
                                 JDOMetaData.JDOStateManagerFieldSig)));
        insn = insn.append(Insn.create(opc_astore_1));

        // test the jdoStateManager field and return null if null
        InsnTarget call = new InsnTarget();
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(Insn.create(opc_ifnonnull, call));
        insn = insn.append(Insn.create(opc_aconst_null));
        insn = insn.append(Insn.create(opc_areturn));

        // call the jdoStateManager's getPersistenceManager method
        insn = insn.append(call);
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            new InsnInterfaceInvoke(
                pool.addInterfaceMethodRef(
                    JDOMetaData.JDOStateManagerPath,
                    "getPersistenceManager",//NOI18N
                    "()" + JDOMetaData.JDOPersistenceManagerSig),//NOI18N
                1));

        // end of method body
        insn = insn.append(Insn.create(opc_areturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              1, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoGetPersistenceManagerMethod;
    }

    /**
     * Build the jdoGetObjectId method for the class.
     *
     * public Object jdoGetObjectId() {
     *     final StateManager sm = this.jdoStateManager;
     *     if (sm == null)
     *         return null;
     *     return sm.getObjectId();
     * }
     */
    //@olsen: added method for generating the jdoGetObjectId method
    ClassMethod makeJDOGetObjectIdMethod(final ClassAction ca,
                                         final String methodName) {
        //@olsen: added variable
        final String methodSig = "()Ljava/lang/Object;";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();

        //@olsen: made method final
        final ClassMethod jdoGetObjectIdMethod
            = new ClassMethod(ACCPublic | ACCFinal,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // fetch the jdoStateManager field into local var
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(
                opc_getfield,
                pool.addFieldRef(theClass.asString(),
                                 JDOMetaData.JDOStateManagerFieldName,
                                 JDOMetaData.JDOStateManagerFieldSig)));
        insn = insn.append(Insn.create(opc_astore_1));

        // test the jdoStateManager field and return null if null
        InsnTarget call = new InsnTarget();
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(Insn.create(opc_ifnonnull, call));
        insn = insn.append(Insn.create(opc_aconst_null));
        insn = insn.append(Insn.create(opc_areturn));

        // call the jdoStateManager's getObjectId method
        insn = insn.append(call);
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            new InsnInterfaceInvoke(
                pool.addInterfaceMethodRef(
                    JDOMetaData.JDOStateManagerPath,
                    "getObjectId",//NOI18N
                    "()Ljava/lang/Object;"),//NOI18N
                1));

        // end of method body
        insn = insn.append(Insn.create(opc_areturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              1, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoGetObjectIdMethod;
    }

    /**
     * Build the jdoGetJDOConstructor method for the class.
     *
     * public <init>(StateManager sm) {
     *     this.jdoFlags = 1;
     *     this.jdoStateManager = sm;
     * }
     */
    //@olsen: added method for generating the JDO constructor
    ClassMethod makeJDOConstructor(final ClassAction ca,
                                   final String methodName) {
        //@olsen: added variable
        final String methodSig = "(" + JDOMetaData.JDOStateManagerSig + ")V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod jdoGetJDOConstructor
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // call the super-class' constructor
        final ConstClass superClass = ca.classFile().superName();
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(opc_invokespecial,
                        pool.addMethodRef(superClass.asString(),
                                          "<init>",//NOI18N
                                          "()V")));//NOI18N

        // put argument value to jdoFlags field
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(Insn.create(opc_iconst_1));
        insn = insn.append(
            Insn.create(opc_putfield,
                        pool.addFieldRef(theClass.asString(),
                                         JDOMetaData.JDOFlagsFieldName,
                                         JDOMetaData.JDOFlagsFieldSig)));

        // put argument value to jdoStateManager field
        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            Insn.create(
                opc_putfield,
                pool.addFieldRef(theClass.asString(),
                                 JDOMetaData.JDOStateManagerFieldName,
                                 JDOMetaData.JDOStateManagerFieldSig)));

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              2, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoGetJDOConstructor;
    }

    /**
     * Build the jdoNewInstance method for the class.
     *
     * public Object jdoNewInstance(StateManager sm) {
     *     return new <init>(sm);
     * }
     */
    //@olsen: added method for generating the getObjectId method
    ClassMethod makeJDONewInstanceMethod(final ClassAction ca,
                                         final String methodName) {
        //@olsen: added variable
        final String methodSig
            = "(" + JDOMetaData.JDOStateManagerSig + ")Ljava/lang/Object;";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod jdoNewInstanceMethod
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // create an instance of the class by JDO constructor
        insn = insn.append(Insn.create(opc_new, theClass));
        insn = insn.append(Insn.create(opc_dup));
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            Insn.create(
                opc_invokespecial,
                pool.addMethodRef(
                    theClass.asString(),
                    "<init>",//NOI18N
                    "(" + JDOMetaData.JDOStateManagerSig + ")V")));//NOI18N

        // end of method body
        insn = insn.append(Insn.create(opc_areturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              3, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoNewInstanceMethod;
    }

    /**
     * Build the jdoClear method for the class.
     *
     * public void jdoClear() {
     *     ...
     * }
     */
    //@olsen: added method for generating the jdoClear method
    ClassMethod makeJDOClearMethod(final ClassAction ca,
                                   final String methodName) {
        //@olsen: added variable
        final String methodSig = "()V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod jdoClearMethod
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        //@olsen: disabled code
        if (false) {
            // reset jdoFlags = LOAD_REQUIRED
            insn = insn.append(Insn.create(opc_aload_0));
            insn = insn.append(Insn.create(opc_iconst_1));
            insn = insn.append(
                Insn.create(opc_putfield,
                            pool.addFieldRef(theClass.asString(),
                                             JDOMetaData.JDOFlagsFieldName,
                                             JDOMetaData.JDOFlagsFieldSig)));
        }

        // iterate over all declared fields of the class
        for (Iterator e = ca.fieldActions(); e.hasNext();) {
            final FieldAction act = (FieldAction)e.next();
            //printFieldAction(act);
            //System.out.println();

            // ignore non-persistent fields
            if (!act.isPersistent())
                continue;

            // ignore primary key fields
            if (act.isPrimaryKey())
                continue;

            //@olsen: disconnect mutable SCOs before clear
            if (act.isMutableSCO()) {
                // fetch field
                insn = insn.append(Insn.create(opc_aload_0));
                insn = insn.append(
                    Insn.create(opc_getfield,
                                pool.addFieldRef(
                                    theClass.asString(),
                                    act.fieldName(),
                                    act.typeDescriptor())));

                // test whether instanceof SCO base type
                // skip disconnecting if == 0
                final ConstClass cc
                    = pool.addClass(JDOMetaData.JDOSecondClassObjectBasePath);
                InsnTarget disconnect = new InsnTarget();
                InsnTarget afterDisconnect = new InsnTarget();
                insn = insn.append(
                    Insn.create(opc_dup));
                insn = insn.append(
                    Insn.create(opc_instanceof,
                                cc));
                insn = insn.append(
                    Insn.create(opc_ifne,
                                disconnect));

                // pop field and skip disconnecting
                insn = insn.append(
                    Insn.create(opc_pop));
                insn = insn.append(
                    Insn.create(opc_goto, afterDisconnect));

                // disconnect SCO field's object
                insn = insn.append(disconnect);

                // cast to SCO base type
                insn = insn.append(
                    Insn.create(opc_checkcast,
                                cc));

                // call method: void unsetOwner();
                final int requiredStack = 1;
                insn = insn.append(
                    new InsnInterfaceInvoke(
                        pool.addInterfaceMethodRef(
                            JDOMetaData.JDOSecondClassObjectBasePath,
                            "unsetOwner",//NOI18N
                            "()V"),//NOI18N
                        requiredStack));

                insn = insn.append(afterDisconnect);
            }

            // get this
            insn = insn.append(Insn.create(opc_aload_0));

            // use the getMethodReturn type to decide how to clear field
            switch(act.getMethodReturn()) {
            case T_DOUBLE:
                insn = insn.append(Insn.create(opc_dconst_0));
                break;
            case T_LONG:
                insn = insn.append(Insn.create(opc_lconst_0));
                break;
            case T_FLOAT:
                insn = insn.append(Insn.create(opc_fconst_0));
                break;
            case T_BOOLEAN:
            case T_CHAR:
            case T_BYTE:
            case T_SHORT:
            case T_INT:
                insn = insn.append(Insn.create(opc_iconst_0));
                break;
            case TC_STRING:
            case TC_OBJECT:
            case TC_INTERFACE:
                insn = insn.append(Insn.create(opc_aconst_null));
                break;
            default:
                throw new InternalError("Unexpected return type");//NOI18N
            }

            // put default value to field
            insn = insn.append(
                Insn.create(opc_putfield,
                            pool.addFieldRef(theClass.asString(),
                                             act.fieldName(),
                                             act.typeDescriptor())));
        }

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              3, // maxStack
                              1, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoClearMethod;
    }

    /**
     * Build the jdoCopy method for the class.
     *
     * public void jdoCopy(Object o, boolean cloneSCOs) {
     *     ...
     * }
     */
//@lars, @olsen: disabled jdoCopy becuase of two problems with the
// current code (this method hasn't been used by the runtime anyway):
// 4388418: Generated jdoCopy() must ignore static fields
// 4388367: Generated jdoCopy() can throw NPE if argument = 'true'
/*
    //@olsen: added method for generating the jdoCopy method
    ClassMethod makeJDOCopyMethod(final ClassAction ca,
                                  final String methodName) {

        //@olsen: added variable
        final String methodSig = "(Ljava/lang/Object;Z)V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod jdoCopyMethod
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // get class object of this and of argument object
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            Insn.create(opc_invokevirtual,
                        pool.addMethodRef(
                            "java/lang/Object",//NOI18N
                            "getClass",//NOI18N
                            "()Ljava/lang/Class;")));//NOI18N
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(
            Insn.create(opc_invokevirtual,
                        pool.addMethodRef(
                            "java/lang/Object",//NOI18N
                            "getClass",//NOI18N
                            "()Ljava/lang/Class;")));//NOI18N

        // test class objects for equality and throw exception if false
        insn = insn.append(
            Insn.create(opc_invokevirtual,
                        pool.addMethodRef(
                            "java/lang/Object",//NOI18N
                            "equals",//NOI18N
                            "(Ljava/lang/Object;)Z")));//NOI18N
        InsnTarget cast = new InsnTarget();
        insn = insn.append(Insn.create(opc_ifne, cast));
        final String exceptionClassName
            = "com/sun/forte4j/persistence/JDOFatalException";//NOI18N
        insn = insn.append(
            Insn.create(opc_new,
                        pool.addClass(exceptionClassName)));
        insn = insn.append(Insn.create(opc_dup));
        insn = insn.append(
            Insn.create(opc_invokespecial,
                        pool.addMethodRef(
                            exceptionClassName,
                            "<init>",//NOI18N
                            "()V")));//NOI18N
        insn = insn.append(Insn.create(opc_athrow));

        // cast argument object to this class' type and store into local var
        insn = insn.append(cast);
        insn = insn.append(Insn.create(opc_aload_1));
        insn = insn.append(Insn.create(opc_checkcast, theClass));
        insn = insn.append(Insn.create(opc_astore_3));

        // iterate over all declared fields of the class
        final ArrayList mscoFields = new ArrayList();
        final JDOMetaData jdoMetaData = env.getJDOMetaData();
        for (Iterator e = ca.fieldActions(); e.hasNext();) {
            final FieldAction act = (FieldAction)e.next();
            //printFieldAction(act);
            //System.out.println();

            // remember fields of MSCO type for later processing
            if (act.isMutableSCO()) {
                mscoFields.add(act);
                continue;
            }

            // get this object
            insn = insn.append(Insn.create(opc_aload_0));

            // fetch arguments object's field
            insn = insn.append(Insn.create(opc_aload_3));
            insn = insn.append(
                Insn.create(opc_getfield,
                            pool.addFieldRef(
                                theClass.asString(),
                                act.fieldName(),
                                act.typeDescriptor())));

            // store into this object's field
            insn = insn.append(
                Insn.create(opc_putfield,
                            pool.addFieldRef(
                                theClass.asString(),
                                act.fieldName(),
                                act.typeDescriptor())));
        }

        if (mscoFields.size() > 0) {
            // test boolean argument value and clone msco fields if true
            insn = insn.append(Insn.create(opc_iload_2));
            InsnTarget shallow = new InsnTarget();
            insn = insn.append(Insn.create(opc_ifeq, shallow));

            // clone fields
            for (Iterator i = mscoFields.iterator(); i.hasNext();) {
                final FieldAction act = (FieldAction)i.next();

                // get this object
                insn = insn.append(Insn.create(opc_aload_0));

                // fetch arguments object's field
                insn = insn.append(Insn.create(opc_aload_3));
                insn = insn.append(
                    Insn.create(opc_getfield,
                                pool.addFieldRef(
                                    theClass.asString(),
                                    act.fieldName(),
                                    act.typeDescriptor())));

                // clone field value and cast to field's type
                insn = insn.append(
                    Insn.create(opc_invokevirtual,
                                pool.addMethodRef(
                                    act.typeName(),
                                    "clone",//NOI18N
                                    "()Ljava/lang/Object;")));//NOI18N
                insn = insn.append(
                    Insn.create(opc_checkcast,
                                pool.addClass(act.typeName())));

                // store into this object's field
                insn = insn.append(
                    Insn.create(opc_putfield,
                                pool.addFieldRef(
                                    theClass.asString(),
                                    act.fieldName(),
                                    act.typeDescriptor())));
            }
            InsnTarget done = new InsnTarget();
            insn = insn.append(Insn.create(opc_goto, done));

            // copy field values
            insn = insn.append(shallow);
            for (Iterator i = mscoFields.iterator(); i.hasNext();) {
                final FieldAction act = (FieldAction)i.next();

                // get this object
                insn = insn.append(Insn.create(opc_aload_0));

                // fetch arguments object's field
                insn = insn.append(Insn.create(opc_aload_3));
                insn = insn.append(
                    Insn.create(opc_getfield,
                                pool.addFieldRef(
                                    theClass.asString(),
                                    act.fieldName(),
                                    act.typeDescriptor())));

                // store into this object's field
                insn = insn.append(
                    Insn.create(opc_putfield,
                                pool.addFieldRef(
                                    theClass.asString(),
                                    act.fieldName(),
                                    act.typeDescriptor())));
            }

            insn = insn.append(done);
        }

        // end of method body
        insn = insn.append(Insn.create(opc_return));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              4, // maxStack
                              4, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoCopyMethod;
    }
*/

    /**
     * Build the jdoGetField method for the class.
     *
     * public Object jdoGetField(int fieldNumber) {
     *     return ...
     * }
     */
    //@olsen: added method for generating the jdoGetField method
    ClassMethod makeJDOGetFieldMethod(final ClassAction ca,
                                      final String methodName) {
        //@olsen: added variable
        final String methodSig = "(I)Ljava/lang/Object;";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod jdoGetFieldMethod
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // get the declared, persistent fields from the JDOMetaData
        final String className = ca.className();
        //@lars: changed getPersistentFields() into getManagedFields()
        final String[] fieldNames
            = env.getJDOMetaData().getManagedFields(className);
        final int nofFields = fieldNames.length;
        //@olsen: added println() for debugging
        if (false) {
            System.out.print("MethodBuilder.makeJDOGetFieldMethod(): "//NOI18N
                             + " declared, persistent fields of class '"//NOI18N
                             + className + "' = {");//NOI18N
            for (int i = 0; i < nofFields; i++)
                System.out.print(" " + fieldNames[i]);//NOI18N
            System.out.println(" }");//NOI18N
        }

        // generate the switch-statement only if more than zero fields
        final InsnTarget defaultOp = new InsnTarget();
        if (nofFields > 0) {
            // get the declared, persistent fields from the class
            final HashMap fieldsByName = new HashMap();
            for (Iterator e = ca.fieldActions(); e.hasNext();) {
                final FieldAction act = (FieldAction)e.next();
                fieldsByName.put(act.fieldName(), act);
            }

            // do the tableswitch on argument
            insn = insn.append(Insn.create(opc_iload_1));
            final int lowOp = 0;
            final InsnTarget[] targetsOp = new InsnTarget[nofFields];
            for (int i = 0; i < nofFields; i++)
                targetsOp[i] = new InsnTarget();
            insn = insn.append(
                new InsnTableSwitch(lowOp, defaultOp, targetsOp));

            // do the case-targets for field accesses
            for (int i = 0; i < nofFields; i++) {
                // target for accessing field [i]
                insn = insn.append(targetsOp[i]);

                final FieldAction act
                    = (FieldAction)fieldsByName.get(fieldNames[i]);
                affirm(act,
                       ("Field '" + fieldNames[i]//NOI18N
                        + "' returned by JDOMetaData is not known by class '"//NOI18N
                        + className + "'."));//NOI18N

                // use the getMethodReturn type to create the wrapper object
                final String wrapperClassName;
                final String wrapperSignature;
                switch(act.getMethodReturn()) {
                case T_DOUBLE:
                    wrapperClassName = "java/lang/Double";//NOI18N
                    wrapperSignature = "(D)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_LONG:
                    wrapperClassName = "java/lang/Long";//NOI18N
                    wrapperSignature = "(J)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_FLOAT:
                    wrapperClassName = "java/lang/Float";//NOI18N
                    wrapperSignature = "(F)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_BOOLEAN:
                    wrapperClassName = "java/lang/Boolean";//NOI18N
                    wrapperSignature = "(Z)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_CHAR:
                    wrapperClassName = "java/lang/Character";//NOI18N
                    wrapperSignature = "(C)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_BYTE:
                    wrapperClassName = "java/lang/Byte";//NOI18N
                    wrapperSignature = "(B)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_SHORT:
                    wrapperClassName = "java/lang/Short";//NOI18N
                    wrapperSignature = "(S)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case T_INT:
                    wrapperClassName = "java/lang/Integer";//NOI18N
                    wrapperSignature = "(I)V";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
                    insn = insn.append(Insn.create(opc_dup));
                    break;
                case TC_STRING:
                case TC_OBJECT:
                case TC_INTERFACE:
                    wrapperClassName = null;
                    wrapperSignature = null;
                    break;
                default:
                    throw new InternalError("Unexpected return type");//NOI18N
                }

                // fetch this object's field
                insn = insn.append(Insn.create(opc_aload_0));
                insn = insn.append(
                    Insn.create(
                        opc_getfield,
                        pool.addFieldRef(
                            theClass.asString(),
                            act.fieldName(),
                            act.typeDescriptor())));

                // wrap the field value if primitive
                switch(act.getMethodReturn()) {
                case T_DOUBLE:
                case T_LONG:
                case T_FLOAT:
                case T_BOOLEAN:
                case T_CHAR:
                case T_BYTE:
                case T_SHORT:
                case T_INT:
                    insn = insn.append(
                        Insn.create(
                            opc_invokespecial,
                            pool.addMethodRef(
                                wrapperClassName,
                                "<init>",//NOI18N
                                wrapperSignature)));
                    break;
                case TC_STRING:
                case TC_OBJECT:
                case TC_INTERFACE:
                    break;
                default:
                    throw new InternalError("Unexpected return type");//NOI18N
                }

                // return the object (break)
                insn = insn.append(Insn.create(opc_areturn));
            }
        }

        // do the default branch target creating a fatal exception
        insn = insn.append(defaultOp);
        final String exceptionClassName
            = "com/sun/jdo/api/persistence/support/JDOFatalException";//NOI18N
        insn = insn.append(
            Insn.create(
                opc_new,
                pool.addClass(exceptionClassName)));
        insn = insn.append(Insn.create(opc_dup));
        insn = insn.append(
            Insn.create(
                opc_invokespecial,
                pool.addMethodRef(
                    exceptionClassName,
                    "<init>",//NOI18N
                    "()V")));//NOI18N

        // end of method body
        insn = insn.append(Insn.create(opc_athrow));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              4, // maxStack
                              2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoGetFieldMethod;
    }

    /**
     * Build the jdoSetField method for the class.
     *
     * public jdoSetField(int fieldNumber, Object value) {
     *     ...
     * }
     */
    //@olsen: added method for generating the jdoSetField method
    ClassMethod makeJDOSetFieldMethod(final ClassAction ca,
                                      final String methodName) {
        //@olsen: added variable
        final String methodSig = "(ILjava/lang/Object;)V";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ConstantPool pool = ca.classFile().pool();
        final ConstClass theClass = ca.classFile().className();

        final AttributeVector methodAttrs = new AttributeVector();
        final ClassMethod jdoSetFieldMethod
            = new ClassMethod(ACCPublic,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

        // get the declared, persistent fields from the JDOMetaData
        final String className = ca.className();
        //@lars: changed getPersistentFields() into getManagedFields()
        final String[] fieldNames
            = env.getJDOMetaData().getManagedFields(className);
        final int nofFields = fieldNames.length;
        //@olsen: added println() for debugging
        if (false) {
            System.out.print("MethodBuilder.makeJDOSetFieldMethod(): "//NOI18N
                             + " declared, persistent fields of class '"//NOI18N
                             + className + "' = {");//NOI18N
            for (int i = 0; i < nofFields; i++)
                System.out.print(" " + fieldNames[i]);//NOI18N
            System.out.println(" }");//NOI18N
        }

        // generate the switch-statement only if more than zero fields
        final InsnTarget defaultOp = new InsnTarget();
        if (nofFields > 0) {
            // get the declared, persistent fields from the class
            final HashMap fieldsByName = new HashMap();
            for (Iterator e = ca.fieldActions(); e.hasNext();) {
                final FieldAction act = (FieldAction)e.next();
                fieldsByName.put(act.fieldName(), act);
            }

            // do the tableswitch on argument
            insn = insn.append(Insn.create(opc_iload_1));
            final int lowOp = 0;
            final InsnTarget[] targetsOp = new InsnTarget[nofFields];
            for (int i = 0; i < nofFields; i++)
                targetsOp[i] = new InsnTarget();
            insn = insn.append(
                new InsnTableSwitch(lowOp, defaultOp, targetsOp));

            // do the case-targets for field accesses
            for (int i = 0; i < nofFields; i++) {
                // target for accessing field [i]
                insn = insn.append(targetsOp[i]);

                final FieldAction act
                    = (FieldAction)fieldsByName.get(fieldNames[i]);
                affirm(act,
                       ("Field '"//NOI18N
                        + fieldNames[i]
                        + "' returned by JDOMetaData is not known by class '"//NOI18N
                        + className + "'."));//NOI18N

                // get object and value argument
                insn = insn.append(Insn.create(opc_aload_0));
                insn = insn.append(Insn.create(opc_aload_2));

                // use the getMethodReturn type to downcast the Object argument
                final String wrapperClassName;
                final String unwrapperSignature;
                final String unwrapperName;
                switch(act.getMethodReturn()) {
                case T_DOUBLE:
                    wrapperClassName = "java/lang/Double";//NOI18N
                    unwrapperSignature = "()D";//NOI18N
                    unwrapperName = "doubleValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_LONG:
                    wrapperClassName = "java/lang/Long";//NOI18N
                    unwrapperSignature = "()J";//NOI18N
                    unwrapperName = "longValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_FLOAT:
                    wrapperClassName = "java/lang/Float";//NOI18N
                    unwrapperSignature = "()F";//NOI18N
                    unwrapperName = "floatValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_BOOLEAN:
                    wrapperClassName = "java/lang/Boolean";//NOI18N
                    unwrapperSignature = "()Z";//NOI18N
                    unwrapperName = "booleanValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_CHAR:
                    wrapperClassName = "java/lang/Character";//NOI18N
                    unwrapperSignature = "()C";//NOI18N
                    unwrapperName = "charValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_BYTE:
                    wrapperClassName = "java/lang/Byte";//NOI18N
                    unwrapperSignature = "()B";//NOI18N
                    unwrapperName = "byteValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_SHORT:
                    wrapperClassName = "java/lang/Short";//NOI18N
                    unwrapperSignature = "()S";//NOI18N
                    unwrapperName = "shortValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case T_INT:
                    wrapperClassName = "java/lang/Integer";//NOI18N
                    unwrapperSignature = "()I";//NOI18N
                    unwrapperName = "intValue";//NOI18N
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(wrapperClassName)));
                    break;
                case TC_STRING:
                case TC_OBJECT:
                case TC_INTERFACE:
                    wrapperClassName = null;
                    unwrapperSignature = null;
                    unwrapperName = null;
                    insn = insn.append(
                        Insn.create(opc_checkcast,
                                    pool.addClass(act.typeName())));
                    break;
                default:
                    throw new InternalError("Unexpected return type");//NOI18N
                }

                // unwrap the object if primitive wrapper
                switch(act.getMethodReturn()) {
                case T_DOUBLE:
                case T_LONG:
                case T_FLOAT:
                case T_BOOLEAN:
                case T_CHAR:
                case T_BYTE:
                case T_SHORT:
                case T_INT:
                    insn = insn.append(
                        Insn.create(
                            opc_invokevirtual,
                            pool.addMethodRef(
                                wrapperClassName,
                                unwrapperName,
                                unwrapperSignature)));
                    break;
                case TC_STRING:
                case TC_OBJECT:
                case TC_INTERFACE:
                    break;
                default:
                    throw new InternalError("Unexpected return type");//NOI18N
                }

                // store argument value in field
                insn = insn.append(
                    Insn.create(
                        opc_putfield,
                        pool.addFieldRef(
                            theClass.asString(),
                            act.fieldName(),
                            act.typeDescriptor())));

                // return (break)
                insn = insn.append(Insn.create(opc_return));
            }
        }

        // do the default branch target creating a fatal exception
        insn = insn.append(defaultOp);
        final String exceptionClassName
            = "com/sun/jdo/api/persistence/support/JDOFatalException";//NOI18N
        insn = insn.append(
            Insn.create(
                opc_new,
                pool.addClass(exceptionClassName)));
        insn = insn.append(Insn.create(opc_dup));
        insn = insn.append(
            Insn.create(
                opc_invokespecial,
                pool.addMethodRef(
                    exceptionClassName,
                    "<init>",//NOI18N
                    "()V")));//NOI18N

        // end of method body
        insn = insn.append(Insn.create(opc_athrow));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              3, // maxStack
                              3, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        return jdoSetFieldMethod;
    }

    /**
     * Build the clone method for the class.
     */
    //@olsen: subst: makeClone -> makeJDOClone
    ClassMethod makeJDOClone(final ClassAction ca,
                             final String methodName) {
        //@olsen: added variable
        final String methodSig = "()Ljava/lang/Object;";//NOI18N
        env.message("adding "//NOI18N
                    + ca.classControl().userClassName() +
                    "." + methodName//NOI18N
                    + Descriptor.userMethodArgs(methodSig));

        final ClassFile cFile = ca.classFile();
        final ConstantPool pool = cFile.pool();
        final ConstClass theClass = cFile.className();
        final ConstClass superClass = cFile.superName();

        final AttributeVector methodAttrs = new AttributeVector();
        //@olsen: fixed bug: changed ACCProtected to ACCPublic to allow for
        //        an inherited method clone() to be public!
        //@olsen: removed ACCSynchronized flag
        final ClassMethod cloneMethod
            = new ClassMethod(ACCPublic, //|ACCSynchronized,
                              pool.addUtf8(methodName),
                              pool.addUtf8(methodSig),
                              methodAttrs);

        // begin of method body
        //@olsen: fix 4467428, made 'begin' final InsnTarget
        final InsnTarget begin = new InsnTarget();
        Insn insn = begin;

//@olsen: disabled feature
/*
        //   if (jdoFlags < 0)
        //     Implementation.fetch(this);

        InsnTarget cloneStart = new InsnTarget();

        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(opc_getfield,
                        pool.addFieldRef(theClass.asString(),
                                         JDOMetaData.JDOFlagsFieldName,
                                         JDOMetaData.JDOFlagsFieldSig)));
        insn = insn.append(Insn.create(opc_ifge, cloneStart));

        insn = insn.append(Insn.create(opc_aload_0));
        insn = insn.append(
            Insn.create(opc_invokestatic,
                        pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "fetch",
                                          "(" + JDOMetaData.JDOPersistenceCapableSig + ")V")));

        insn = insn.append(cloneStart);
*/

        // THISCLASS newObject = (THISCLASS) super.clone();
        {
            insn = insn.append(Insn.create(opc_aload_0));
            insn = insn.append(
                Insn.create(opc_invokespecial,
                            pool.addMethodRef(superClass.asString(),
//                            pool.addMethodRef("java/lang/Object",
                                              methodName,
                                              methodSig)));

            // add cast to the appropriate type
            insn = insn.append(Insn.create(opc_checkcast, theClass));
        }

//@olsen: disabled feature
/*
        if (ca.getNeedsJDOStateManagerMethods()) {
*/
        // newObject.jdoStateManager = null;
        if (false)
        {
            insn = insn.append(Insn.create(opc_dup));
            insn = insn.append(Insn.create(opc_aconst_null));
            insn = insn.append(
                Insn.create(
                    opc_putfield,
                    pool.addFieldRef(theClass.asString(),
                                     JDOMetaData.JDOStateManagerFieldName,
                                     JDOMetaData.JDOStateManagerFieldSig)));
        }

//@olsen: disabled feature
/*
        if (ca.getNeedsJDOFlagsMethods()) {
*/
        // newObject.jdoFlags = 0;
        if (false)
        {
            insn = insn.append(Insn.create(opc_dup));
            insn = insn.append(Insn.create(opc_iconst_0));
            insn = insn.append(
                Insn.create(opc_putfield,
                            pool.addFieldRef(theClass.asString(),
                                             JDOMetaData.JDOFlagsFieldName,
                                             JDOMetaData.JDOFlagsFieldSig)));
        }

        // return newObject;

        // end of method body
        insn = insn.append(Insn.create(opc_areturn));

        final AttributeVector codeSpecificAttrs = new AttributeVector();

        //@olsen: fix 4467428, added dummy, non-empty line number table
        if (addLineNumberTableAttr) {
            codeSpecificAttrs.addElement(
                new LineNumberTableAttribute(
                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
                    new short[]{ 0 }, new InsnTarget[]{ begin }));
        }

        methodAttrs.addElement(
            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
                              //@olsen: updated maxLocals
                              1, //3, //3, // maxStack
                              1, //2, // maxLocals
                              begin,
                              new ExceptionTable(),
                              codeSpecificAttrs));

        //@olsen: fix 4467428, added synthetic attribute for generated method
        if (addSyntheticAttr) {
            methodAttrs.addElement(
                new SyntheticAttribute(
                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
        }

        methodAttrs.addElement(
            new ExceptionsAttribute(
                pool.addUtf8(ExceptionsAttribute.expectedAttrName),
                pool.addClass("java/lang/CloneNotSupportedException")));//NOI18N

        return cloneMethod;
    }

    // for debugging
    static private void printFieldAction(FieldAction act) {
        System.out.println("fieldName() = " + act.fieldName());//NOI18N
        System.out.println("userFieldName() = " + act.userFieldName());//NOI18N
        System.out.println("typeDescriptor() = " + act.typeDescriptor());//NOI18N
        System.out.println("typeName() = " + act.typeName());//NOI18N
        System.out.println("fieldClassName() = " + act.fieldClassName());//NOI18N
        System.out.println("isPersistent() = " + act.isPersistent());//NOI18N
        System.out.println("isPrimaryKey() = " + act.isPrimaryKey());//NOI18N
        System.out.println("isMutableSCO() = " + act.isMutableSCO());//NOI18N
        System.out.println("isSynthetic() = " + act.isSynthetic());//NOI18N
        //System.out.println("index() = " + act.index());
        System.out.println("nDims() = " + act.nDims());//NOI18N
        System.out.println("createMethod() = " + act.createMethod());//NOI18N
        System.out.println("createMethodSig() = " + act.createMethodSig());//NOI18N
        System.out.println("setMethod() = " + act.setMethod());//NOI18N
        System.out.println("setMethodSig() = " + act.setMethodSig());//NOI18N
        System.out.println("setMethodArg() = "//NOI18N
                           + typeToString(act.setMethodArg()));
        System.out.println("getMethod() = " + act.getMethod());//NOI18N
        System.out.println("getMethodSig() = " + act.getMethodSig());//NOI18N
        System.out.println("getMethodReturn() = "//NOI18N
                           + typeToString(act.getMethodReturn()));
    }

    // for debugging
    static private String typeToString(int val) {
        switch(val) {
        case T_DOUBLE:
            return "T_DOUBLE";//NOI18N
        case T_LONG:
            return "T_LONG";//NOI18N
        case T_BOOLEAN:
            return "T_BOOLEAN";//NOI18N
        case T_CHAR:
            return "T_CHAR";//NOI18N
        case T_FLOAT:
            return "T_FLOAT";//NOI18N
        case T_BYTE:
            return "T_BYTE";//NOI18N
        case T_SHORT:
            return "T_SHORT";//NOI18N
        case T_INT:
            return "T_INT";//NOI18N
        case TC_STRING:
            return "TC_STRING";//NOI18N
        case TC_OBJECT:
            return "TC_OBJECT";//NOI18N
        case TC_INTERFACE:
            return "TC_INTERFACE";//NOI18N
        default:
            throw new InternalError("Unexpected return type");//NOI18N
        }
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish MethodBuilder.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.