Package org.jpox.enhancer.bcel.method

Source Code of org.jpox.enhancer.bcel.method.PropertyGetterMethod

/**********************************************************************
Copyright (c) 2007 Erik Bengtson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
    ...
**********************************************************************/
package org.jpox.enhancer.bcel.method;

import javax.jdo.spi.PersistenceCapable;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.CHECKCAST;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.IFEQ;
import org.apache.bcel.generic.IFNE;
import org.apache.bcel.generic.IFNULL;
import org.apache.bcel.generic.IF_ICMPEQ;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LDC;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ReferenceType;
import org.apache.bcel.generic.Type;
import org.jpox.enhancer.ClassEnhancer;
import org.jpox.enhancer.bcel.BCELClassEnhancer;
import org.jpox.enhancer.bcel.BCELUtils;
import org.jpox.enhancer.bcel.metadata.BCELClassMetaData;
import org.jpox.enhancer.bcel.metadata.BCELMember;
import org.jpox.enhancer.bcel.metadata.BCELFieldPropertyMetaData;
import org.jpox.metadata.AbstractMemberMetaData;
import org.jpox.util.ClassUtils;
import org.jpox.util.Localiser;

/**
* Enhance a persistent property setter
* @version $Revision: 1.5 $
*/
public class PropertyGetterMethod
{
    /** Localisation of messages */
    protected static Localiser LOCALISER=Localiser.getInstance("org.jpox.enhancer.Localisation",
        ClassEnhancer.class.getClassLoader());

    /** target field */
    protected BCELFieldPropertyMetaData fieldConfig;

    /** InstructionList instance */
    protected InstructionList il;

    /** MethodGen instance  */
    protected MethodGen methodGen;

    /** is synthetic */
    protected boolean synthetic;

    /** target ClassGen instance */
    protected ClassGen classGen;

    /** target class name */
    protected String className;

    /** target ConstantPoolGen instance */
    protected ConstantPoolGen constantPoolGen;

    /** ClassMetaData for the class */
    protected BCELClassMetaData cmd;
   
    /** Types of the arguments. */
    protected Object[] argTypes;

    /** InstructionFactory instance */
    protected InstructionFactory factory;
   
    /** Method */
    protected Method method;

    /**
     * Constructor
     * @param m Method
     * @param className Name of class
     * @param constantPoolGen BCEL pool gen
     * @param newClass the new class
     * @param argTypes types of args to the method
     * @param fieldConfig metadata for the field/property
     * @param enhancer The enhancer
     */
    public PropertyGetterMethod(
        Method m,
        String className,
        ConstantPoolGen constantPoolGen,
        ClassGen newClass,
        Type argTypes[],
        BCELFieldPropertyMetaData fieldConfig,
        BCELClassEnhancer enhancer)
    {
        this.method = m;
        this.fieldConfig = fieldConfig;
        this.methodGen = new MethodGen(m, className, constantPoolGen);
        this.methodGen.setInstructionList(new InstructionList());
        this.methodGen.removeLocalVariables();
        this.methodGen.removeLineNumbers();
        this.methodGen.removeExceptions();
        this.il = methodGen.getInstructionList();
        this.factory = new InstructionFactory(newClass);
        this.className = className;
        this.cmd = (BCELClassMetaData)enhancer.getClassMetaData();
        this.classGen = newClass;
        this.fieldConfig = fieldConfig;
        this.constantPoolGen = constantPoolGen;
    }

    public void execute()
    {      
        methodGen.setMaxLocals();
        methodGen.setMaxStack();
        BCELMember targetField = fieldConfig.getEnhanceField();
        Type smType = BCELUtils.getJDOMethodType(targetField.getType());
        Type nativeType = targetField.getType();
        String fieldName;
        if(!((AbstractMemberMetaData)fieldConfig).isProperty())
        {
            fieldName = targetField.getName();
        }
        else
        {
            fieldName = ClassUtils.getFieldNameForJavaBeanGetter(targetField.getName());
        }
        InstructionHandle jumpTarget;

        BranchInstruction jump1 = null;
        if( (fieldConfig.getJdoFieldFlag() & PersistenceCapable.CHECK_READ) == PersistenceCapable.CHECK_READ)
        {
            il.append(InstructionConstants.ALOAD_0);
            il.append(factory.createGetField(className, ClassEnhancer.FN_Flag, Type.BYTE));
            jump1 = new IFEQ(null);
            il.append(jump1);
        }

        il.append(InstructionConstants.ALOAD_0);
        il.append(factory.createGetField(className, ClassEnhancer.FN_StateManager, BCELClassEnhancer.OT_StateManager));
        BranchInstruction jump2 = new IFNULL(null);
        il.append(jump2);

        il.append(InstructionConstants.ALOAD_0);
        il.append(factory.createGetField(className, ClassEnhancer.FN_StateManager, BCELClassEnhancer.OT_StateManager));
        il.append(InstructionConstants.ALOAD_0);
        il.append(BCELUtils.getBIPUSH(fieldConfig.getFieldId()));
        if (cmd.getPersistenceCapableSuperclass() != null)
        {
            il.append(factory.createGetStatic(className, ClassEnhancer.FN_JdoInheritedFieldCount, Type.INT));
            il.append(InstructionConstants.IADD);
        }
        il.append(factory.createInvoke(ClassEnhancer.CN_StateManager, "isLoaded", Type.BOOLEAN,
            new Type[]{BCELClassEnhancer.OT_PersistenceCapable, Type.INT}, Constants.INVOKEINTERFACE));
        BranchInstruction jump3 = new IFNE(null);
        il.append(jump3);

        // statemanager.getXXXfield();
        il.append(InstructionConstants.ALOAD_0);
        il.append(factory.createGetField(className, ClassEnhancer.FN_StateManager, BCELClassEnhancer.OT_StateManager));
        il.append(InstructionConstants.ALOAD_0);
        il.append(BCELUtils.getBIPUSH(fieldConfig.getFieldId()));
        if (cmd.getPersistenceCapableSuperclass() != null)
        {
            il.append(factory.createGetStatic(className, ClassEnhancer.FN_JdoInheritedFieldCount, Type.INT));
            il.append(InstructionConstants.IADD);
        }
        //jdoGetXXX
        il.append(InstructionConstants.ALOAD_0);
        il.append(factory.createInvoke(
            className,
            "jdo"+BCELUtils.getGetterName(fieldName),
            nativeType,
            new Type[] {},
            Constants.INVOKEVIRTUAL));

        il.append(factory.createInvoke(ClassEnhancer.CN_StateManager, "get" + BCELUtils.getJDOMethodName(targetField.getType()) + "Field",
            smType, new Type[]{BCELClassEnhancer.OT_PersistenceCapable, Type.INT, smType}, Constants.INVOKEINTERFACE));

        if (nativeType instanceof ReferenceType)
        {
            String type = null;
            if (nativeType instanceof ArrayType)
            {
                type = nativeType.getSignature();
            }
            else
            {
                type = nativeType.toString();
            }
            il.append(new CHECKCAST(constantPoolGen.addClass(type)));
        }
        il.append(InstructionFactory.createReturn(nativeType));

        //----detach------
        if (cmd.isDetachable())
        {
            // jdoIsDetached()
            jumpTarget = il.append(InstructionConstants.ALOAD_0);
            il.append(factory.createInvoke(ClassEnhancer.CN_PersistenceCapable, ClassEnhancer.MN_JdoIsDetached,
                Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));

            //0
            il.append(InstructionConstants.ICONST_0);
            // if (jdoIsDetached() == 0)
            IF_ICMPEQ ifIsDetached = new IF_ICMPEQ(null);
            il.append(ifIsDetached);

            // if (jdoDetachedState[2].get(?) == 1)
            //   jdoDetachedState[2]
            ifIsDetached.setTarget(il.append(InstructionConstants.ALOAD_0));
            il.append(factory.createGetField(className, ClassEnhancer.FN_JdoDetachedState, BCELClassEnhancer.OT_ObjectArray));
            il.append(InstructionConstants.ICONST_2);
            il.append(InstructionConstants.AALOAD);
            il.append(factory.createCheckCast(BCELClassEnhancer.OT_BitSet)); // Cast to BitSet

            //   the field index: 0, 1, 2...
            il.append(BCELUtils.getBIPUSH(fieldConfig.getFieldId()));
            if (cmd.getPersistenceCapableSuperclass() != null)
            {
                // add to field index the parentFieldCount
                il.append(factory.createGetStatic(className, ClassEnhancer.FN_JdoInheritedFieldCount, Type.INT));
                il.append(InstructionConstants.IADD);
            }
            //   get(?)
            il.append(factory.createInvoke(ClassEnhancer.CN_BitSet, "get", Type.BOOLEAN, new Type[]{Type.INT}, Constants.INVOKEVIRTUAL));

            // 1
            il.append(InstructionConstants.ICONST_1);
            // if (jdoLoadedFields.get(?) == 1)
            IF_ICMPEQ ifLoaded = new IF_ICMPEQ(null);
            il.append(ifLoaded);

            // throw new JDODetachedFieldAccessException("XXXX was not loaded.");
            createThrowException(ClassEnhancer.CN_JDODetachedFieldAccessException, LOCALISER.msg("Enhancer.DetachedFieldAccess", fieldName));

            //----detach------

            // return <target field>
            InstructionHandle jumpTarget2;
            jumpTarget2 = il.append(InstructionConstants.ALOAD_0);
            il.append(factory.createInvoke(
                className,
                "jdo"+BCELUtils.getGetterName(fieldName),
                nativeType,
                new Type[] { },
                Constants.INVOKEVIRTUAL));

            if (nativeType instanceof ReferenceType)
            {
                String type = null;
                if (nativeType instanceof ArrayType)
                {
                    type = nativeType.getSignature();
                }
                else
                {
                    type = nativeType.toString();
                }
                il.append(new CHECKCAST(constantPoolGen.addClass(type)));
            }
            il.append(InstructionFactory.createReturn(nativeType));

            if( (fieldConfig.getJdoFieldFlag() & PersistenceCapable.CHECK_READ) == PersistenceCapable.CHECK_READ)
            {
                jump1.setTarget(jumpTarget);
            }
            jump2.setTarget(jumpTarget);
            jump3.setTarget(jumpTarget);
            ifIsDetached.setTarget(jumpTarget2);
            ifLoaded.setTarget(jumpTarget2);
        }
        else
        {
            // return <target field>
            jumpTarget = il.append(InstructionConstants.ALOAD_0);
            il.append(factory.createInvoke(
                className,
                "jdo"+BCELUtils.getGetterName(fieldName),
                nativeType,
                new Type[] { },
                Constants.INVOKEVIRTUAL));

            if (nativeType instanceof ReferenceType)
            {
                String type = null;
                if (nativeType instanceof ArrayType)
                {
                    type = nativeType.getSignature();
                }
                else
                {
                    type = nativeType.toString();
                }
                il.append(new CHECKCAST(constantPoolGen.addClass(type)));
            }
            il.append(InstructionFactory.createReturn(nativeType));

            if( (fieldConfig.getJdoFieldFlag() & PersistenceCapable.CHECK_READ) == PersistenceCapable.CHECK_READ)
            {
                jump1.setTarget(jumpTarget);
            }
            jump2.setTarget(jumpTarget);
            jump3.setTarget(jumpTarget);
        }
        methodGen.setMaxLocals();
        methodGen.setMaxStack();
        classGen.replaceMethod(method, methodGen.getMethod());
    }
   

    /**
     * Helper method to create a throw exception instruction.
     * <br>
     * this method generate below code...<br>
     * <code>throw new [newExceptin param class]([message param]);</code>
     * @param newException throw exception
     * @param message exception message
     * @return first InstructionHandle
     */
    protected InstructionHandle createThrowException(String newException, String message)
    {
        InstructionHandle result;
        result = il.append(factory.createNew(newException));
        il.append(InstructionConstants.DUP);
        il.append(new LDC(classGen.getConstantPool().addString(message)));
        il.append(
            factory.createInvoke(
                newException,
                Constants.CONSTRUCTOR_NAME,
                Type.VOID,
                new Type[] { Type.STRING },
                Constants.INVOKESPECIAL));
        il.append(InstructionConstants.ATHROW);
        return result;
    }   
}
TOP

Related Classes of org.jpox.enhancer.bcel.method.PropertyGetterMethod

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.