Package org.nutz.aop.asm

Source Code of org.nutz.aop.asm.ClassY

package org.nutz.aop.asm;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.nutz.aop.AopCallback;
import org.nutz.repo.org.objectweb.asm.ClassWriter;
import org.nutz.repo.org.objectweb.asm.MethodVisitor;
import org.nutz.repo.org.objectweb.asm.Opcodes;
import org.nutz.repo.org.objectweb.asm.Type;

/**
*
* @author wendal(wendal1985@gmail.com)
*
*/
class ClassY implements Opcodes {

  ClassWriter cw;

  String myName;

  String enhancedSuperName;

  Method[] methodArray;

  Constructor<?>[] constructors;

  ClassY(Class<?> klass, String myName, Method[] methodArray, Constructor<?>[] constructors) {
    this.myName = myName.replace('.', '/');
    this.enhancedSuperName = klass.getName().replace('.', '/');
    this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    cw.visitAsmClassAgent.CLASS_LEVEL,
          ACC_PUBLIC,
          this.myName,
          null,
          enhancedSuperName,
          getParentInterfaces(klass));
    this.methodArray = methodArray;
    this.constructors = constructors;
  }

  String[] getParentInterfaces(Class<?> xClass) {
    Class<?>[] its = xClass.getInterfaces();
    if (its == null || its.length == 0)
      return new String[]{AopCallback.class.getName().replace('.', '/')};
    else {
      String[] iii = new String[its.length + 1];
      for (int i = 0; i < its.length; i++)
        iii[i] = its[i].getName().replace('.', '/');
      iii[its.length] = AopCallback.class.getName().replace('.', '/');
      return iii;
    }
  }

  String[] convertExp(Class<?>[] expClasses) {
    if (expClasses.length == 0)
      return null;
    String[] results = new String[expClasses.length];
    for (int i = 0; i < results.length; i++)
      results[i] = expClasses[i].getName().replace('.', '/');
    return results;
  }

  int getAccess(int modify) {
    if (Modifier.isProtected(modify))
      return ACC_PROTECTED;
    if (Modifier.isPublic(modify))
      return ACC_PUBLIC;
    return 0x00;
  }

  static int findMethodIndex(String name, String desc, Method[] methods) {
    for (int i = 0; i < methods.length; i++) {
      Method method = methods[i];
      if (Type.getMethodDescriptor(method).equals(desc) && method.getName().equals(name))
        return i;
    }
    return -1;// 是否应该抛出异常呢?应该不可能发生的
  }

  void addConstructors() {
    for (Constructor<?> constructor : constructors) {
      String[] expClasses = convertExp(constructor.getExceptionTypes());
      String desc = Type.getConstructorDescriptor(constructor);
      int access = getAccess(constructor.getModifiers());
      MethodVisitor mv = cw.visitMethod(access, "<init>", desc, null, expClasses);
      new ChangeToChildConstructorMethodAdapter(mv, desc, access, enhancedSuperName).visitCode();
    }
  }

  byte[] toByteArray() {
    addField();
    addConstructors();
    addAopMethods();
    enhandMethod();
    return cw.toByteArray();
  }

  private void enhandMethod() {
    for (Method method : methodArray) {
      String methodName = method.getName();
      String methodDesc = Type.getMethodDescriptor(method);
      int methodAccess = getAccess(method.getModifiers());
      MethodVisitor mv = cw.visitMethodmethodAccess,
                        methodName,
                        methodDesc,
                        null,
                        convertExp(method.getExceptionTypes()));
      int methodIndex = findMethodIndex(methodName, methodDesc, methodArray);
      new AopMethodAdaptermv,
                  methodAccess,
                  methodName,
                  methodDesc,
                  methodIndex,
                  myName,
                  enhancedSuperName).visitCode();
    }
  }

  private void addAopMethods() {
    new AopInvokeAdpter(methodArray,
              cw.visitMethodACC_PUBLIC,
                      "_aop_invoke",
                      "(I[Ljava/lang/Object;)Ljava/lang/Object;",
                      null,
                      null),
              ACC_PUBLIC,
              "invoke",
              "(I[Ljava/lang/Object;)Ljava/lang/Object;",
              0,
              myName,
              enhancedSuperName).visitCode();
  }

  private void addField() {
    cw.visitFieldACC_PRIVATE + ACC_STATIC,
        AsmClassAgent.MethodArray_FieldName,
        "[Ljava/lang/reflect/Method;",
        null,
        null).visitEnd();
    cw.visitFieldACC_PRIVATE + ACC_STATIC,
        AsmClassAgent.MethodInterceptorList_FieldName,
        "[Ljava/util/List;",
        "[Ljava/util/List<Lorg/nutz/aop/MethodInterceptor;>;",
        null).visitEnd();
  }

  static <T> byte[] enhandClassClass<T> kclass,
                      String myName,
                      Method[] methodArray,
                      Constructor<?>[] constructors) {
    return new ClassY(kclass, myName, methodArray, constructors).toByteArray();
  }
}
TOP

Related Classes of org.nutz.aop.asm.ClassY

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.