Package limpidlog.asm1

Source Code of limpidlog.asm1.MyMethodAdapter

//Copyright 2006-2007 Acelet Corporation. All rights reserved.

package limpidlog.asm1;

import java.io.*;
import java.net.*;
import java.util.*;
import limpidlog.org.objectweb.asm.Label;
import limpidlog.org.objectweb.asm.MethodAdapter;
import limpidlog.org.objectweb.asm.MethodVisitor;
import limpidlog.org.objectweb.asm.Opcodes;
import limpidlog.org.objectweb.asm.Type;
import limpidlog.lib.Events;
import limpidlog.lib.Options;

/**
* @author Wei Jiang
*/
public class MyMethodAdapter extends MethodAdapter implements Events, Opcodes {
  int access;
  String methodName;
  String descriptor;
  String classNameWithSlash;
  String sourceFileName;
  Vector memberFieldVector;
  Hashtable lineVariableHashtable;
  Vector labelVector;

  String classNameWithDot;

  Type[] argumentTypes;
  boolean isStatic;
  boolean isInnerClass;
  String methodFullName;

  Type typeOfObject = Type.getType(Object.class);
  boolean containsDebugInfo = false;
  int localVarIndexMax;
  String defaultWhere;
  String functionDescForObject = "(Ljava/lang/Object;)Llimpidlog/log/Log;";
  String functionDescForString = "(Ljava/lang/String;)Llimpidlog/log/Log;";
  int numberOfMemberFields;
  int currentLine = 0;
  int lineNumberVisit = 0;
  int labelIndex = 1;
  Vector localVariableVector;

  protected MyMethodAdapter(MethodVisitor mv, int access, String methodName, String descriptor,
  String classNameWithSlash, String sourceFileName,
  Vector memberFieldVector, Vector labelVector, Hashtable lineVariableHashtable) {
    super(mv);
    this.access = access;
    this.methodName = methodName;
    this.descriptor = descriptor;
    this.classNameWithSlash = classNameWithSlash;
    this.sourceFileName = sourceFileName;
    this.memberFieldVector = memberFieldVector;
    this.labelVector = labelVector;
    this.lineVariableHashtable = lineVariableHashtable;

    if (Options.debug)
      System.out.println("MyMethodAdapter.<init>: " +
                         " access="+access+
                         " methodName="+methodName+
                         " descriptor="+descriptor+
                         " classNameWithSlash="+classNameWithSlash+
                         " sourceFileName="+sourceFileName+
                         " memberFieldVector="+memberFieldVector+
                         " labelVector="+labelVector+
                         " lineVariableHashtable="+lineVariableHashtable);

    classNameWithDot = classNameWithSlash.replace('/', '.');
    methodFullName = classNameWithDot + "." + methodName;
    argumentTypes = Type.getArgumentTypes(descriptor);
    defaultWhere =  methodFullName + "(" + sourceFileName + ")";
    numberOfMemberFields = memberFieldVector.size();

    isStatic = ((access & Opcodes.ACC_STATIC) > 0);

    String baseName = classNameWithSlash.substring(classNameWithSlash.lastIndexOf("/") + 1);
    String theName = sourceFileName.substring(0, sourceFileName.indexOf("."));
    if (theName.equals(baseName) == false)
      isInnerClass = true;

    if (Options.debug)
      System.out.println("MyMethodAdapter.<init>: " +
                         " classNameWithDot="+classNameWithDot+
                         " methodFullName="+methodFullName+
                         " argumentTypes="+argumentTypes+
                         " defaultWhere="+defaultWhere+
                         " numberOfMemberFields="+numberOfMemberFields+
                         " isStatic="+isStatic+
                         " baseName="+baseName+
                         " theName="+theName+
                         " isInnerClass="+isInnerClass);
  }

  protected void addArgument() {
    if (Options.logOnArgument == false)
      return;

    int argIndex = 0;
    if (isStatic == false) {
      argIndex++;
    }

    for (int index = 0; index < argumentTypes.length; index++) {
      String variableName = getLocalVariableName(argIndex);
      if (variableName == null)
        continue;

      Type type = argumentTypes[index];
      int opcode = type.getOpcode(Opcodes.ILOAD);
      String functionDesc = makeFunctionType(type);

      super.visitLdcInsn(variableName);
      super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addName", functionDescForString);
      super.visitVarInsn(opcode, argIndex);
      super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addValue", functionDesc);

      argIndex += type.getSize();
    }
  }

  protected String getLocalVariableName(int index) {
    if (Options.useLocalVariableName == false) {
      return "#" + index;
    }

    if (localVariableVector != null) {
      for (int i = 0; i < localVariableVector.size(); i++) {
        LocalVariable localVariable = (LocalVariable) localVariableVector.get(i);
        if (index == localVariable.index)
          return localVariable.name;
      }
    }
    return null;
  }

  protected Type getTypeFromOpcode(int opcode) {
    switch (opcode) {
    case Opcodes.ISTORE:
      return Type.INT_TYPE;
    case Opcodes.LSTORE:
      return Type.LONG_TYPE;
    case Opcodes.FSTORE:
      return Type.FLOAT_TYPE;
    case Opcodes.DSTORE:
      return Type.DOUBLE_TYPE;
    case Opcodes.ASTORE:
    default:
      return typeOfObject;
    }
  }

  protected String makeFunctionType(String type) {
    if (type.equals("Z") ||
        type.equals("B") ||
        type.equals("C") ||
        type.equals("D") ||
        type.equals("F") ||
        type.equals("I") ||
        type.equals("J") ||
        type.equals("S") ||
        type.equals("[Z") ||
        type.equals("[B") ||
        type.equals("[C") ||
        type.equals("[D") ||
        type.equals("[F") ||
        type.equals("[I") ||
        type.equals("[J") ||
        type.equals("[S"))
      ;
    else
      type = "Ljava/lang/Object;";
    return "(" + type +")Llimpidlog/log/Log;";
  }

  protected String makeFunctionType(Type type) {
    String desc = type.getDescriptor();
    return makeFunctionType(desc);
  }

  protected String makeWhere(int lineNumber) {
    return methodFullName + "(" + sourceFileName + ":" + lineNumber + ")";
  }

  protected void onField(int opcode, String owner, String name, String desc) {
    if (currentLine == 0//generated code, like class$(Person.java:0)
      return;
    if (name.equals("this") || name.startsWith("this$") || isInnerClass)
      return;

    String functionDesc = makeFunctionType(desc);

    super.visitTypeInsn(NEW, "limpidlog/log/Log");
    super.visitInsn(DUP);
    super.visitLdcInsn(makeWhere(currentLine));
    super.visitLdcInsn(EVENT_FIELD);
    super.visitMethodInsn(INVOKESPECIAL, "limpidlog/log/Log", "<init>",
      "(Ljava/lang/String;Ljava/lang/String;)V");
    super.visitLdcInsn(name);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addName", functionDescForString);

    int readOpcode = GETSTATIC;
    if (opcode == PUTFIELD) {
      super.visitVarInsn(ALOAD, 0);
      readOpcode = GETFIELD;
    }
    super.visitFieldInsn(readOpcode, owner, name, desc);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addValue", functionDesc);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "log", "()V");
  }

  protected void onIncrease(int var, int increament) {
    if (currentLine == 0//generated code, like class$(Person.java:0)
      return;

    String variableName = "#" + var;

    String functionDesc = "(I)Llimpidlog/log/Log;";

    super.visitTypeInsn(NEW, "limpidlog/log/Log");
    super.visitInsn(DUP);
    super.visitLdcInsn(makeWhere(currentLine));
    super.visitLdcInsn(EVENT_INCREASE);
    super.visitMethodInsn(INVOKESPECIAL, "limpidlog/log/Log", "<init>",
      "(Ljava/lang/String;Ljava/lang/String;)V");
    super.visitLdcInsn(variableName);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addName", functionDescForString);
    super.visitVarInsn(ILOAD, var);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addValue", functionDesc);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "log", "()V");
  }

  protected void onLabel(Label label) {
    if (labelIndex < labelVector.size()) {
      Label aLabel = (Label) labelVector.get(labelIndex++);
      localVariableVector = (Vector) lineVariableHashtable.get(aLabel);
    }
  }

  protected void onLineNumber(int line, Label start) {
    containsDebugInfo = true;
    currentLine = line;

    super.visitTypeInsn(NEW, "limpidlog/log/Log");
    super.visitInsn(DUP);
    super.visitLdcInsn(makeWhere(line));
    super.visitLdcInsn(EVENT_LINE);
    super.visitMethodInsn(INVOKESPECIAL, "limpidlog/log/Log", "<init>",
      "(Ljava/lang/String;Ljava/lang/String;)V");

    lineNumberVisit++;
    if ((methodName.equals("<clinit>") || methodName.equals("<init>"))) {
      if (lineNumberVisit == 2)
        addArgument();
    } else if (lineNumberVisit == 1) {
      addArgument();
    }

    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "log", "()V");
  }

  protected void onReturn(Type type) {
    if (currentLine == 0//generated code, like class$(Person.java:0)
      return;

    if (localVariableVector != null)
      localVarIndexMax = localVariableVector.size();
    else
      localVarIndexMax = 1;

    String functionDesc = null;
    if (type != null) {
      super.visitVarInsn(type.getOpcode(ISTORE), localVarIndexMax);
      functionDesc = makeFunctionType(type);
    }

    super.visitTypeInsn(NEW, "limpidlog/log/Log");
    super.visitInsn(DUP);
    super.visitLdcInsn(makeWhere(currentLine));
    super.visitLdcInsn(EVENT_RETURN);
    super.visitMethodInsn(INVOKESPECIAL, "limpidlog/log/Log", "<init>",
      "(Ljava/lang/String;Ljava/lang/String;)V");

    if (type != null) {
      super.visitLdcInsn(EVENT_RETURN);
      super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addName", functionDescForString);
      super.visitVarInsn(type.getOpcode(ILOAD), localVarIndexMax);
      super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addValue", functionDesc);
      super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "log", "()V");
      super.visitVarInsn(type.getOpcode(ILOAD), localVarIndexMax);
    } else
      super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "log", "()V");
  }

  protected void onStore(int opcode, int var) {
    if (currentLine == 0//generated code, like class$(Person.java:0)
      return;

    String variableName = getLocalVariableName(var);
    if (variableName == null)
      return;

    Type type = getTypeFromOpcode(opcode);
    String functionDesc = makeFunctionType(type);

    super.visitTypeInsn(NEW, "limpidlog/log/Log");
    super.visitInsn(DUP);
    super.visitLdcInsn(makeWhere(currentLine));
    super.visitLdcInsn(EVENT_STORE);
    super.visitMethodInsn(INVOKESPECIAL, "limpidlog/log/Log", "<init>",
      "(Ljava/lang/String;Ljava/lang/String;)V");
    super.visitLdcInsn(variableName);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addName", functionDescForString);
    super.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "addValue", functionDesc);
    super.visitMethodInsn(INVOKEVIRTUAL, "limpidlog/log/Log", "log", "()V");
  }

  public void visitFieldInsn(int opcode, String owner, String name, String desc) {
    super.visitFieldInsn(opcode, owner, name, desc);

    if (Options.logOnField) {
      if ((opcode == PUTSTATIC) || (opcode == PUTFIELD)) {
        if (owner.equals(classNameWithSlash))
          onField(opcode, owner, name, desc);
      }
    }
  }

  public void visitIincInsn(int var, int increment) {
    super.visitIincInsn(var, increment);

    if (Options.logOnIncrease)
      onIncrease(var, increment);
  }

  public void visitInsn(int opcode) {
    if (Options.logOnReturn) {
      switch (opcode) {
      case RETURN:
        onReturn(null);
        break;
      case ARETURN:
        onReturn(typeOfObject);
        break;
      case DRETURN:
        onReturn(Type.DOUBLE_TYPE);
        break;
      case FRETURN:
        onReturn(Type.FLOAT_TYPE);
        break;
      case IRETURN:
        onReturn(Type.INT_TYPE);
        break;
      case LRETURN:
        onReturn(Type.LONG_TYPE);
        break;
      }
    }
    super.visitInsn(opcode);
  }

  public void visitLabel(Label label) {
    super.visitLabel(label);
    onLabel(label);
  }

  public void visitLineNumber(int line, Label start) {
    super.visitLineNumber(line, start);
    onLineNumber(line, start);
  }

  public void visitMaxs(int maxStack, int maxLocals) {
    super.visitMaxs(maxStack + 4, maxLocals + 2);
  }

  public void visitVarInsn(int opcode, int var) {
    super.visitVarInsn(opcode, var);

    if (Options.logOnStore) {
      if (opcode == ISTORE || opcode == LSTORE || opcode == FSTORE || opcode == DSTORE ||
        opcode == ASTORE) {
        onStore(opcode, var);
      }
    }
  }
}
TOP

Related Classes of limpidlog.asm1.MyMethodAdapter

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.