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

io.github.lab515.utils.ByteRunner Maven / Gradle / Ivy

There is a newer version: 1.0.12
Show newest version
package io.github.lab515.utils;

import jdk.internal.org.objectweb.asm.Type;
import java.lang.reflect.Method;

public class ByteRunner {
    static class RunningContext{
        Class cls;
        Method mtd;
        int mid;
        int skip = 0; // skip 0: NO, 1: SKIP, 2: SKIPPED
        String name;
        String desc;
        int[] inters;
        Object[] interHandlings;
        Calling para;
        public void setValue(Class type, int mid, String name, String desc, int[] interceptors){
            this.cls = type;
            this.mid = mid;
            mtd = null;
            skip = 0;
            this.name = name;
            this.desc = desc;
            this.inters = interceptors;
            this.interHandlings = new Object[inters.length/2];
            if(para == null){
                para = new Calling();
            }
            para.setValue(type, name, desc);
        }
    }

    private static Interceptor[] allInterceptors = null;
    private static ThreadLocal cxt = new ThreadLocal<>(); // store only some flags
    private static Method[] allMethods = new Method[1024]; // good enough



    public static void setHandlers(Interceptor[] interceptors){
        allInterceptors = interceptors;
        ByteShifter.allInterceptors = interceptors;
    }
    private static Method matchMethod(Class type, String name, String desc){
        for (Method mtd : type.getDeclaredMethods()) {
            if(name.equals(mtd.getName()) && desc.equals(Type.getMethodDescriptor(mtd))){
                return mtd;
            }
        }
        return null;
    }

    static Method findMethod(){
        RunningContext rc = cxt.get();
        if(rc == null){
            return null;
        }
        Method m = allMethods[rc.mid];
        if (m == null) {
            m = matchMethod(rc.cls, rc.name,rc.desc);
            m.setAccessible(true);
            allMethods[rc.mid] = m;
            allMethods = allMethods;
        }
        return m;
    }

    public static Object handle(Object target, Object[] args) throws Throwable {
        RunningContext rc = cxt.get();
        if(rc == null || rc.skip == 1){
            return null; // exception expected
        }
        Object ret = null;
        Throwable err = null;
        Object[] pargs = new Object[args.length];
        Calling para = rc.para;
        boolean stop = false;
        for(int i = 0; i < rc.inters.length-1;i+=2) {
            if (rc.inters[i] < 0) {
                continue;
            }
            para.setValue(rc.cls, rc.name,rc.desc);
            para.interceptorFlag = rc.inters[i+1];
            para.handling = rc.interHandlings[i/2];
            for(int k =  0; k < args.length;k++){
                pargs[k] = args[k];
            }
            para.args = pargs;
            para.target = target;
            para.err = err;
            para.retVal = ret;
            try {
                int flag = allInterceptors[rc.inters[i]].preCall(para);
                rc.interHandlings[i/2] = para.handling;
                if((flag & Interceptor.C_SKIP) != 0){
                    rc.inters[i] = -1;
                }
                if ((flag & Interceptor.C_OVERWRITE) != 0) {
                    err = para.err;
                    ret = para.retVal;
                    for (int k = 0; k < args.length; k++) {
                        args[k] = pargs[k];
                    }
                }
                if((flag & Interceptor.C_STOP)!=0){
                    stop = true;
                    break;
                }
            }catch (Throwable t){
                System.out.println(ExUtils.getExcept(t));
                rc.inters[i] = -1;
            }
        }
        if(!stop) {
            try {
                rc.skip = 1;
                Method m = allMethods[rc.mid];
                if (m == null) {
                    m = matchMethod(rc.cls, rc.name,rc.desc);
                    m.setAccessible(true);
                    allMethods[rc.mid] = m; // safe
                    allMethods = allMethods;
                }
                ret = m.invoke(target, args);
            } catch (Throwable e) {
                err = e;
                if (err.getCause() != null) {
                    err = err.getCause();
                }
            }finally {
                rc.skip = 0; // set it anyway
            }
            for (int i = 0; i < rc.inters.length; i += 2) {
                if (rc.inters[i] < 0) {
                    continue;
                }
                for(int k =  0; k < args.length;k++){
                    pargs[k] = args[k];
                }
                para.setValue(rc.cls, rc.name, rc.desc);
                para.args = pargs;
                para.interceptorFlag = rc.inters[i + 1];
                para.handling = rc.interHandlings[i/2];
                para.target = target;
                para.err = err;
                para.retVal = ret;
                try {
                    int flag = allInterceptors[rc.inters[i]].postCall(para);
                    if ((flag & Interceptor.C_OVERWRITE) != 0) {
                        err = para.err;
                        ret = para.retVal;
                    }
                    if ((flag & Interceptor.C_STOP) != 0) {
                        break;
                    }
                } catch (Throwable t) {
                    System.out.println(ExUtils.getExcept(t));
                }
            }
        }
        if(err != null){
            throw err;
        }
        return ret;
    }

    public static boolean skip(int[] interceptors, Class type, String name, String desc,int mid){
        RunningContext rc = cxt.get();
        if(rc == null || rc.skip == 2){
            cxt.set(rc = new RunningContext());
        }
        if(rc.skip == 1){
            rc.skip = 2;
            return true;
        }

        rc.setValue(type,mid, name, desc, interceptors);
        boolean ret = true;
        for(int i = 0; i < interceptors.length-1;i+=2){
            Interceptor intp = interceptors[i] < allInterceptors.length ? allInterceptors[interceptors[i]] : null;
            if(intp == null){
                interceptors[i] = -1;
                continue;
            }
            rc.para.setValue(type,name,desc);
            rc.para.interceptorFlag = interceptors[i+1];
            if(!intp.filterCall(rc.para)){
                interceptors[i] = -1;
            }else {
                rc.interHandlings[i/2] = rc.para.handling;
                ret = false;
            }
        }
        rc.skip = 0;
        return ret;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy