Plex-FAWE/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ReflectionUtils.java
dordsor21 f2ee2248e0
Consistenty use javax annotations. (#1197)
- Unfortunately jetbrains annotations seem to be exposed transitively via core somewhere, but with the correct IDE settings, annotations can be defaulted to javax
 - Cleaning up of import order in #1195
 - Must be merged before #1195

Co-authored-by: NotMyFault <mc.cache@web.de>
2021-07-24 15:52:08 +02:00

114 lines
3.8 KiB
Java

package com.fastasyncworldedit.core.util;
import javax.annotation.Nonnull;
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;
import java.util.Arrays;
import java.util.Comparator;
public class ReflectionUtils {
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())) {
try {
Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
lookupField.setAccessible(true);
// blank out the final bit in the modifiers int
((MethodHandles.Lookup) lookupField.get(null))
.findSetter(Field.class, "modifiers", int.class)
.invokeExact(field, field.getModifiers() & ~Modifier.FINAL);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
public static void setFailsafeFieldValue(Field field, Object target, Object value) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
setAccessibleNonFinal(field);
field.set(target, value);
}
public static Object getHandle(Object wrapper) {
final Method getHandle = makeMethod(wrapper.getClass(), "getHandle");
return callMethod(getHandle, wrapper);
}
//Utils
public static Method makeMethod(Class<?> clazz, String methodName, Class<?>... parameters) {
try {
return clazz.getDeclaredMethod(methodName, parameters);
} catch (NoSuchMethodException ex) {
return null;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
@SuppressWarnings("unchecked")
public static <T> T callMethod(Method method, Object instance, Object... parameters) {
if (method == null) {
throw new RuntimeException("No such method");
}
method.setAccessible(true);
try {
return (T) method.invoke(instance, parameters);
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static Field[] sortFields(Field[] fields) {
Arrays.sort(fields, Comparator.comparing(Field::getName));
return fields;
}
public static <T extends AccessibleObject> T setAccessible(T ao) {
ao.setAccessible(true);
return ao;
}
@SuppressWarnings("unchecked")
public static <T> T getField(@Nonnull Field field, Object instance) {
field.setAccessible(true);
try {
return (T) field.get(instance);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static Class<?> getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException ex) {
return null;
}
}
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;
}
}
}