All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.javassist.expr.MethodCall Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package com.feilong.lib.javassist.expr;

import com.feilong.lib.javassist.CannotCompileException;
import com.feilong.lib.javassist.ClassPool;
import com.feilong.lib.javassist.CtBehavior;
import com.feilong.lib.javassist.CtClass;
import com.feilong.lib.javassist.CtMethod;
import com.feilong.lib.javassist.NotFoundException;
import com.feilong.lib.javassist.bytecode.BadBytecode;
import com.feilong.lib.javassist.bytecode.Bytecode;
import com.feilong.lib.javassist.bytecode.CodeAttribute;
import com.feilong.lib.javassist.bytecode.CodeIterator;
import com.feilong.lib.javassist.bytecode.ConstPool;
import com.feilong.lib.javassist.bytecode.Descriptor;
import com.feilong.lib.javassist.bytecode.MethodInfo;
import com.feilong.lib.javassist.compiler.CompileError;
import com.feilong.lib.javassist.compiler.Javac;

/**
 * Method invocation (caller-side expression).
 */
public class MethodCall extends Expr{

    /**
     * Undocumented constructor. Do not use; internal-use only.
     */
    protected MethodCall(int pos, CodeIterator i, CtClass declaring, MethodInfo m){
        super(pos, i, declaring, m);
    }

    private int getNameAndType(ConstPool cp){
        int pos = currentPos;
        int c = iterator.byteAt(pos);
        int index = iterator.u16bitAt(pos + 1);

        if (c == INVOKEINTERFACE){
            return cp.getInterfaceMethodrefNameAndType(index);
        }
        return cp.getMethodrefNameAndType(index);
    }

    /**
     * Returns the method or constructor containing the method-call
     * expression represented by this object.
     */
    @Override
    public CtBehavior where(){
        return super.where();
    }

    /**
     * Returns the line number of the source line containing the
     * method call.
     *
     * @return -1 if this information is not available.
     */
    @Override
    public int getLineNumber(){
        return super.getLineNumber();
    }

    /**
     * Returns the source file containing the method call.
     *
     * @return null if this information is not available.
     */
    @Override
    public String getFileName(){
        return super.getFileName();
    }

    /**
     * Returns the class of the target object,
     * which the method is called on.
     */
    protected CtClass getCtClass() throws NotFoundException{
        return thisClass.getClassPool().get(getClassName());
    }

    /**
     * Returns the class name of the target object,
     * which the method is called on.
     */
    public String getClassName(){
        String cname;

        ConstPool cp = getConstPool();
        int pos = currentPos;
        int c = iterator.byteAt(pos);
        int index = iterator.u16bitAt(pos + 1);

        if (c == INVOKEINTERFACE){
            cname = cp.getInterfaceMethodrefClassName(index);
        }else{
            cname = cp.getMethodrefClassName(index);
        }

        if (cname.charAt(0) == '['){
            cname = Descriptor.toClassName(cname);
        }

        return cname;
    }

    /**
     * Returns the name of the called method.
     */
    public String getMethodName(){
        ConstPool cp = getConstPool();
        int nt = getNameAndType(cp);
        return cp.getUtf8Info(cp.getNameAndTypeName(nt));
    }

    /**
     * Returns the called method.
     */
    public CtMethod getMethod() throws NotFoundException{
        return getCtClass().getMethod(getMethodName(), getSignature());
    }

    /**
     * Returns the method signature (the parameter types
     * and the return type).
     * The method signature is represented by a character string
     * called method descriptor, which is defined in the JVM specification.
     *
     * @see com.feilong.lib.javassist.CtBehavior#getSignature()
     * @see com.feilong.lib.javassist.bytecode.Descriptor
     * @since 3.1
     */
    public String getSignature(){
        ConstPool cp = getConstPool();
        int nt = getNameAndType(cp);
        return cp.getUtf8Info(cp.getNameAndTypeDescriptor(nt));
    }

    /**
     * Returns the list of exceptions that the expression may throw.
     * This list includes both the exceptions that the try-catch statements
     * including the expression can catch and the exceptions that
     * the throws declaration allows the method to throw.
     */
    @Override
    public CtClass[] mayThrow(){
        return super.mayThrow();
    }

    /**
     * Returns true if the called method is of a superclass of the current
     * class.
     */
    public boolean isSuper(){
        return iterator.byteAt(currentPos) == INVOKESPECIAL && !where().getDeclaringClass().getName().equals(getClassName());
    }

    /*
     * Returns the parameter types of the called method.
     * 
     * public CtClass[] getParameterTypes() throws NotFoundException {
     * return Descriptor.getParameterTypes(getMethodDesc(),
     * thisClass.getClassPool());
     * }
     */

    /*
     * Returns the return type of the called method.
     * 
     * public CtClass getReturnType() throws NotFoundException {
     * return Descriptor.getReturnType(getMethodDesc(),
     * thisClass.getClassPool());
     * }
     */

    /**
     * Replaces the method call with the bytecode derived from
     * the given source text.
     *
     * 

* $0 is available even if the called method is static. * * @param statement * a Java statement except try-catch. */ @Override public void replace(String statement) throws CannotCompileException{ thisClass.getClassFile(); // to call checkModify(). ConstPool constPool = getConstPool(); int pos = currentPos; int index = iterator.u16bitAt(pos + 1); String classname, methodname, signature; int opcodeSize; int c = iterator.byteAt(pos); if (c == INVOKEINTERFACE){ opcodeSize = 5; classname = constPool.getInterfaceMethodrefClassName(index); methodname = constPool.getInterfaceMethodrefName(index); signature = constPool.getInterfaceMethodrefType(index); }else if (c == INVOKESTATIC || c == INVOKESPECIAL || c == INVOKEVIRTUAL){ opcodeSize = 3; classname = constPool.getMethodrefClassName(index); methodname = constPool.getMethodrefName(index); signature = constPool.getMethodrefType(index); }else{ throw new CannotCompileException("not method invocation"); } Javac jc = new Javac(thisClass); ClassPool cp = thisClass.getClassPool(); CodeAttribute ca = iterator.get(); try{ CtClass[] params = Descriptor.getParameterTypes(signature, cp); CtClass retType = Descriptor.getReturnType(signature, cp); int paramVar = ca.getMaxLocals(); jc.recordParams(classname, params, true, paramVar, withinStatic()); int retVar = jc.recordReturnType(retType, true); if (c == INVOKESTATIC){ jc.recordStaticProceed(classname, methodname); }else if (c == INVOKESPECIAL){ jc.recordSpecialProceed(Javac.param0Name, classname, methodname, signature, index); }else{ jc.recordProceed(Javac.param0Name, methodname); } /* * Is $_ included in the source code? */ checkResultValue(retType, statement); Bytecode bytecode = jc.getBytecode(); storeStack(params, c == INVOKESTATIC, paramVar, bytecode); jc.recordLocalVariables(ca, pos); if (retType != CtClass.voidType){ bytecode.addConstZero(retType); bytecode.addStore(retVar, retType); // initialize $_ } jc.compileStmnt(statement); if (retType != CtClass.voidType){ bytecode.addLoad(retVar, retType); } replace0(pos, bytecode, opcodeSize); }catch (CompileError e){ throw new CannotCompileException(e); }catch (NotFoundException e){ throw new CannotCompileException(e); }catch (BadBytecode e){ throw new CannotCompileException("broken method"); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy