Package org.shiftone.jrat.inject.bytecode.asm

Source Code of org.shiftone.jrat.inject.bytecode.asm.InjectClassVisitor

package org.shiftone.jrat.inject.bytecode.asm;

import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import org.shiftone.jrat.inject.bytecode.InjectorException;
import org.shiftone.jrat.inject.bytecode.InjectorStrategy;
import org.shiftone.jrat.inject.bytecode.Modifier;
import org.shiftone.jrat.util.VersionUtil;
import org.shiftone.jrat.util.log.Logger;
import java.util.Date;

public class InjectClassVisitor extends ClassAdapter implements Constants, Opcodes {

  private static final Logger LOG = Logger.getLogger(InjectClassVisitor.class);
  private int handlerCount;
  private Type classType;
  private GeneratorAdapter initializer;

  public InjectClassVisitor(ClassVisitor visitor) {

    super(visitor);
  }

  public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {

    handlerCount = 0;
    classType = Type.getType("L" + name.replace('.', '/') + ";");
    super.visit(version, access, name, signature, superName, interfaces);
    initializer = addInitializer();
  }

  private GeneratorAdapter addInitializer() {

    int access = Modifier.PRIVATE_STATIC;
    String descriptor = "()V";
    MethodVisitor initMethodVisitor = super.visitMethod(access, initializeName, descriptor, null, null);
    GeneratorAdapter initializer = new GeneratorAdapter(initMethodVisitor, access, initializeName, descriptor);
    initMethodVisitor.visitCode();
    return initializer;
  }

  public void visitEnd() {

    initializer.returnValue();
    initializer.endMethod();
    addCommentField();
    super.visitEnd();
  }

  private void addCommentField() {

    FieldVisitor commentField = super.visitField(Modifier.PRIVATE_STATIC_FINAL,
        InjectorStrategy.COMMENT_FIELD_NAME,
        "Ljava/lang/String;",
        null,
        "Class enhanced on " + new Date() + " w/ version JRat v" + VersionUtil.getBuiltOn() + " built on "
            + VersionUtil.getBuiltOn());
    commentField.visitEnd();
  }

  public FieldVisitor visitField(final int access, final String name, final String desc, final String signature,
      final Object value) {

    if (name.equals(InjectorStrategy.COMMENT_FIELD_NAME)) {
      throw new InjectorException("this class was previously injected by JRat");
    }
    return super.visitField(access, name, desc, signature, value);
  }

  private void addMethodHandlerField(String fieldName, String methodName, String descriptor) {

    FieldVisitor handler = super.visitField(Modifier.PRIVATE_STATIC_FINAL,
        fieldName,
        MethodHandler.TYPE.getDescriptor(),
        null,
        null);
    handler.visitEnd();
    initializer.push(classType.getClassName());
    initializer.push(methodName);
    initializer.push(descriptor);
    initializer.invokeStatic(HandlerFactory.TYPE, HandlerFactory.getMethodHandler);
    initializer.putStatic(classType, fieldName, MethodHandler.TYPE);
  }

  public void pushThis(GeneratorAdapter adapter, boolean isStatic) {

    if (isStatic) {
      adapter.push("test");
    } else {
      adapter.loadThis();
    }
  }

  public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {

    if (name.equals("<clinit>") || name.equals("<init>") || Modifier.isAbstract(access)
        || Modifier.isNative(access)) {
      // LOG.debug("skipping " + name);
      return super.visitMethod(access, name, descriptor, signature, exceptions);
    }
    int index = (handlerCount++);
    String handlerFieldName = InjectorStrategy.HANDLER_PREFIX + index;
    String targetMethodName = name + InjectorStrategy.METHOD_POSTFIX;
    addMethodHandlerField(handlerFieldName, name, descriptor);
    // -- [ Proxy Method ] --
    {
      Method method = new Method(name, descriptor);
      MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
      ProxyMethodVisitor visitor = new ProxyMethodVisitor(access,
          method,
          mv,
          classType,
          targetMethodName,
          handlerFieldName);
      visitor.visitCode();
      visitor.visitEnd();
    }
    // -- [ Target Method ] --
    return super.visitMethod(Modifier.makePrivate(access), targetMethodName, descriptor, signature, exceptions);
  }
}
TOP

Related Classes of org.shiftone.jrat.inject.bytecode.asm.InjectClassVisitor

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.