Package cn.wensiqun.asmsupport.operators.method

Source Code of cn.wensiqun.asmsupport.operators.method.MethodInvoker

package cn.wensiqun.asmsupport.operators.method;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.objectweb.asm.Type;

import cn.wensiqun.asmsupport.Parameterized;
import cn.wensiqun.asmsupport.asm.InstructionHelper;
import cn.wensiqun.asmsupport.block.ProgramBlock;
import cn.wensiqun.asmsupport.clazz.AClass;
import cn.wensiqun.asmsupport.clazz.ArrayClass;
import cn.wensiqun.asmsupport.definition.method.Method;
import cn.wensiqun.asmsupport.definition.variable.IVariable;
import cn.wensiqun.asmsupport.entity.MethodEntity;
import cn.wensiqun.asmsupport.exception.ASMSupportException;
import cn.wensiqun.asmsupport.exception.NoSuchMethod;
import cn.wensiqun.asmsupport.operators.AbstractOperator;
import cn.wensiqun.asmsupport.operators.array.ArrayValue;
import cn.wensiqun.asmsupport.operators.numerical.crement.AbstractCrement;
import cn.wensiqun.asmsupport.utils.AClassUtils;
import cn.wensiqun.asmsupport.utils.ASConstant;
import cn.wensiqun.asmsupport.utils.ModifierUtils;

/**
*
* @author 温斯群(Joe Wen)
*
*/
public abstract class MethodInvoker extends AbstractOperator implements
    Parameterized {

    protected static String METHOD_NAME_INIT = "<init>";
   
    private static Log log = LogFactory.getLog(MethodInvoker.class);

    //protected AClass[] argumentClasses;
    protected String name;
    protected Parameterized[] arguments;
    protected AClass methodOwner;
   
    /** 调用完方法是否需要保存返回值栈 如果是构造方法则是否需要保存新构造的方法的一个引用 */
    private boolean saveReturn;
   
    /** found method entity will be called*/
    protected MethodEntity mtdEntity;
   
    /**
     *
     * @param owner
     * @param name
     * @param arguments
     * @param block
     */
    protected MethodInvoker(ProgramBlock block, AClass owner,
            String name,
            Parameterized[] arguments) {
        super(block);
        this.methodOwner = owner;
        this.name = name;
        this.arguments = arguments;
    }

    /**
     * 将方法的参数入栈
     */
    protected void argumentsToStack() {
      for(int i=0; i<arguments.length; i++){
            Parameterized argu = arguments[i];
            log.debug("push argument to stack");
            if(argu instanceof IVariable){
                ((IVariable) argu).availableFor(this);
            }
            argu.loadToStack(block);
            cast(argu.getParamterizedType(), mtdEntity.getArgClasses()[i]);
        }
    }
   
    private void cast(AClass from, AClass to){
        if(from.isPrimitive() && to.isPrimitive()){
            insnHelper.cast(from.getType(), to.getType());
        }else if(from.isPrimitive()){
            insnHelper.box(from.getType());
        }else if(AClassUtils.isPrimitiveWrapAClass(from) && to.isPrimitive()){
            Type primType = InstructionHelper.getUnBoxedType(from.getType());
            insnHelper.unbox(from.getType());
            insnHelper.cast(primType, to.getType());
        }
    }

    @Override
    protected void beforeInitProperties() {
      AClass[] argumentClasses = new AClass[arguments.length];
        List<AClass> argumentClassList = new ArrayList<AClass>();
        for (int i = 0; i < arguments.length; i++) {
            argumentClassList.add(arguments[i].getParamterizedType());
        }
        argumentClassList.toArray(argumentClasses);
       
      Method currentMethod = block.getMethod();
        if(currentMethod.getMode() == ASConstant.METHOD_CREATE_MODE_MODIFY && name.endsWith(ASConstant.METHOD_PROXY_SUFFIX)){
          mtdEntity = (MethodEntity) currentMethod.getMethodEntity().clone();
            mtdEntity.setName(name);
        }else{
            // 如果是构造方法则返回类型为自己本身
            if (name.equals(METHOD_NAME_INIT)) {
                mtdEntity = methodOwner.availableConstructor(block.getMethodOwner(), argumentClasses);
                if(mtdEntity == null){
                    throw new NoSuchMethod(methodOwner, name, argumentClasses);
                }
            }else{
                mtdEntity = methodOwner.availableMethod(block.getMethodOwner(), name, argumentClasses);
                if(mtdEntity == null){
                    throw new NoSuchMethod(methodOwner, name, argumentClasses);
                }
            }
        }
       
        if(ModifierUtils.isVarargs(mtdEntity.getModifier())){
           
          AClass[] foundMethodArgTypes = mtdEntity.getArgClasses();
         
          if(ArrayUtils.getLength(foundMethodArgTypes) != ArrayUtils.getLength(arguments) ||
             !arguments[ArrayUtils.getLength(arguments) - 1].getParamterizedType().isArray()){
           
            int fixedArgsLen = mtdEntity.getArgClasses().length - 1;//argumentClasses.length - 1;
                Parameterized[] fixedArgs = new Parameterized[fixedArgsLen];
                System.arraycopy(arguments, 0, fixedArgs, 0, fixedArgsLen);

                ArrayValue variableVarifyArauments;
                ArrayClass arrayClass = (ArrayClass)mtdEntity.getArgClasses()[mtdEntity.getArgClasses().length - 1];
                variableVarifyArauments = block.newArrayWithValue(arrayClass,
                       (Parameterized[]) ArrayUtils.subarray(arguments, fixedArgsLen , arguments.length));
                variableVarifyArauments.asArgument();
               
                arguments = (Parameterized[]) ArrayUtils.add(fixedArgs, variableVarifyArauments);
          }
        }

        for(AClass exception : mtdEntity.getExceptions()){
          block.addException(exception);
      }
       
    }

    @Override
    protected void checkOutCrement() {
        for (Parameterized argu : arguments) {
            if(argu instanceof AbstractCrement){
                allCrement.add((AbstractCrement) argu);
            }
        }
    }

    @Override
    protected void checkAsArgument() {
        for (Parameterized argu : arguments) {
            // 将argu从Block的执行队列中删除
            // 因为此时由方法调用负责调用value
            argu.asArgument();
        }
        /*if(variableVarifyArauments != null){
            variableVarifyArauments.asArgument();
        }*/
    }

    public boolean isSaveReference() {
        return saveReturn;
    }
   
    @Override
    public void asArgument() {
        //如果方法调用是作为参数传入给其他参数。那么将此方法调用操作从执行队列中移除
        block.removeExe(this);
    }

    @Override
    public void loadToStack(ProgramBlock block) {
        if(getReturnType().equals(Type.VOID_TYPE)){
            throw new ASMSupportException("cannot push the void return type to stack!");
        }
       
        boolean saveRef = isSaveReference();
        setSaveReference(true);
        this.execute();
        setSaveReference(saveRef);
    }
   
    /*public MethodInvoker invoke(String methodName, Parameterized... arguments) {
        return new MethodInvokeInvoker(block, this, methodName, arguments);
    }*/

    public void setSaveReference(boolean saveReturn) {
        this.saveReturn = saveReturn;
    }
   
    public Type getReturnType() {
        return getReturnClass() != null ? getReturnClass().getType() : Type.VOID_TYPE;
    }

    public final AClass getReturnClass() {
        if(name.equals(METHOD_NAME_INIT)){
            return methodOwner;
        }else if(mtdEntity != null){
            return mtdEntity.getReturnClass();
        }else{
            return AClass.VOID_ACLASS;
        }
    }
   
    protected AClass getActuallyOwner(){
        return mtdEntity.getActuallyOwner();
    }
   
    /**
     *
     * @return
     */
    public int getModifiers() {
        return this.mtdEntity.getModifier();
    }

    @Override
    public AClass getParamterizedType() {
        return getReturnClass();
    }
   
}
TOP

Related Classes of cn.wensiqun.asmsupport.operators.method.MethodInvoker

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.