All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adrninistrator.javacg.parser.JarEntryPreHandle2Parser Maven / Gradle / Ivy

package com.adrninistrator.javacg.parser;

import com.adrninistrator.javacg.common.JavaCGConstants;
import com.adrninistrator.javacg.conf.JavaCGConfInfo;
import com.adrninistrator.javacg.dto.classes.ClassExtendsInfo;
import com.adrninistrator.javacg.dto.jar.JarInfo;
import com.adrninistrator.javacg.dto.method.MethodArgReturnTypes;
import com.adrninistrator.javacg.spring.UseSpringBeanByAnnotationHandler;
import com.adrninistrator.javacg.util.JavaCGByteCodeUtil;
import com.adrninistrator.javacg.util.JavaCGClassMethodUtil;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.commons.lang3.ArrayUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author adrninistrator
 * @date 2022/9/14
 * @description: 解析jar包中的文件,第二次预处理
 */
public class JarEntryPreHandle2Parser extends AbstractJarEntryParser {

    private final Set classExtendsSet = new HashSet<>(JavaCGConstants.SIZE_100);

    private Map> classExtendsImplMethodWithArgTypesMap;
    private Map> interfaceMethodWithArgTypesMap;
    private Map classAndSuperMap;
    private Map classExtendsInfoMap;
    private Map> childrenClassMap;
    private Set interfaceExtendsSet;
    private Map> interfaceExtendsInfoMap;
    private Map> childrenInterfaceMap;
    private Set allClassNameSet;

    private final UseSpringBeanByAnnotationHandler useSpringBeanByAnnotationHandler;

    public JarEntryPreHandle2Parser(JavaCGConfInfo javaCGConfInfo, Map jarInfoMap, UseSpringBeanByAnnotationHandler useSpringBeanByAnnotationHandler) {
        super(javaCGConfInfo, jarInfoMap);
        this.useSpringBeanByAnnotationHandler = useSpringBeanByAnnotationHandler;
    }

    @Override
    public void init() {
        // 获取涉及继承的类
        for (Map.Entry entry : classAndSuperMap.entrySet()) {
            String superClassName = entry.getValue();
            if (JavaCGClassMethodUtil.isClassInJdk(superClassName) && !allClassNameSet.contains(superClassName)) {
                // 若父类是JDK中的类,且在指定的jar包中未找到,则不添加
                continue;
            }
            String className = entry.getKey();
            classExtendsSet.add(className);
            classExtendsSet.add(superClassName);
        }
    }

    @Override
    protected boolean handleEntry(ZipInputStream zipInputStream, String jarEntryPath) throws IOException {
        // 尝试处理jar包中的class文件
        tryHandleClassEntry(zipInputStream, jarEntryPath);
        // 以上方法返回值不处理
        return true;
    }

    @Override
    protected boolean handleClassEntry(JavaClass javaClass, String jarEntryPath) {
        if (javaClass.isClass()) {
            // 处理类
            // 查找涉及继承的类的信息,需要提前执行,使后续处理方法调用时,classExtendsMethodInfoMap的数据是完整的
            findClassExtendsInfo(javaClass);

            if (javaCGConfInfo.isParseMethodCallTypeValue()) {
                // 记录类中带有Spring相关注解的字段信息
                useSpringBeanByAnnotationHandler.recordClassFieldsWithSpringAnnotation(javaClass);
            }
            return true;
        }

        // 处理接口
        findInterfaceExtendsInfo(javaClass);
        return true;
    }

    // 查找涉及继承的类的信息
    private void findClassExtendsInfo(JavaClass javaClass) {
        String className = javaClass.getClassName();
        if (!classExtendsSet.contains(className) || classExtendsInfoMap.containsKey(className)) {
            // 假如当前类不涉及继承,或当前类已处理过,则不处理
            return;
        }

        String superClassName = javaClass.getSuperclassName();
        List childrenClassList = childrenClassMap.computeIfAbsent(superClassName, k -> new ArrayList<>());
        childrenClassList.add(className);

        classExtendsInfoMap.put(className, new ClassExtendsInfo(javaClass.getAccessFlags(), superClassName));
        // 记录类中可能涉及继承的方法
        Method[] methods = javaClass.getMethods();
        if (ArrayUtils.isNotEmpty(methods)) {
            Map methodArgReturnTypesMap = JavaCGByteCodeUtil.genExtendsClassMethodWithArgTypes(javaClass.getMethods());
            JavaCGClassMethodUtil.copyClassMethodMap(classExtendsImplMethodWithArgTypesMap, className, methodArgReturnTypesMap);
        }
    }

    // 查找涉及继承的接口的信息
    private void findInterfaceExtendsInfo(JavaClass interfaceClass) {
        String interfaceName = interfaceClass.getClassName();
        if (interfaceClass.isAnnotation() ||
                !interfaceExtendsSet.contains(interfaceName) ||
                interfaceExtendsInfoMap.containsKey(interfaceName)) {
            // 假如接口为注解,或当前接口不涉及继承,或当前接口已处理过,则不处理
            return;
        }

        String[] superInterfaceNames = interfaceClass.getInterfaceNames();
        for (String superInterfaceName : superInterfaceNames) {
            List childrenInterfaceList = childrenInterfaceMap.computeIfAbsent(superInterfaceName, k -> new ArrayList<>());
            childrenInterfaceList.add(interfaceName);
        }

        // 记录当前接口的方法信息
        Map methodAttributeMap = new HashMap<>();
        for (Method method : interfaceClass.getMethods()) {
            methodAttributeMap.put(new MethodArgReturnTypes(method.getName(), method.getArgumentTypes(), method.getReturnType()), method.getAccessFlags());
        }
        interfaceExtendsInfoMap.put(interfaceName, Arrays.asList(superInterfaceNames));
        interfaceMethodWithArgTypesMap.put(interfaceName, methodAttributeMap);
    }

    //
    public void setClassExtendsImplMethodWithArgTypesMap(Map> classExtendsImplMethodWithArgTypesMap) {
        this.classExtendsImplMethodWithArgTypesMap = classExtendsImplMethodWithArgTypesMap;
    }

    public void setInterfaceMethodWithArgTypesMap(Map> interfaceMethodWithArgTypesMap) {
        this.interfaceMethodWithArgTypesMap = interfaceMethodWithArgTypesMap;
    }

    public void setClassAndSuperMap(Map classAndSuperMap) {
        this.classAndSuperMap = classAndSuperMap;
    }

    public void setClassExtendsInfoMap(Map classExtendsInfoMap) {
        this.classExtendsInfoMap = classExtendsInfoMap;
    }

    public void setChildrenClassMap(Map> childrenClassMap) {
        this.childrenClassMap = childrenClassMap;
    }

    public void setInterfaceExtendsSet(Set interfaceExtendsSet) {
        this.interfaceExtendsSet = interfaceExtendsSet;
    }

    public void setInterfaceExtendsInfoMap(Map> interfaceExtendsInfoMap) {
        this.interfaceExtendsInfoMap = interfaceExtendsInfoMap;
    }

    public void setChildrenInterfaceMap(Map> childrenInterfaceMap) {
        this.childrenInterfaceMap = childrenInterfaceMap;
    }

    public void setAllClassNameSet(Set allClassNameSet) {
        this.allClassNameSet = allClassNameSet;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy