解析jar包以及将.class文件转换成java类型



import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;

import java.io.File;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ServiceDiscovery {

    public static List<ServiceGroup> discovery(File jar) {
        List<ServiceGroup> serviceGroupList = Lists.newArrayList();
        try {
            JarFile jarFile = new JarFile(jar);
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = entries.nextElement();
                if (jarEntry.getName().endsWith(".class")) {
                    //读取到内存中,然后用asm进行解析.判断是否为接口定义.
                    try (InputStream input = jarFile.getInputStream(jarEntry)) {
                        byte[] classBuff = new byte[(int) jarEntry.getSize()];
                        IOUtils.read(input, classBuff);

                        ClassReader reader = new ClassReader(classBuff);
                        if ((reader.getAccess() & Opcodes.ACC_INTERFACE) != 0) {
                            String serviceName = TypeDescToJavaType.pathToJavaType(jarEntry.getName());
                            System.out.println(serviceName);
                            ServiceDissect serviceDissect = new ServiceDissect(serviceName);
                            parseService(reader, serviceDissect, serviceName);
                            if (CollectionUtils.isNotEmpty(serviceDissect.getServiceGroup().getServices())) {
                                serviceGroupList.add(serviceDissect.getServiceGroup());
                            }
                        }
                    }
                }
            }

            System.out.println("=========== 接口服务解析结果 ============");
            serviceGroupList.forEach((s) -> System.out.println(s));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return serviceGroupList;
    }

    /**
     * 解析reader中每一个方法,对于public的方法,打印出来.
     * @param reader
     * @param serviceDissect
     * @param serviceName
     */
    private static void parseService(ClassReader reader, ServiceDissect serviceDissect, String serviceName) {
        reader.accept(new ClassVisitor(Opcodes.ASM6) {
            @Override
            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                System.out.println(desc + "|" + visible);
                return super.visitAnnotation(desc, visible);
            }

            @Override
            public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
                System.out.println("visitTypeAnnotation:" + desc + "|" + visible);
                return super.visitTypeAnnotation(typeRef, typePath, desc, visible);
            }

            @Override
            public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
                System.out.println("\n");
                System.out.println(access + "|" + name + "|" + desc + "|" + signature);
                int left = desc.indexOf('(');
                int right = desc.indexOf(')');
                serviceDissect.onMethodBegin(name, desc.substring(left + 1, right), desc.substring(right + 1), serviceName);
                return new MethodAnnotationScanner(serviceDissect);
            }
        }, 0);
    }
}


import java.util.List;

public class ServiceDissect {

    private ServiceGroup serviceGroup;

    private Service activeMethodMeta;

    public ServiceDissect(String className) {
        serviceGroup = new ServiceGroup(className);
    }

    public void onMethodBegin(String name, String param, String returnType, String serviceName) {
        activeMethodMeta = new Service();
        activeMethodMeta.setMethod(name);

        String[] types = param.split(";");
        List<JavaType> typeList = Lists.newArrayList();
        for (String type : types) {
            if (StringUtils.isNotEmpty(type)) {
                typeList.add(TypeDescToJavaType.toJavaType(type));
            }
        }
        activeMethodMeta.setParamTypes(typeList.toArray(new JavaType[typeList.size()]));
        activeMethodMeta.setReturnType(TypeDescToJavaType.toJavaType(returnType));
        activeMethodMeta.setServiceName(serviceName);
    }

    public void onMethodEnd() {
        //默认的情况下认为是TR服务.
        if (activeMethodMeta.getServiceType() == null) {
            activeMethodMeta.setServiceType(ServiceType.TR);
        }
        //把当前服务加到服务列表中
        serviceGroup.getServices().add(activeMethodMeta);
        activeMethodMeta = null;
    }

    public void onRpcAnnotated() {
        activeMethodMeta.setServiceType(ServiceType.RPC);
    }

    /**
     * Getter method for property <tt>serviceGroup</tt>.
     *
     * @return property value of serviceGroup
     */
    public ServiceGroup getServiceGroup() {
        return serviceGroup;
    }

    public void onRpcName(String alias) {
        activeMethodMeta.setAlias(alias);
    }
}


import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;

public class AnnotationScanner extends AnnotationVisitor {
    private ServiceDissect serviceDissect;
`
    public AnnotationScanner(ServiceDissect serviceDissect) {
        super(Opcodes.ASM6);
        this.serviceDissect = serviceDissect;
    }

    @Override
    public void visit(String name, Object value) {
        //System.out.println("name:" + name + ",value:" + value);
        if ("value".equals(name)){
            serviceDissect.onRpcName(value.toString());
        }
        super.visit(name, value);
    }
}


import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;


public class MethodAnnotationScanner extends MethodVisitor {

    private ServiceDissect serviceDissect;

    public MethodAnnotationScanner(ServiceDissect serviceDissect) {
        super(Opcodes.ASM6);
        this.serviceDissect = serviceDissect;
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        //System.out.println("visitAnnotation: desc=" + desc + " visible=" + visible);
        if ("Lcom/888/888/999/annotation/OperationType;".equals(desc)) {
            serviceDissect.onRpcAnnotated();
        }
        return new AnnotationScanner(serviceDissect);
    }

    @Override
    public void visitEnd() {
        //System.out.println("============End of Method==============");
        serviceDissect.onMethodEnd();
        super.visitEnd();
    }
}



public class TypeDescToJavaType {

    /**
     * 把以/分隔的class替换成java类型.
     * @param pathClass
     * @return
     */
    public static String pathToJavaType(String pathClass){
        return pathClass.substring(0, pathClass.lastIndexOf('.')).replace('/', '.');
    }

    /**
     * 把类型描述转换为JavaType
     * @param typeDesc
     * @return
     */
    public static JavaType toJavaType(String typeDesc) {
        JavaType javaType = new JavaType();
        //先检查是否为数组
        int i = 0;
        char[] typeDescChar = typeDesc.toCharArray();
        while (typeDescChar[i] == '[') {
            javaType.setDemision(javaType.getDemision() + 1);
            i++;
            javaType.setArray(true);
        }

        String[][] primiTypeTypeMap = new String[][] {
                {"Z", "Boolean"}, {"C", "Char"}, {"B", "Byte"}, {"S", "Short"},
                {"I", "Integer"}, {"F", "Float"}, {"J", "Long"}, {"D", "Double"}};
        if ('L' == typeDescChar[i]) {
            javaType.setPrimitive(false);
            int lastIdx = typeDesc.lastIndexOf(';') == -1 ? typeDesc.length() : typeDesc.lastIndexOf(';');
            String type = typeDesc.substring(++i, lastIdx);
            if (javaType.isArray()) {
                StringBuilder sb = new StringBuilder(4);
                for (int j = 0; j < javaType.getDemision(); j++) {
                    sb.append("[]");
                }
                javaType.setFullQualifiedName(type.replace('/', '.') + sb.toString());
            } else {
                javaType.setFullQualifiedName(type.replace('/', '.'));
            }
            return javaType;
        } else {
            for (int j = 0; j < primiTypeTypeMap.length; j++) {
                if (primiTypeTypeMap[j][0].charAt(0) == typeDescChar[0]) {
                    javaType.setFullQualifiedName(primiTypeTypeMap[j][1]);
                    return javaType;
                }
            }
            throw new RuntimeException("不能识别的TypeDescription!" + typeDesc);
        }
    }
}


import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class Service {

    /**
     * 服务名称
     */
    private String serviceName;

    /**
     * 方法名称
     */
    private String method;

    /**
     * 参数类型定义
     */
    private JavaType[] paramTypes;

    /**
     * 返回类型
     */
    private JavaType returnType;

    /**
     * 接口类型
     */
    private ServiceType serviceType;

    /**
     * 接口别名
     */
    private String alias;
}


import com.google.common.collect.Lists;
import lombok.Data;

import java.util.List;

@Data
public class ServiceGroup {

    public ServiceGroup(String serviceName) {
        this.serviceName = serviceName;
    }

    /**
     * 提供服务的类名
     */
    private String serviceName;

    /**
     * 提供可调用的接口方法.
     */
    private List<Service> services = Lists.newArrayList();
}


import lombok.Data;


@Data
public class JavaType {

    /**
     * 是否为基本类型
     */
    private boolean isPrimitive;

    /**
     * 是否为数组类型
     */
    private boolean isArray;

    /**
     * 数组的维度
     */
    private int    demision;
    /**
     * 类全名称
     */
    private String fullQualifiedName;
}
List<Service> allService = Lists.newArrayList();
                for (ArtifactResult artifactResult : artifactResults) {
                    List<ServiceGroup> serviceGroups = ServiceDiscovery.discovery(artifactResult.getArtifact().getFile());
                    //服务入库
                    for (ServiceGroup serviceGroup : serviceGroups) {
                        for Service service : serviceGroup.getServices()) {
                           Service dbService = new Service();
                            dbService.setServiceName(serviceGroup.getServiceName());
                            dbService.setMethod(service.getMethod());
                            dbService.setSutId(sutId);
                            dbService.setReturnType(service.getReturnType().getFullQualifiedName());
                            if (service.getParamTypes() != null) {
                                dbService.setParamTypes(StringUtils.join(Lists.newArrayList(
                                        service.getParamTypes()).stream().map((s) -> s.getFullQualifiedName())
                                        .collect(Collectors.toList()), ";"));
                            }
                            if (service.getServiceType() == ServiceType.RPC) {
                                dbService.setServiceType(ServiceType.RPC.getCode());
                                dbService.setDisplayName(service.getAlias().substring(service.getAlias().lastIndexOf('.') + 1));
                            } else if (service.getServiceType() == ServiceType.TR) {
                                dbService.setServiceType(ServiceType.TR.getCode());
                                dbService.setDisplayName(service.getMethod() + ":"
                                        + service.getServiceName().substring(service.getServiceName().lastIndexOf('.') + 1));
                            }
                            allService.add(dbService);

                        }
                    }
                }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值