Package org.jpox.enhancer.bcel

Source Code of org.jpox.enhancer.bcel.BCELClassMethod

/**********************************************************************
Copyright (c) 2004 Kikuchi Kousuke 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:
2007 Andy Jefferson - adapted to extend ClassMethod
    ...
**********************************************************************/
package org.jpox.enhancer.bcel;

import org.jpox.enhancer.ClassEnhancer;
import org.jpox.enhancer.ClassMethod;
import org.jpox.enhancer.bcel.metadata.BCELClassMetaData;
import org.jpox.util.Localiser;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
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;

/**
* Representation of a method required by an enhanced class, for use by BCEL.
* @version $Revision: 1.4 $
*/
public abstract class BCELClassMethod extends ClassMethod
{
    /** Localisation of messages */
    protected static Localiser LOCALISER=Localiser.getInstance("org.jpox.enhancer.Localisation",
        ClassEnhancer.class.getClassLoader());

    /** InstructionFactory instance */
    protected InstructionFactory factory;

    /** 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;

    /**
     * Constructor.
     * @param methodName method name
     * @param permissions bcel method type
     * @param returnType return type
     * @param argTypes argment types
     * @param argNames argment names
     * @param synthetic synthetic method
     * @param enhancer Class Enhancer
     */
    public BCELClassMethod(String methodName, int permissions, Type returnType, Type argTypes[], String argNames[],
            boolean synthetic, BCELClassEnhancer enhancer)
    {
        super(enhancer, methodName, permissions, returnType, argTypes, argNames);
        this.classGen = enhancer.newClass;
        this.className = enhancer.className;
        this.cmd = (BCELClassMetaData)enhancer.getClassMetaData();
        this.constantPoolGen = enhancer.constantPoolGen;
        this.synthetic = synthetic;
    }

    /**
     * Convenience accessor for the BCELClassEnhancer
     * @return ClassEnhancer for BCEL
     */
    protected BCELClassEnhancer getClassEnhancer()
    {
        return (BCELClassEnhancer)enhancer;
    }

    /**
     * Method to initialise the class method.
     */
    public void initialise()
    {
        factory = new InstructionFactory(classGen);
        il = new InstructionList();
        this.methodGen =
            new MethodGen(access, (Type)returnType, (Type[])argTypes, argNames, methodName, className, il,
                classGen.getConstantPool());
    }

    /**
     * Method to add the contents of the class method.
     */
    public void execute()
    {
        if (returnType.equals(Type.VOID))
        {
            il.append(InstructionConstants.RETURN);
        }
        else if (returnType instanceof ReferenceType)
        {
            il.append(InstructionConstants.ACONST_NULL);
            il.append(InstructionConstants.ARETURN);
        }
        else if (Type.LONG.equals(returnType))
        {
            il.append(InstructionConstants.LCONST_0);
            il.append(InstructionConstants.LRETURN);
        }
        else if (Type.DOUBLE.equals(returnType))
        {
            il.append(InstructionConstants.DCONST_0);
            il.append(InstructionConstants.DRETURN);
        }
        else if (Type.FLOAT.equals(returnType))
        {
            il.append(InstructionConstants.FCONST_0);
            il.append(InstructionConstants.FRETURN);
        }
        else
        {
            il.append(InstructionConstants.ICONST_0);
            il.append(InstructionConstants.IRETURN);
        }
    }

    /**
     * Method to close the definition of the class method
     */
    public void close()
    {
        if (methodGen != null)
        {
            methodGen.setMaxStack();
            methodGen.setMaxLocals();
            Method m = methodGen.getMethod();
            classGen.addMethod(m);
            if (synthetic)
            {
                BCELUtils.addSynthetic(m, classGen.getConstantPool());
            }

            // Log the method addition
            super.close();

            methodGen.update();
            classGen.update();
            il.dispose();
        }
    }

    /**
     * Helper method to create a throw exception instruction.
     * <br>
     *  this method generate below code...<br>
     * <code>throw new [newExceptin param class]([message param]+[intMessage param]);</code>
     * @param newException throw exception
     * @param message exception message
     * @param intMessage exception message append ,like ICONST_2 or ILOAD_1
     * @return first InstructionHandle
     */
    protected InstructionHandle createThrowException(
        String newException,
        String message,
        Instruction intMessage)
    {
        InstructionHandle result;
        result = il.append(factory.createNew(newException));
        il.append(InstructionConstants.DUP);
        il.append(factory.createNew(Type.STRINGBUFFER));
        il.append(InstructionConstants.DUP);
        il.append(new LDC(classGen.getConstantPool().addString(message)));
        il.append(
            factory.createInvoke(
                Type.STRINGBUFFER.getClassName(),
                Constants.CONSTRUCTOR_NAME,
                Type.VOID,
                new Type[] { Type.STRING },
                Constants.INVOKESPECIAL));
        il.append(intMessage);
        il.append(
            factory.createInvoke(
                Type.STRINGBUFFER.getClassName(),
                "append",
                Type.STRINGBUFFER,
                new Type[] { Type.INT },
                Constants.INVOKEVIRTUAL));
        il.append(
            factory.createInvoke(
                Type.STRINGBUFFER.getClassName(),
                "toString",
                Type.STRING,
                Type.NO_ARGS,
                Constants.INVOKEVIRTUAL));
        il.append(
            factory.createInvoke(
                ClassEnhancer.CN_IllegalArgumentException,
                Constants.CONSTRUCTOR_NAME,
                Type.VOID,
                new Type[] { Type.STRING },
                Constants.INVOKESPECIAL));
        il.append(InstructionConstants.ATHROW);
        return result;
    }

    /**
     * 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.BCELClassMethod

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.