Package org.jpox.enhancer.bcel.method

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

/**********************************************************************
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.BranchInstruction;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.IFEQ;
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.MethodGen;
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;

/**
* Enhance a persistent property setter
* @version $Revision: 1.4 $
*/
public class PropertySetterMethod
{
    /** 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 PropertySetterMethod(
        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());
        }
        // if( jdoStateManager != null )

        InstructionHandle last;
        BranchInstruction flgIsZero = null;
        if( (fieldConfig.getJdoFieldFlag() & PersistenceCapable.CHECK_WRITE) == PersistenceCapable.CHECK_WRITE)
        {
            // (flag == 0)
            il.append(InstructionConstants.ALOAD_0);
            il.append(factory.createGetField(className, ClassEnhancer.FN_Flag, Type.BYTE));
            flgIsZero = new IFEQ(null);
            il.append(flgIsZero);
        }
        il.append(InstructionConstants.ALOAD_0);
        il.append(factory.createGetField(className, ClassEnhancer.FN_StateManager, BCELClassEnhancer.OT_StateManager));
        BranchInstruction hasStateManager = new IFNULL(null);
        il.append(hasStateManager);
        // {
        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(InstructionConstants.ALOAD_0);
            il.append(factory.createInvoke(
                className,
                "jdo"+BCELUtils.getGetterName(fieldName),
                nativeType,
                new Type[] {},
                Constants.INVOKEVIRTUAL));           
        il.append(InstructionFactory.createLoad(nativeType, 1));
        il.append(factory.createInvoke(ClassEnhancer.CN_StateManager, "set" + BCELUtils.getJDOMethodName(smType) + "Field",
            Type.VOID, new Type[]{BCELClassEnhancer.OT_PersistenceCapable, Type.INT, smType, smType}, Constants.INVOKEINTERFACE));
        //}
        //----detach------
        if (cmd.isDetachable())
        {
            // jdoIsDetached()
            last = il.append(InstructionConstants.ALOAD_0);
            il.append(factory.createInvoke(ClassEnhancer.CN_PersistenceCapable, ClassEnhancer.MN_JdoIsDetached,
                Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));

            // 1
            il.append(InstructionConstants.ICONST_1);
            // if (jdoIsDetached() == 1)
            IF_ICMPEQ ifIsDetached = new IF_ICMPEQ(null);
            il.append(ifIsDetached);
            // return;
            il.append(InstructionConstants.ALOAD_0);
            il.append(InstructionFactory.createLoad(nativeType, 1));
                il.append(factory.createInvoke(
                    className,
                    "jdo"+BCELUtils.getSetterName(fieldName),
                    Type.VOID,
                    new Type[] {nativeType},
                    Constants.INVOKEVIRTUAL));           
            il.append(InstructionConstants.RETURN);

            // ((BitSet)jdoDetachedState[3]).set(?)
            //   jdoDetachedState[3]
            ifIsDetached.setTarget(il.append(InstructionConstants.ALOAD_0));
            il.append(factory.createGetField(className, ClassEnhancer.FN_JdoDetachedState, BCELClassEnhancer.OT_ObjectArray));
            il.append(InstructionConstants.ICONST_3);
            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);
            }
            //   set(?)
            il.append(factory.createInvoke(ClassEnhancer.CN_BitSet, "set", Type.VOID, new Type[]{Type.INT}, Constants.INVOKEVIRTUAL));
            //----detach------

            il.append(InstructionConstants.ALOAD_0);
            il.append(InstructionFactory.createLoad(nativeType, 1));
                il.append(factory.createInvoke(
                    className,
                    "jdo"+BCELUtils.getSetterName(fieldName),
                    Type.VOID,
                    new Type[] {nativeType},
                    Constants.INVOKEVIRTUAL));           
            il.append(InstructionConstants.RETURN);
            methodGen.setInstructionList(il);
        }
        else
        {
            last = il.append(InstructionConstants.ALOAD_0);
            il.append(InstructionFactory.createLoad(nativeType, 1));
                il.append(factory.createInvoke(
                    className,
                    "jdo"+BCELUtils.getSetterName(fieldName),
                    Type.VOID,
                    new Type[] {nativeType},
                    Constants.INVOKEVIRTUAL));           
            il.append(InstructionConstants.RETURN);
            methodGen.setInstructionList(il);
        }
        hasStateManager.setTarget(last);
        if( (fieldConfig.getJdoFieldFlag() & PersistenceCapable.CHECK_WRITE) == PersistenceCapable.CHECK_WRITE)
        {
            flgIsZero.setTarget(last);
        }
        methodGen.setMaxLocals();
        methodGen.setMaxStack();
        classGen.replaceMethod(method, methodGen.getMethod());
    }
}
TOP

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

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.