Package cn.wensiqun.asmsupport.utils

Source Code of cn.wensiqun.asmsupport.utils.ClassUtils

package cn.wensiqun.asmsupport.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.EmptyVisitor;

import cn.wensiqun.asmsupport.clazz.AClass;
import cn.wensiqun.asmsupport.clazz.AClassFactory;
import cn.wensiqun.asmsupport.entity.MethodEntity;
import cn.wensiqun.asmsupport.loader.ASMClassLoader;


/**
*
* @author 温斯群(Joe Wen)
*
*/
public class ClassUtils extends org.apache.commons.lang3.ClassUtils {
 
  /** 基本类型Class */
  static Map<String, Class<?>> primitivesToClasses;

    static
    {
    HashMap<String, Class<?>> tmp = new HashMap<String, Class<?>>();
    tmp.put( "boolean", boolean.class );
    tmp.put( "int", int.class );
    tmp.put( "char", char.class );
    tmp.put( "short", short.class );
    tmp.put( "int", int.class );
    tmp.put( "long", long.class );
    tmp.put( "float", float.class );
    tmp.put( "double", double.class );
    tmp.put( "void", void.class );
   
    /*class description*/
    tmp.put( "Z", boolean.class );
    tmp.put( "B", byte.class );
    tmp.put( "C", char.class );
    tmp.put( "S", short.class );
    tmp.put( "I", int.class );
    tmp.put( "J", long.class );
    tmp.put( "F", float.class );
    tmp.put( "D", double.class );
    tmp.put( "V", void.class );

      primitivesToClasses = Collections.unmodifiableMap( tmp );
    }
 
    /**
     *
     * @param cls
     * @return
     */
    public static Class<?> getRootComponentType(Class<?> cls){
        if(cls.isArray()){
            return getRootComponentType(cls.getComponentType());
        }else{
            return cls;
        }
    }
   
    /**
     *
     * @param arrayClass
     * @return
     */
    public static int getDimension(Class<?> arrayClass){
      if(arrayClass.isArray()){
        return StringUtils.findAllIndexes(arrayClass.getName(), "[").length;
      }else{
        return 0;
      }
    }
   
    /**
     * determine cls1 is super of cls2
     * @param cls1
     * @param cls2
     * @return
     */
    public static boolean isSuper(Class<?> cls1, Class<?> cls2) {
        if (cls1.equals(cls2.getSuperclass())) {
            return true;
        } else {
            return isSuper(cls1, cls2.getSuperclass());
        }
    }

    public static Class<?> getMethodOwner(Class<?> owner, String name,
            Class<?> arguments) {
        for (; !owner.equals(Object.class); owner = owner.getSuperclass()) {
        }
        return owner;
    }

    /**
     *
     * @param owner
     * @param innerCls
     * @return
     */
    public static boolean isDirectInnerClass(Class<?> owner, Class<?> innerCls) {

        String[] clses = StringUtils.split(innerCls.getName(),
                INNER_CLASS_SEPARATOR_CHAR);

        if (clses.length > 1) {
            if (clses[clses.length - 2].equals(owner.getName())) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断innerCls是否是owner的内部类
     *
     * @param owner
     * @param innerCls
     * @return
     */
    public static boolean isInnerClass(Class<?> owner, Class<?> innerCls) {
        int ownerIndex = innerCls.getName().indexOf(owner.getName());

        int separatorIndex = innerCls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR);

        if (ownerIndex >= 0 && separatorIndex > 0 && ownerIndex < separatorIndex) {
            return true;
        }

        return false;
    }
   
    /**
   * 通过className获取class实例,这里的参数可以是int,char的那个基本类型
   * @param className
   * @return
   * @throws ClassNotFoundException
   */
  public static Class<?> forName(String className) throws ClassNotFoundException {
    try {
     
      Class<?> clazz = primitivesToClasses.get(className);
      if(clazz != null){
        return clazz;
      }
     
      if(className.startsWith("[")){
        className = StringUtils.replace(className, "/", ".");
      }else if(className.startsWith("L")){
        className = StringUtils.substring(className, 1, className.length() - 1);
        className = StringUtils.replace(className, "/", ".");
      }
     
      return Class.forName(className);
    } catch (ClassNotFoundException e) {
      Class<?> cls = (Class<?>) primitivesToClasses.get(className);
      if(cls != null){
        return cls;
      }else{
        //chech for internal name
        className = StringUtils.replace(className, "/", ".");
        try{
          return Class.forName(className);
        } catch (ClassNotFoundException e1) {
          throw e;
        }
      }
    }
  }
 
  /**
   *
   * @param sourceClass
   * @return
   */
  public static List<List<Class<?>>> getClassUpwardsRoute(Class<?> sourceClass){
    return getClassUpwardsRoute(sourceClass, null);
  }

  /**
   *
   * @param sourceClass
   * @param destionClass
   * @return
   */
  public static List<List<Class<?>>> getClassUpwardsRoute(Class<?> sourceClass, Class<?> destionClass){
    List<List<Class<?>>> list = new ArrayList<List<Class<?>>>();
    getClassUpwardsRoute(list, null, sourceClass, destionClass);
   
    List<List<Class<?>>> allRoute = new ArrayList<List<Class<?>>>();
    for(int i=0; i<list.size(); i++){
      List<Class<?>> route = list.get(i);
      if(destionClass == null || route.get(route.size() - 1).equals(destionClass)){
        allRoute.add(route);
      }
    }
   
    return allRoute;
  }
 
    private static void getClassUpwardsRoute(List<List<Class<?>>> allRoutes, List<Class<?>> currentRoute, Class<?> currentClass, Class<?> destionClass){
      if(currentClass == null){
        return;
      }
     
      if(currentRoute == null){
        currentRoute = new ArrayList<Class<?>>();
        allRoutes.add(currentRoute);
      }
     
        currentRoute.add(currentClass);
     
      if(currentClass.equals(destionClass)){
        return;
      }
     
        Class<?>[] interfaces = currentClass.getInterfaces();
     
      if(ArrayUtils.isNotEmpty(interfaces)){
        for(Class<?> inter : interfaces){
          List<Class<?>> newRoute = new ArrayList<Class<?>>();
          CollectionUtils.addAll(newRoute, currentRoute.iterator());
          allRoutes.add(newRoute);
          getClassUpwardsRoute(allRoutes, newRoute, inter, destionClass);
        }
      }
   
      getClassUpwardsRoute(allRoutes, currentRoute, currentClass.getSuperclass(), destionClass);
     
  }
 
  /**
   *
   * @param clazz
   * @return
   * @throws IOException
   */
  public static List<MethodEntity> getAllMethod(Class<?> clazz, final String findName) throws IOException{
    final AClass owner = AClassFactory.getProductClass(clazz);
    InputStream classStream = ASMClassLoader.asmClassLoader.getResourceAsStream(clazz.getName().replace('.', '/') + ".class");
    ClassReader cr = new ClassReader(classStream);
    final List<MethodEntity> list = new ArrayList<MethodEntity>();
   
    cr.accept(new ClassAdapter(new EmptyVisitor()){

      @Override
      public MethodVisitor visitMethod(int access, String name,
          String desc, String signature, String[] exceptions) {
        if((StringUtils.isEmpty(findName) || name.equals(findName))){
         
          if(exceptions == null){
            exceptions = new String[0];
          }
         
          try {
           
            Type[] types = Type.getArgumentTypes(desc);
            AClass[] aclass = new AClass[types.length];
            String[] args = new String[types.length];
            for(int i=0; i<types.length; i++){
              aclass[i] = AClassFactory.getProductClass(forName(types[i].getDescriptor()));
              args[i] = "arg" + i;
            }
           
            AClass returnType = AClassFactory.getProductClass(
                forName(Type.getReturnType(desc).getDescriptor()));
           

            AClass[] exceptionArray = new AClass[exceptions.length];
            for(int i=0; i<exceptions.length; i++){
              exceptionArray[i] = AClassFactory.getProductClass(forName(exceptions[i]));
            }
           
            MethodEntity me = new MethodEntity(
                  name, owner, owner, aclass, args, returnType, exceptionArray, access);
           
            list.add(me);
          } catch (ClassNotFoundException e) {
            e.printStackTrace();
          }
        }
        return super.visitMethod(access, name, desc, signature, exceptions);
      }
     
    }, 0);
   
    return list;
  }

}
TOP

Related Classes of cn.wensiqun.asmsupport.utils.ClassUtils

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.