mirror of
https://github.com/GTNewHorizons/CodeChickenCore.git
synced 2026-11-11 15:57:42 +00:00
316 lines
10 KiB
Java
316 lines
10 KiB
Java
package codechicken.core;
|
|||
|
|
|
||
|
|
import java.lang.reflect.Constructor;
|
||
|
|
import java.lang.reflect.Field;
|
||
|
|
import java.lang.reflect.InvocationTargetException;
|
||
|
|
import java.lang.reflect.Method;
|
||
|
|
import java.util.HashMap;
|
||
|
|
|
||
|
|
import codechicken.lib.asm.ObfMapping;
|
||
|
|
|
||
|
|
public class ReflectionManager
|
||
|
|
{
|
||
|
|
public static HashMap<Class<?>, Class<?>> primitiveWrappers = new HashMap<Class<?>, Class<?>>();
|
||
|
|
|
||
|
|
static
|
||
|
|
{
|
||
|
|
primitiveWrappers.put(Integer.TYPE, Integer.class);
|
||
|
|
primitiveWrappers.put(Short.TYPE, Short.class);
|
||
|
|
primitiveWrappers.put(Byte.TYPE, Byte.class);
|
||
|
|
primitiveWrappers.put(Long.TYPE, Long.class);
|
||
|
|
primitiveWrappers.put(Double.TYPE, Double.class);
|
||
|
|
primitiveWrappers.put(Float.TYPE, Float.class);
|
||
|
|
primitiveWrappers.put(Boolean.TYPE, Boolean.class);
|
||
|
|
primitiveWrappers.put(Character.TYPE, Character.class);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static boolean isInstance(Class<?> class1, Object obj)
|
||
|
|
{
|
||
|
|
Class<?> primitive = primitiveWrappers.get(class1);
|
||
|
|
if(primitive != null)
|
||
|
|
{
|
||
|
|
if(primitive == Long.class && Long.class.isInstance(obj))
|
||
|
|
return true;
|
||
|
|
if((primitive == Long.class || primitive == Integer.class) && Integer.class.isInstance(obj))
|
||
|
|
return true;
|
||
|
|
if((primitive == Long.class || primitive == Integer.class || primitive == Short.class) && Short.class.isInstance(obj))
|
||
|
|
return true;
|
||
|
|
if((primitive == Long.class || primitive == Integer.class || primitive == Short.class || primitive == Byte.class) && Integer.class.isInstance(obj))
|
||
|
|
return true;
|
||
|
|
|
||
|
|
if(primitive == Double.class && Double.class.isInstance(obj))
|
||
|
|
return true;
|
||
|
|
if((primitive == Double.class || primitive == Float.class) && Float.class.isInstance(obj))
|
||
|
|
return true;
|
||
|
|
|
||
|
|
return primitive.isInstance(obj);
|
||
|
|
}
|
||
|
|
return class1.isInstance(obj);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static Class<?> findClass(String name)
|
||
|
|
{
|
||
|
|
return findClass(name, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static boolean classExists(String name)
|
||
|
|
{
|
||
|
|
return findClass(name, false) != null;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static Class<?> findClass(String name, boolean init)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return Class.forName(name, init, ReflectionManager.class.getClassLoader());
|
||
|
|
}
|
||
|
|
catch (ClassNotFoundException cnfe)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return Class.forName("net.minecraft.src."+name, init, ReflectionManager.class.getClassLoader());
|
||
|
|
}
|
||
|
|
catch (ClassNotFoundException cnfe2)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void setField(Class<?> class1, Object instance, String name, Object value) throws IllegalArgumentException, IllegalAccessException
|
||
|
|
{
|
||
|
|
setField(class1, instance, new String[]{name}, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void setField(Class<?> class1, Object instance, String[] names, Object value) throws IllegalArgumentException, IllegalAccessException
|
||
|
|
{
|
||
|
|
for(Field field : class1.getDeclaredFields())
|
||
|
|
{
|
||
|
|
boolean match = false;
|
||
|
|
for(String name : names)
|
||
|
|
{
|
||
|
|
if(field.getName().equals(name))
|
||
|
|
{
|
||
|
|
match = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(!match)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
field.setAccessible(true);
|
||
|
|
field.set(instance, value);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void setField(Class<?> class1, Object instance, int fieldindex, Object value) throws IllegalArgumentException, IllegalAccessException
|
||
|
|
{
|
||
|
|
Field field = class1.getDeclaredFields()[fieldindex];
|
||
|
|
field.setAccessible(true);
|
||
|
|
field.set(instance, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Static function
|
||
|
|
* void return type
|
||
|
|
* single name
|
||
|
|
*/
|
||
|
|
public static void callMethod(Class<?> class1, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
callMethod(class1, null, new String[]{name}, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Static function
|
||
|
|
* void return type
|
||
|
|
* single name
|
||
|
|
*/
|
||
|
|
public static void callMethod(Class<?> class1, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
callMethod(class1, null, names, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* void return type
|
||
|
|
* single name
|
||
|
|
*/
|
||
|
|
public static void callMethod(Class<?> class1, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
callMethod(class1, null, instance, new String[]{name}, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* void return type
|
||
|
|
*/
|
||
|
|
public static void callMethod(Class<?> class1, Object instance, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
callMethod(class1, null, instance, names, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Static method
|
||
|
|
* single name
|
||
|
|
*/
|
||
|
|
public static <R> R callMethod(Class<?> class1, Class<R> returntype, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
return callMethod(class1, returntype, null, new String[]{name}, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Static method
|
||
|
|
*/
|
||
|
|
public static <R> R callMethod(Class<?> class1, Class<R> returntype, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
return callMethod(class1, returntype, null, names, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* sinlge name
|
||
|
|
*/
|
||
|
|
public static <R> R callMethod(Class<?> class1, Class<R> returntype, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
return callMethod(class1, returntype, instance, new String[]{name}, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static <R> R callMethod(Class<?> class1, Class<R> returntype, Object instance, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
nextMethod: for(Method method : class1.getDeclaredMethods())
|
||
|
|
{
|
||
|
|
boolean match = false;
|
||
|
|
for(String name : names)
|
||
|
|
{
|
||
|
|
if(method.getName().equals(name))
|
||
|
|
{
|
||
|
|
match = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(!match)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
Class<?>[] paramtypes = method.getParameterTypes();
|
||
|
|
if(paramtypes.length != params.length)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
for(int i = 0; i < params.length; i++)
|
||
|
|
{
|
||
|
|
if(!isInstance(paramtypes[i], params[i]))
|
||
|
|
continue nextMethod;
|
||
|
|
}
|
||
|
|
|
||
|
|
method.setAccessible(true);
|
||
|
|
return (R)method.invoke(instance, params);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static <T> T getField(Class<?> class1, Class<T> fieldType, Object instance, int fieldIndex) throws IllegalArgumentException, IllegalAccessException
|
||
|
|
{
|
||
|
|
Field field = class1.getDeclaredFields()[fieldIndex];
|
||
|
|
field.setAccessible(true);
|
||
|
|
return (T) field.get(instance);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static <T> T getField(Class<?> class1, Class<T> fieldType, Object instance, String fieldName)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
Field field = class1.getDeclaredField(fieldName);
|
||
|
|
field.setAccessible(true);
|
||
|
|
return (T) field.get(instance);
|
||
|
|
}
|
||
|
|
catch(Exception e)
|
||
|
|
{
|
||
|
|
throw new RuntimeException(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static <T> T newInstance(Class<T> class1, Object... params) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
|
||
|
|
{
|
||
|
|
nextMethod: for(Constructor<?> constructor : class1.getDeclaredConstructors())
|
||
|
|
{
|
||
|
|
Class<?>[] paramtypes = constructor.getParameterTypes();
|
||
|
|
if(paramtypes.length != params.length)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
for(int i = 0; i < params.length; i++)
|
||
|
|
{
|
||
|
|
if(!isInstance(paramtypes[i], params[i]))
|
||
|
|
continue nextMethod;
|
||
|
|
}
|
||
|
|
|
||
|
|
constructor.setAccessible(true);
|
||
|
|
return (T)constructor.newInstance(params);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static boolean hasField(Class<?> class1, String fieldName)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
class1.getDeclaredField(fieldName);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch(NoSuchFieldException nfe)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static <T> T get(Field field, Class<T> class1)
|
||
|
|
{
|
||
|
|
return get(field, class1, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static <T> T get(Field field, Class<T> class1, Object instance)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
return (T)field.get(instance);
|
||
|
|
}
|
||
|
|
catch(Exception e)
|
||
|
|
{
|
||
|
|
throw new RuntimeException(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void set(Field field, Object value)
|
||
|
|
{
|
||
|
|
set(field, null, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void set(Field field, Object instance, Object value)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
field.set(instance, value);
|
||
|
|
}
|
||
|
|
catch(Exception e)
|
||
|
|
{
|
||
|
|
throw new RuntimeException(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static Field getField(ObfMapping mapping)
|
||
|
|
{
|
||
|
|
mapping.toRuntime();
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
Class<?> clazz = ReflectionManager.class.getClassLoader().loadClass(mapping.javaClass());
|
||
|
|
Field field = clazz.getDeclaredField(mapping.s_name);
|
||
|
|
field.setAccessible(true);
|
||
|
|
return field;
|
||
|
|
}
|
||
|
|
catch(Exception e)
|
||
|
|
{
|
||
|
|
throw new RuntimeException(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|