Package com.onpositive.instrumentation.tasks

Source Code of com.onpositive.instrumentation.tasks.Instrumentor

package com.onpositive.instrumentation.tasks;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.EmptyVisitor;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;

import com.onpositive.instrumentation.processors.ClassProcessingParticipant;
import com.onpositive.instrumentation.processors.ClassProcessor;
import com.onpositive.instrumentation.processors.InstrumentationContributor;

public class Instrumentor {

  private final class Checker extends EmptyVisitor {
    boolean instrumented = false;

    public FieldVisitor visitField(int access, String name, String desc,
        String signature, Object value) {
      if (name.equals("ON_POSITIVE_INSTRUMENTED")) {
        instrumented = true;
      }
      return super.visitField(access, name, desc, signature, value);
    }
  }

  private final class MC extends ClassProcessingParticipant {
    private final HashSet<String> notSkip;

    private MC(HashSet<String> notSkip) {
      this.notSkip = notSkip;
    }

    public boolean isInterestedIn(ClassReader reader) {
      return true;
    }

    public void visitField(int access, String name, String desc,
        String signature, Object value) {
      if (name.equals("PROFILER_INSTRUMENTED")) {

      }
      super.visitField(access, name, desc, signature, value);
    }

    public InstrumentationContributor getInstrumentationContributor(
        int access, String name, String desc, String signature,
        String[] exceptions, GeneratorAdapter adapter) {
      final String mn = name + "." + desc;
      if (name.equals("<init>")) {
        notSkip.add(mn);
      }
      if (name.equals("<clinit>")) {
        notSkip.add(mn);
      }
      return new InstrumentationContributor(adapter) {

        public void visitJumpInsn(int opcode, Label label) {
          notSkip.add(mn);
          super.visitJumpInsn(opcode, label);
        }

        public void visitInsn(int opcode) {
          if (opcode == Opcodes.ATHROW) {
            notSkip.add(mn);
          }
          super.visitInsn(opcode);
        }

        public void visitMethodInsn(int opcode, String owner,
            String name, String desc) {
          notSkip.add(mn);
          super.visitMethodInsn(opcode, owner, name, desc);
        }

        public void visitTryCatchBlock(Label start, Label end,
            Label handler, String type) {
          notSkip.add(mn);
          super.visitTryCatchBlock(start, end, handler, type);
        }

      };
    }
  }

  public static final String D_TEMP_CD = "D:/tempCd";

  CallDictionary dict;
  IJavaProject jprj;

  HashMap<String, IType> types = new HashMap<String, IType>();

  public boolean isBinary(String type) {
    IType iType = types.get(type);
    if (iType != null) {
      return iType.isBinary();
    }
    try {
      iType = jprj.findType(type.replace('/', '.').replace('$', '.'));
      if (iType != null) {
        types.put(type, iType);
        return iType.isBinary();
      }

    } catch (JavaModelException e) {

    }
    int indexOf = type.indexOf('$');
    if (indexOf != -1) {
      return isBinary(type.substring(0, indexOf));
    }
    return false;
  }

  public Instrumentor(CallDictionary dict, IJavaProject project) {
    this.dict = dict;
    jprj = project;
  }

  public Instrumentor() {
    this.dict = new CallDictionary();
  }

  static Type methodTrap = Type
      .getObjectType("com/onpositive/traps/Profiler");
  static Method enterMethod = Method.getMethod("void enterBinaryCall(int)");
  static Method exitMethod = Method.getMethod("void exitBinaryCall(int)");

  public void instrumentClass1(IFile f) throws IOException, CoreException {
    if (!f.exists()) {
      return;
    }
    BufferedInputStream bufferedInputStream = new BufferedInputStream(
        f.getContents());
    ByteArrayOutputStream stream = new ByteArrayOutputStream((int) 10000);
    try {
      while (bufferedInputStream.available() >= 0) {
        int k = bufferedInputStream.read();
        if (k == -1) {
          break;
        } else {
          stream.write(k);
        }
      }
    } finally {
      bufferedInputStream.close();
    }
    byte[] originalBytes = stream.toByteArray();
    ClassReader classReader = new ClassReader(originalBytes);
    int access = classReader.getAccess();
    if( (access & Opcodes.ACC_INTERFACE) != 0){
      return;
    }
    Checker classVisitor = new Checker();
    classReader.accept(classVisitor, 0);
    if (classVisitor.instrumented) {
      // System.out.println("Instrumented:"+f.getName());
      return;
    }
    String className = classReader.getClassName();

    if (className.contains("client")) {
      return;
    }
    if (className.startsWith("com/onpositive/gae")) {
      return;
    }
    if (className.startsWith("com/onpositive/traps")) {
      return;
    }
    // HashSet<IMethod> rootMethods = new HashSet<IMethod>();
    // try {
    // IType findType = jprj.findType(className.replace('/', '.'));
    // determineRoots(rootMethods, findType);
    // } catch (JavaModelException e) {
    // return;
    // }
    // if (className.contains("client")) {
    // return;
    // }
    byte[] processClass = null;
    ClassProcessor p = new ClassProcessor();
    final HashSet<String> notSkip = new HashSet<String>();
    MC participant = new MC(notSkip);
    p.addParticipant(participant);
    HashSet<String> pr = new HashSet<String>();
    pr.add("java/");
    p.addParticipant(new CallTracerParticipant(this, pr));

    // ClassTransformer pa = new
    // MethodEnterExitHookTransformer(this,notSkip);

    processClass = p.processClass(originalBytes);
    if (processClass == null) {
      processClass = originalBytes;
    }
    if (true) {
      ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES
          | ClassWriter.COMPUTE_MAXS);

      // pa.setTarget(writer);

      ClassReader reader = new ClassReader(processClass);     
      CustomClassInstrumentator pa = new CustomClassInstrumentator(this,writer,className);
      reader.accept(pa, ClassReader.SKIP_FRAMES);
      processClass = writer.toByteArray();
    }
    if (processClass != null) {
      f.setContents(new ByteArrayInputStream(processClass), true, false,
          new NullProgressMonitor());
    }
  }

}
TOP

Related Classes of com.onpositive.instrumentation.tasks.Instrumentor

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.