io.github.lab515.utils.ByteRunner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qray Show documentation
Show all versions of qray Show documentation
remoting ondemand in java
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;
}
}