Package cn.wensiqun.visitor.invoker

Source Code of cn.wensiqun.visitor.invoker.MethodInvokeGrepVisitor

package cn.wensiqun.visitor.invoker;

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

import jw.asmsupport.clazz.AClass;
import jw.asmsupport.clazz.AClassFactory;

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

import cn.wensiqun.entity.invoker.LocalVariableSignature;
import cn.wensiqun.info.InvokeInfo;
import cn.wensiqun.info.InvokeInfo.FunctionInfo;
import cn.wensiqun.utils.CommonUtils;

public class MethodInvokeGrepVisitor extends StackLocalMethodVisitor {
 
 
    private static final Log LOG = LogFactory.getLog(MethodInvokeGrepVisitor.class);

  private List<FunctionInfo> calledFuns;

  private String[] calledFunNames;
 
  private String[] calledFunDescs;
 
  private Class<?>[] calledFunOwners;
 
  private Type     callingFunOwner;
 
  private FunctionInfo   callingFun;
 
  private Map<FunctionInfo, List<InvokeInfo>> invokeInfos;
 
  private ClassLoader classLoader;
 
  public MethodInvokeGrepVisitor(
      int callingFunModifier,
      String callingFunName,
      String callingFunDesc,
      Type callingFunOwner,
      List<LocalVariableSignature> callingFunLocVarSigns,
      List<FunctionInfo> calledFuns,
      Map<FunctionInfo, List<InvokeInfo>> invokeInfoMap,
      ClassLoader classLoader) {
   
    super(callingFunDesc, callingFunModifier, callingFunOwner, callingFunLocVarSigns);
   
    this.calledFuns = calledFuns;
    this.classLoader = classLoader;
   
    this.calledFunNames = new String[calledFuns.size()];//calledFun.getName();
    this.calledFunDescs = new String[calledFuns.size()];//Type.getMethodDescriptor(calledFun);
    this.calledFunOwners = new Class<?>[calledFuns.size()];//calledFun.getDeclaringClass();
   
    for(int i=0, len=calledFuns.size(); i<len; i++){
      FunctionInfo calledFun = calledFuns.get(i);
      this.calledFunNames[i] = calledFun.getName();
      this.calledFunDescs[i] = calledFun.getDescription();
      this.calledFunOwners[i] = calledFun.getDeclaringClass();
    }
   
   
    this.callingFunOwner = callingFunOwner;
    this.invokeInfos = invokeInfoMap;
   
    //reflect to get calling function
    try {
     
      try {
        if (callingFunName.equals("<init>")) {
         
          callingFun = InvokeInfo.buildConstructorFunctionInfo(CommonUtils.reflect2Constructor(callingFunOwner.getDescriptor()
              , callingFunDesc, classLoader));
       
        }else if(callingFunName.equals("<clinit>")){
          Class<?> callingFunOwnerCls = CommonUtils.forName(callingFunOwner.getDescriptor(), true, classLoader);
          callingFun = InvokeInfo.buildStaticFunctionInfo(callingFunOwnerCls);
       
        }else{
         
          callingFun = InvokeInfo.buildCommonFunctionInfo(CommonUtils.reflect2Method(callingFunOwner.getDescriptor(),
              callingFunName, callingFunDesc, classLoader));
       
        }
      } catch (Exception e) {
        LOG.error("cannot get method : " + callingFunName + " cause by : " + e.getMessage());
      }
     
    } catch (Exception e) {
      LOG.error("cannot load class : " + callingFunOwner + " cause by : " + e.getMessage());
    }
   
  }

  @Override
  public void visitMethodInsn(int opcode, String owner, String name, String desc) {
    for(int idx=0, len=calledFuns.size(); idx<len; idx++){
      String calledFunDesc = calledFunDescs[idx];
      String calledFunName = calledFunNames[idx];
      Class<?> calledFunOwner = calledFunOwners[idx];
      FunctionInfo calledFun = calledFuns.get(idx);
     
      if(desc.equals(calledFunDesc) && name.equals(calledFunName)){
        try{
          AClass ownerClass = AClassFactory.getProductClass( CommonUtils.forName(owner.replace("/", "."), true, classLoader));
          AClass byInvokedMethodOwnerAClass = AClassFactory.getProductClass(calledFunOwner);
          if(ownerClass.isChildOrEqual(byInvokedMethodOwnerAClass)){
           
            int argumentsSize = calledFun.getParameterTypes().length;
            List<Type> allTypeInStack = new ArrayList<Type>();
            for(int i=0; i<argumentsSize;i++){
              allTypeInStack.add(stack.get(stack.size() - 1 - i));
            }
           
            Class<?>[] argumentActuallyTypes = new Class<?>[argumentsSize];
            for(int i=argumentsSize; i>0;i--){
              Type typeInStack = allTypeInStack.get(i-1);
              Class<?> argCls = null;
              int sort = typeInStack.getSort();
              switch(sort){
              case 1 :
                    argCls = boolean.class;
                    break;
              case 2 :
                argCls = char.class;
                    break;
              case 3 :
                argCls = byte.class;
                    break;
              case 4 :
                argCls = short.class;
                    break;
              case 5 :
                argCls = int.class;
                    break;
              case 6 :
                argCls = float.class;
                    break;
              case 7 :
                argCls = long.class;
                    break;
              case 8 :
                argCls = double.class;
                    break;
              case 9 :
                argCls = CommonUtils.forName(typeInStack.getDescriptor(), true, classLoader);
                    break;
              default :
                  argCls = CommonUtils.forName(typeInStack.getClassName(), true, classLoader);
                    break;
              }
              argumentActuallyTypes[argumentsSize-i] = argCls;
            }
           
            InvokeInfo invokeInfo = new InvokeInfo(CommonUtils.forName(callingFunOwner.getClassName(), true, classLoader),
                callingFun, calledFun, argumentActuallyTypes, currentLineNumber);
           
            invokeInfos.get(calledFun).add(invokeInfo);
          }
        } catch (Throwable e) {
          LOG.warn("error when extart method invoke information : " + calledFun + " cause by : " + e.getMessage(), e);
          }
      }
    }
   
    super.visitMethodInsn(opcode, owner, name, desc);
  }
 
 

 
}
TOP

Related Classes of cn.wensiqun.visitor.invoker.MethodInvokeGrepVisitor

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.