Plex-FAWE/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

114 lines
3.8 KiB
Java
Raw Normal View History

package com.boydti.fawe.util;
2020-07-14 02:50:59 +00:00
import org.jetbrains.annotations.NotNull;
2020-02-22 03:53:25 +00:00
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
2019-06-21 00:05:18 +00:00
import java.util.Arrays;
import java.util.Comparator;
public class ReflectionUtils {
2020-03-05 21:07:20 +00:00
public static <T> T as(Class<T> t, Object o) {
return t.isInstance(o) ? t.cast(o) : null;
}
public static void setAccessibleNonFinal(Field field) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
// let's make the field accessible
field.setAccessible(true);
// next we change the modifier in the Field instance to
// not be final anymore, thus tricking reflection into
// letting us modify the static final field
if (Modifier.isFinal(field.getModifiers())) {
2019-12-21 20:21:25 +00:00
try {
2020-02-22 03:53:25 +00:00
Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
lookupField.setAccessible(true);
2019-12-21 20:21:25 +00:00
// blank out the final bit in the modifiers int
2020-02-22 03:53:25 +00:00
((MethodHandles.Lookup) lookupField.get(null))
2020-03-05 21:07:20 +00:00
.findSetter(Field.class, "modifiers", int.class)
2020-02-22 03:53:25 +00:00
.invokeExact(field, field.getModifiers() & ~Modifier.FINAL);
} catch (Throwable e) {
e.printStackTrace();
2019-12-21 20:21:25 +00:00
}
}
2019-12-21 20:21:25 +00:00
}
public static void setFailsafeFieldValue(Field field, Object target, Object value) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
2019-12-21 20:21:25 +00:00
setAccessibleNonFinal(field);
2020-03-05 21:07:20 +00:00
field.set(target, value);
}
2019-08-15 19:21:24 +00:00
public static Object getHandle(Object wrapper) {
final Method getHandle = makeMethod(wrapper.getClass(), "getHandle");
return callMethod(getHandle, wrapper);
}
//Utils
2019-08-15 19:21:24 +00:00
public static Method makeMethod(Class<?> clazz, String methodName, Class<?>... parameters) {
try {
2019-05-29 03:23:51 +00:00
return clazz.getDeclaredMethod(methodName, parameters);
2019-08-15 19:21:24 +00:00
} catch (NoSuchMethodException ex) {
return null;
2019-08-15 19:21:24 +00:00
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
@SuppressWarnings("unchecked")
2019-08-15 19:21:24 +00:00
public static <T> T callMethod(Method method, Object instance, Object... parameters) {
if (method == null) {
throw new RuntimeException("No such method");
}
method.setAccessible(true);
try {
2019-05-29 03:23:51 +00:00
return (T) method.invoke(instance, parameters);
2019-08-15 19:21:24 +00:00
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
2019-08-15 19:21:24 +00:00
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static Field[] sortFields(Field[] fields) {
Arrays.sort(fields, Comparator.comparing(Field::getName));
return fields;
}
2019-08-15 19:21:24 +00:00
public static <T extends AccessibleObject> T setAccessible(T ao) {
ao.setAccessible(true);
return ao;
}
@SuppressWarnings("unchecked")
2020-03-05 21:07:20 +00:00
public static <T> T getField(@NotNull Field field, Object instance) {
field.setAccessible(true);
try {
return (T) field.get(instance);
2019-08-15 19:21:24 +00:00
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
2019-08-15 19:21:24 +00:00
public static Class<?> getClass(String name) {
try {
return Class.forName(name);
2019-08-15 19:21:24 +00:00
} catch (ClassNotFoundException ex) {
return null;
}
}
2019-08-15 19:21:24 +00:00
public static <T> Class<? extends T> getClass(String name, Class<T> superClass) {
try {
return Class.forName(name).asSubclass(superClass);
} catch (ClassCastException | ClassNotFoundException ex) {
return null;
}
}
}