mirror of
https://github.com/QM4RS/FridaBox.git
synced 2026-10-08 00:42:24 +02:00
feat: Introduce black-reflection and compiler modules, integrate reflection utilities, and update core components.
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
package top.niunaijun.blackreflection;
|
||||
|
||||
/**
|
||||
* on 2022/2/16.
|
||||
* * ∧_∧
|
||||
* (`・ω・∥
|
||||
* 丶 つ0
|
||||
* しーJ
|
||||
* 此处无Bug
|
||||
*/
|
||||
public class BlackNullPointerException extends NullPointerException {
|
||||
public BlackNullPointerException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package top.niunaijun.blackreflection;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import top.niunaijun.blackreflection.annotation.BClass;
|
||||
import top.niunaijun.blackreflection.annotation.BClassName;
|
||||
import top.niunaijun.blackreflection.annotation.BClassNameNotProcess;
|
||||
import top.niunaijun.blackreflection.annotation.BConstructor;
|
||||
import top.niunaijun.blackreflection.annotation.BConstructorNotProcess;
|
||||
import top.niunaijun.blackreflection.annotation.BField;
|
||||
import top.niunaijun.blackreflection.annotation.BFieldCheckNotProcess;
|
||||
import top.niunaijun.blackreflection.annotation.BFieldNotProcess;
|
||||
import top.niunaijun.blackreflection.annotation.BFieldSetNotProcess;
|
||||
import top.niunaijun.blackreflection.annotation.BMethodCheckNotProcess;
|
||||
import top.niunaijun.blackreflection.annotation.BParamClass;
|
||||
import top.niunaijun.blackreflection.annotation.BParamClassName;
|
||||
import top.niunaijun.blackreflection.utils.Reflector;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class BlackReflection {
|
||||
public static boolean DEBUG = false;
|
||||
public static boolean CACHE = false;
|
||||
private static final Map<Class<?>, Object> sProxyCache = new HashMap<>();
|
||||
private static final Map<Class<?>, Object> sProxyWithExceptionCache = new HashMap<>();
|
||||
|
||||
// key caller
|
||||
private static final WeakHashMap<Object, Map<Class<?>, Object>> sCallerProxyCache = new WeakHashMap<>();
|
||||
|
||||
// public static <T> T create(Class<T> clazz, final Object caller) {
|
||||
// return create(clazz, caller, false);
|
||||
// }
|
||||
|
||||
public static <T> T create(Class<T> clazz, final Object caller, boolean withException) {
|
||||
try {
|
||||
T proxy = getProxy(clazz, caller, withException);
|
||||
if (proxy != null)
|
||||
return proxy;
|
||||
final WeakReference<Object> weakCaller = caller == null ? null : new WeakReference<>(caller);
|
||||
|
||||
final Class<?> aClass = getClassNameByBlackClass(clazz);
|
||||
Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String name = method.getName();
|
||||
Class<?> returnType = method.getReturnType();
|
||||
|
||||
try {
|
||||
boolean isStatic = weakCaller == null;
|
||||
|
||||
Object callerByWeak = isStatic ? null : weakCaller.get();
|
||||
|
||||
// fidel
|
||||
BField bField = method.getAnnotation(BField.class);
|
||||
BFieldNotProcess bFieldNotProcess = method.getAnnotation(BFieldNotProcess.class);
|
||||
if (bField != null || bFieldNotProcess != null) {
|
||||
Object call;
|
||||
Reflector on = Reflector.on(aClass).field(name);
|
||||
if (isStatic) {
|
||||
call = on.get();
|
||||
} else {
|
||||
if (callerByWeak == null) {
|
||||
return generateNullValue(returnType);
|
||||
}
|
||||
call = on.get(callerByWeak);
|
||||
}
|
||||
return call;
|
||||
}
|
||||
|
||||
// void
|
||||
BFieldSetNotProcess bFieldSetNotProcess = method.getAnnotation(BFieldSetNotProcess.class);
|
||||
if (bFieldSetNotProcess != null) {
|
||||
// startsWith "_set_"
|
||||
name = name.substring("_set_".length());
|
||||
Reflector on = Reflector.on(aClass).field(name);
|
||||
if (isStatic) {
|
||||
on.set(args[0]);
|
||||
} else {
|
||||
if (callerByWeak == null) {
|
||||
return 0;
|
||||
}
|
||||
on.set(callerByWeak, args[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check field
|
||||
BFieldCheckNotProcess bFieldCheckNotProcess = method.getAnnotation(BFieldCheckNotProcess.class);
|
||||
if (bFieldCheckNotProcess != null) {
|
||||
// startsWith "_check_"
|
||||
name = name.substring("_check_".length());
|
||||
try {
|
||||
Reflector on = Reflector.on(aClass).field(name);
|
||||
return on.getField();
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Class<?>[] paramClass = getParamClass(method);
|
||||
|
||||
// check method
|
||||
BMethodCheckNotProcess bMethodCheckNotProcess = method.getAnnotation(BMethodCheckNotProcess.class);
|
||||
if (bMethodCheckNotProcess != null) {
|
||||
// startsWith "_check_"
|
||||
name = name.substring("_check_".length());
|
||||
try {
|
||||
return Reflector.on(aClass).method(name, paramClass).getMethod();
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// method
|
||||
BConstructor bConstructor = method.getAnnotation(BConstructor.class);
|
||||
BConstructorNotProcess bConstructorNotProcess = method.getAnnotation(BConstructorNotProcess.class);
|
||||
if (bConstructor != null || bConstructorNotProcess != null) {
|
||||
Reflector on = Reflector.on(aClass).constructor(paramClass);
|
||||
return on.newInstance(args);
|
||||
}
|
||||
|
||||
Object call;
|
||||
Reflector on = Reflector.on(aClass).method(name, paramClass);
|
||||
if (isStatic) {
|
||||
call = on.call(args);
|
||||
} else {
|
||||
if (callerByWeak == null) {
|
||||
return generateNullValue(returnType);
|
||||
}
|
||||
call = on.callByCaller(callerByWeak, args);
|
||||
}
|
||||
return call;
|
||||
} catch (Throwable throwable) {
|
||||
if (DEBUG) {
|
||||
if (throwable.getCause() != null) {
|
||||
throwable.getCause().printStackTrace();
|
||||
} else {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (throwable instanceof BlackNullPointerException) {
|
||||
throw new NullPointerException(throwable.getMessage());
|
||||
}
|
||||
if (withException) {
|
||||
throw throwable;
|
||||
}
|
||||
}
|
||||
|
||||
return generateNullValue(returnType);
|
||||
}
|
||||
});
|
||||
|
||||
if (caller == null) {
|
||||
if (withException) {
|
||||
sProxyWithExceptionCache.put(clazz, o);
|
||||
} else {
|
||||
sProxyCache.put(clazz, o);
|
||||
}
|
||||
}
|
||||
return (T) o;
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <T> T getProxy(Class<T> clazz, final Object caller, boolean withException) {
|
||||
try {
|
||||
if (caller == null) {
|
||||
Object o;
|
||||
if (withException) {
|
||||
o = sProxyWithExceptionCache.get(clazz);
|
||||
} else {
|
||||
o = sProxyCache.get(clazz);
|
||||
}
|
||||
if (o != null) {
|
||||
return (T) o;
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<?>[] getParamClass(Method method) throws Throwable {
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Class<?>[] param = new Class[parameterTypes.length];
|
||||
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
Annotation[] parameterAnnotation = parameterAnnotations[i];
|
||||
boolean found = false;
|
||||
for (Annotation annotation : parameterAnnotation) {
|
||||
if (annotation instanceof BParamClassName) {
|
||||
found = true;
|
||||
param[i] = Class.forName(((BParamClassName) annotation).value());
|
||||
break;
|
||||
} else if (annotation instanceof BParamClass) {
|
||||
found = true;
|
||||
param[i] = ((BParamClass) annotation).value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
param[i] = parameterTypes[i];
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
private static Class<?> getClassNameByBlackClass(Class<?> clazz) throws ClassNotFoundException {
|
||||
BClass bClass = clazz.getAnnotation(BClass.class);
|
||||
BClassName bClassName = clazz.getAnnotation(BClassName.class);
|
||||
BClassNameNotProcess bClassNameNotProcess = clazz.getAnnotation(BClassNameNotProcess.class);
|
||||
if (bClass == null && bClassName == null && bClassNameNotProcess == null) {
|
||||
throw new RuntimeException("Not found @BlackClass or @BlackStrClass");
|
||||
}
|
||||
|
||||
if (bClass != null) {
|
||||
return bClass.value();
|
||||
} else if (bClassName != null) {
|
||||
return Class.forName(bClassName.value());
|
||||
} else {
|
||||
return Class.forName(bClassNameNotProcess.value());
|
||||
}
|
||||
}
|
||||
|
||||
private static Object generateNullValue(Class<?> returnType) {
|
||||
if (returnType == void.class) {
|
||||
return 0;
|
||||
}
|
||||
if (returnType.isPrimitive()) {
|
||||
throw new BlackNullPointerException("value is null!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({TYPE})
|
||||
public @interface BClass {
|
||||
Class<?> value();
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({TYPE})
|
||||
public @interface BClassName {
|
||||
String value();
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({TYPE})
|
||||
public @interface BClassNameNotProcess {
|
||||
String value();
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* on 2022/2/16.
|
||||
* * ∧_∧
|
||||
* (`・ω・∥
|
||||
* 丶 つ0
|
||||
* しーJ
|
||||
* 此处无Bug
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BConstructor {
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* on 2022/2/16.
|
||||
* * ∧_∧
|
||||
* (`・ω・∥
|
||||
* 丶 つ0
|
||||
* しーJ
|
||||
* 此处无Bug
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BConstructorNotProcess {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BField {
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BFieldCheckNotProcess {
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BFieldNotProcess {
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BFieldSetNotProcess {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BMethod {
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BMethodCheckNotProcess {
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({PARAMETER})
|
||||
public @interface BParamClass {
|
||||
Class<?> value();
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({PARAMETER})
|
||||
public @interface BParamClassName {
|
||||
String value();
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BStaticField {
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package top.niunaijun.blackreflection.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
public @interface BStaticMethod {
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package top.niunaijun.blackreflection.utils;
|
||||
|
||||
import top.niunaijun.blackreflection.annotation.BClass;
|
||||
import top.niunaijun.blackreflection.annotation.BClassName;
|
||||
import top.niunaijun.blackreflection.annotation.BClassNameNotProcess;
|
||||
|
||||
/**
|
||||
* on 2022/2/18.
|
||||
* * ∧_∧
|
||||
* (`・ω・∥
|
||||
* 丶 つ0
|
||||
* しーJ
|
||||
* 此处无Bug
|
||||
*/
|
||||
public class ClassUtil {
|
||||
public static Class<?> classReady(Class<?> clazz) {
|
||||
BClassNameNotProcess bClassNameNotProcess = clazz.getAnnotation(BClassNameNotProcess.class);
|
||||
if (bClassNameNotProcess != null) {
|
||||
return classReady(bClassNameNotProcess.value());
|
||||
}
|
||||
BClass annotation = clazz.getAnnotation(BClass.class);
|
||||
if (annotation != null) {
|
||||
return annotation.value();
|
||||
}
|
||||
BClassName bClassName = clazz.getAnnotation(BClassName.class);
|
||||
if (bClassName != null) {
|
||||
return classReady(bClassName.value());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class<?> classReady(String clazz) {
|
||||
try {
|
||||
return Class.forName(clazz);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
package top.niunaijun.blackreflection.utils;
|
||||
|
||||
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class Reflector {
|
||||
public static final String LOG_TAG ="Reflector";
|
||||
|
||||
protected Class<?> mType;
|
||||
protected Object mCaller;
|
||||
protected Constructor<?> mConstructor;
|
||||
protected Field mField;
|
||||
protected Method mMethod;
|
||||
|
||||
|
||||
public static Reflector on(String name) throws Exception {
|
||||
return on(name, true, Reflector.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static Reflector on(String name, boolean initialize) throws Exception {
|
||||
return on(name, initialize, Reflector.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static Reflector on(String name, boolean initialize, ClassLoader loader) throws Exception {
|
||||
try {
|
||||
return on(Class.forName(name, initialize, loader));
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Reflector on(Class<?> type) {
|
||||
Reflector reflector = new Reflector();
|
||||
reflector.mType = type;
|
||||
return reflector;
|
||||
}
|
||||
|
||||
public static Reflector with(Object caller) throws Exception {
|
||||
return on(caller.getClass()).bind(caller);
|
||||
}
|
||||
|
||||
protected Reflector() {
|
||||
|
||||
}
|
||||
|
||||
public Reflector constructor(Class<?>... parameterTypes) throws Exception {
|
||||
try {
|
||||
mConstructor = mType.getDeclaredConstructor(parameterTypes);
|
||||
mConstructor.setAccessible(true);
|
||||
mField = null;
|
||||
mMethod = null;
|
||||
return this;
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R newInstance(Object... initargs) throws Exception {
|
||||
if (mConstructor == null) {
|
||||
throw new Exception("Constructor was null!");
|
||||
}
|
||||
try {
|
||||
return (R) mConstructor.newInstance(initargs);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new Exception("Oops!", e.getTargetException());
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object checked(Object caller) throws Exception {
|
||||
if (caller == null || mType.isInstance(caller)) {
|
||||
return caller;
|
||||
}
|
||||
throw new Exception("Caller [" + caller + "] is not a instance of type [" + mType + "]!");
|
||||
}
|
||||
|
||||
protected void check(Object caller, Member member, String name) throws Exception {
|
||||
if (member == null) {
|
||||
throw new Exception(name + " was null!");
|
||||
}
|
||||
if (caller == null && !Modifier.isStatic(member.getModifiers())) {
|
||||
throw new Exception("Need a caller!");
|
||||
}
|
||||
checked(caller);
|
||||
}
|
||||
|
||||
public Reflector bind(Object caller) throws Exception {
|
||||
mCaller = checked(caller);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Reflector unbind() {
|
||||
mCaller = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Reflector field(String name) throws Exception {
|
||||
try {
|
||||
mField = findField(name);
|
||||
mField.setAccessible(true);
|
||||
mConstructor = null;
|
||||
mMethod = null;
|
||||
return this;
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return mField;
|
||||
}
|
||||
|
||||
protected Field findField(String name) throws NoSuchFieldException {
|
||||
try {
|
||||
return mType.getField(name);
|
||||
} catch (NoSuchFieldException e) {
|
||||
for (Class<?> cls = mType; cls != null; cls = cls.getSuperclass()) {
|
||||
try {
|
||||
return cls.getDeclaredField(name);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R get() throws Exception {
|
||||
return get(mCaller);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R get(Object caller) throws Exception {
|
||||
check(caller, mField, "Field");
|
||||
try {
|
||||
return (R) mField.get(caller);
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Reflector set(Object value) throws Exception {
|
||||
return set(mCaller, value);
|
||||
}
|
||||
|
||||
public Reflector set(Object caller, Object value) throws Exception {
|
||||
check(caller, mField, "Field");
|
||||
try {
|
||||
mField.set(caller, value);
|
||||
return this;
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Reflector method(String name, Class<?>... parameterTypes) throws Exception {
|
||||
try {
|
||||
mMethod = findMethod(name, parameterTypes);
|
||||
mMethod.setAccessible(true);
|
||||
mConstructor = null;
|
||||
mField = null;
|
||||
return this;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return mMethod;
|
||||
}
|
||||
|
||||
protected Method findMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
try {
|
||||
return mType.getMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
for (Class<?> cls = mType; cls != null; cls = cls.getSuperclass()) {
|
||||
try {
|
||||
return cls.getDeclaredMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public <R> R call(Object... args) throws Exception {
|
||||
return callByCaller(mCaller, args);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R callByCaller(Object caller, Object... args) throws Exception {
|
||||
check(caller, mMethod, "Method");
|
||||
try {
|
||||
return (R) mMethod.invoke(caller, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new Exception("Oops!", e.getTargetException());
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Oops!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class QuietReflector extends Reflector {
|
||||
|
||||
protected Throwable mIgnored;
|
||||
|
||||
public static QuietReflector on(String name) {
|
||||
return on(name, true, QuietReflector.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static QuietReflector on(String name, boolean initialize) {
|
||||
return on(name, initialize, QuietReflector.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static QuietReflector on(String name, boolean initialize, ClassLoader loader) {
|
||||
Class<?> cls = null;
|
||||
try {
|
||||
cls = Class.forName(name, initialize, loader);
|
||||
return on(cls, null);
|
||||
} catch (Throwable e) {
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
return on(cls, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static QuietReflector on(Class<?> type) {
|
||||
return on(type, (type == null) ? new Exception("Type was null!") : null);
|
||||
}
|
||||
|
||||
private static QuietReflector on(Class<?> type, Throwable ignored) {
|
||||
QuietReflector reflector = new QuietReflector();
|
||||
reflector.mType = type;
|
||||
reflector.mIgnored = ignored;
|
||||
return reflector;
|
||||
}
|
||||
|
||||
public static QuietReflector with(Object caller) {
|
||||
if (caller == null) {
|
||||
return on((Class<?>) null);
|
||||
}
|
||||
return on(caller.getClass()).bind(caller);
|
||||
}
|
||||
|
||||
protected QuietReflector() {
|
||||
|
||||
}
|
||||
|
||||
public Throwable getIgnored() {
|
||||
return mIgnored;
|
||||
}
|
||||
|
||||
protected boolean skip() {
|
||||
return skipAlways() || mIgnored != null;
|
||||
}
|
||||
|
||||
protected boolean skipAlways() {
|
||||
return mType == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector constructor(Class<?>... parameterTypes) {
|
||||
if (skipAlways()) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
super.constructor(parameterTypes);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R newInstance(Object... initargs) {
|
||||
if (skip()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
return super.newInstance(initargs);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector bind(Object obj) {
|
||||
if (skipAlways()) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
super.bind(obj);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector unbind() {
|
||||
super.unbind();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector field(String name) {
|
||||
if (skipAlways()) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
super.field(name);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R get() {
|
||||
if (skip()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
return super.get();
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R get(Object caller) {
|
||||
if (skip()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
return super.get(caller);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector set(Object value) {
|
||||
if (skip()) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
super.set(value);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector set(Object caller, Object value) {
|
||||
if (skip()) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
super.set(caller, value);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuietReflector method(String name, Class<?>... parameterTypes) {
|
||||
if (skipAlways()) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
super.method(name, parameterTypes);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R call(Object... args) {
|
||||
if (skip()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
return super.call(args);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R callByCaller(Object caller, Object... args) {
|
||||
if (skip()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
mIgnored = null;
|
||||
return super.callByCaller(caller, args);
|
||||
} catch (Throwable e) {
|
||||
mIgnored = e;
|
||||
// Log.w(LOG_TAG, "Oops!", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user