package greencode.util; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Hashtable; public final class GenericReflection { private static final Hashtable<Class<?>, Hashtable<Integer, Constructor<?>>> cacheConstructor = new Hashtable<Class<?>, Hashtable<Integer,Constructor<?>>>(); private static final Hashtable<Class<?>, Hashtable<Integer, Constructor<?>>> cacheDeclaredConstructor = new Hashtable<Class<?>, Hashtable<Integer,Constructor<?>>>(); private static final Hashtable<Class<?>, Method[]> cacheMethods = new Hashtable<Class<?>, Method[]>(); private static final Hashtable<Class<?>, Field[]> cacheFields = new Hashtable<Class<?>, Field[]>(); private static final Hashtable<Class<?>, Hashtable<String, Field[]>> cacheConditionFields = new Hashtable<Class<?>, Hashtable<String, Field[]>>(); private static final Hashtable<Class<?>, Hashtable<String, Field>> cacheField = new Hashtable<Class<?>, Hashtable<String, Field>>(); private static final Hashtable<Class<?>, Hashtable<String, Method>> cacheDeclaredMethods = new Hashtable<Class<?>, Hashtable<String,Method>>(); private static final Hashtable<Class<?>, Hashtable<String, Hashtable<Integer, Method>>> cacheMethod = new Hashtable<Class<?>, Hashtable<String,Hashtable<Integer,Method>>>(); private static final Hashtable<Class<?>, HashSet<Class<?>>> interfaces = new Hashtable<Class<?>, HashSet<Class<?>>>(); private GenericReflection() {} public static Object getValue(Class<?> Class, String nameField, Object reference) { try { return getDeclaredField(Class, nameField).get(reference); } catch (Exception e) { throw new RuntimeException(e); } } public static void setValue(Class<?> Class, String nameField, Object value, Object reference) { try { getDeclaredField(Class, nameField).set(reference, value); } catch (Exception e) { throw new RuntimeException(e); } } public static Field getDeclaredField(Class<?> Class, String fieldName) throws SecurityException, NoSuchFieldException { Hashtable<String, Field> fields = cacheField.get(Class); if(fields == null) cacheField.put(Class, fields = new Hashtable<String, Field>()); Field field = fields.get(fieldName); if(field == null) { (field = Class.getDeclaredField(fieldName)).setAccessible(true); fields.put(fieldName, field); } return field; } public static Field[] getDeclaredFields(Class<?> Class) { Field[] fields = cacheFields.get(Class); if(fields == null) { fields = Class.getDeclaredFields(); for (Field f : fields) f.setAccessible(true); cacheFields.put(Class, fields); } return fields; } public static void registerDeclaredFields(Class<?> Class, String id, Field[] fields) { Hashtable<String, Field[]> hashFields = cacheConditionFields.get(Class); if(hashFields == null) cacheConditionFields.put(Class, hashFields = new Hashtable<String, Field[]>()); hashFields.put(id, fields); } public static Field[] getDeclaredFieldsByConditionId(Class<?> Class, String id) { Hashtable<String, Field[]> hashFields = cacheConditionFields.get(Class); if(hashFields != null) return hashFields.get(id); return null; } public static Field[] getDeclaredFieldsByCondition(Class<?> Class, String id, Condition<Field> condition) { return getDeclaredFieldsByCondition(Class, id, condition, false); } public static Field[] getDeclaredFieldsByCondition(Class<?> Class, String id, Condition<Field> condition, boolean considerParents) { final ArrayList<Field> _fields = new ArrayList<Field>(); Field[] fields = getDeclaredFields(Class); for (Field field : fields) if(condition.init(field)) _fields.add(field); if(considerParents) { final Class<?>[] parents = ClassUtils.getParents(Class); for (Class<?> parent : parents) { fields = getDeclaredFields(parent); for (Field field : fields) { if(condition.init(field)) _fields.add(field); } } } fields = _fields.toArray(new Field[_fields.size()]); registerDeclaredFields(Class, id, fields); return fields; } public static Method getDeclaredMethod(Class<?> Class, String methodName, Class<?>... parameterTypes) throws SecurityException, NoSuchMethodException { Hashtable<String, Method> methods = cacheDeclaredMethods.get(Class); if(methods == null) cacheDeclaredMethods.put(Class, methods = new Hashtable<String, Method>()); Method method = methods.get(methodName); if(method == null) { (method = Class.getDeclaredMethod(methodName, parameterTypes)).setAccessible(true); methods.put(methodName, method); } return method; } public static Method getMethod(Class<?> Class, String methodName, Class<?>... parameterTypes) throws SecurityException, NoSuchMethodException { Hashtable<String, Hashtable<Integer, Method>> methods = cacheMethod.get(Class); if(methods == null) cacheMethod.put(Class, methods = new Hashtable<String, Hashtable<Integer,Method>>()); Hashtable<Integer, Method> methodArgs = methods.get(methodName); if(methodArgs == null) methods.put(methodName, methodArgs = new Hashtable<Integer, Method>()); final int hashCode = Arrays.hashCode(parameterTypes); Method method = methodArgs.get(hashCode); if(method == null) { (method = Class.getMethod(methodName, parameterTypes)).setAccessible(true); methodArgs.put(hashCode, method); } return method; } public static Method[] getDeclaredMethods(Class<?> Class) { Method[] methods = cacheMethods.get(Class); if(methods == null) cacheMethods.put(Class, methods = Class.getDeclaredMethods()); return methods; } public static void setFinalAccessible(Field field) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); } @SuppressWarnings("unchecked") public static<C> Constructor<C> getConstrutor(Class<C> Class, Class<?>... parameterTypes) throws SecurityException, NoSuchMethodException { final int hashcode = Arrays.hashCode(parameterTypes); Hashtable<Integer, Constructor<?>> constructors = cacheConstructor.get(Class); if(constructors == null) cacheConstructor.put(Class, constructors = new Hashtable<Integer, Constructor<?>>()); Constructor<C> constructor = (Constructor<C>) constructors.get(hashcode); if(constructor == null) { (constructor = Class.getConstructor(parameterTypes)).setAccessible(true); constructors.put(hashcode, constructor); } return constructor; } @SuppressWarnings("unchecked") public static<C> Constructor<C> getDeclaredConstrutor(Class<C> Class, Class<?>... parameterTypes) throws SecurityException, NoSuchMethodException { final int hashcode = Arrays.hashCode(parameterTypes); Hashtable<Integer, Constructor<?>> constructors = cacheDeclaredConstructor.get(Class); if(constructors == null) cacheDeclaredConstructor.put(Class, constructors = new Hashtable<Integer, Constructor<?>>()); Constructor<C> constructor = (Constructor<C>) constructors.get(hashcode); if(constructor == null) { (constructor = Class.getDeclaredConstructor(parameterTypes)).setAccessible(true); constructors.put(hashcode, constructor); } return constructor; } public static boolean hasInterface(Class<?> Class, Class<?> Interface) { HashSet<Class<?>> interfs = interfaces.get(Class); if(interfs == null) interfaces.put(Class, interfs = new HashSet<Class<?>>(Arrays.asList(Class.getInterfaces()))); return interfs.contains(Interface); } public static class NoThrow { public static Object getValue(Field field, Object reference) { try { return field.get(reference); } catch (Exception e) { throw new RuntimeException(e); } } public static void setFinalStaticValue(Class<?> c, String fieldName, Object value) { setFinalValue(c, fieldName, value, null); } public static void setFinalValue(Class<?> c, String fieldName, Object value, Object reference) { GenericReflection.NoThrow.setFinalValue(GenericReflection.NoThrow.getDeclaredField(c, fieldName), value, reference); } public static void setFinalValue(Field field, Object value, Object reference) { try { setFinalAccessible(field); field.set(reference, value); } catch (Exception e) { throw new RuntimeException(e); } } public static void setValue(Field field, Object value, Object reference) { try { field.set(reference, value); } catch (Exception e) { throw new RuntimeException(e); } } public static Field getDeclaredField(Class<?> Class, String fieldName) { try { return GenericReflection.getDeclaredField(Class, fieldName); } catch (Exception e) { throw new RuntimeException(e); } } public static<C> Constructor<C> getConstrutor(Class<C> Class, Class<?>... parameterTypes) { try { return GenericReflection.getConstrutor(Class, parameterTypes); } catch (Exception e) { throw new RuntimeException(e); } } public static<C> Constructor<C> getDeclaredConstrutor(Class<C> Class, Class<?>... parameterTypes) { try { return GenericReflection.getDeclaredConstrutor(Class, parameterTypes); } catch (Exception e) { throw new RuntimeException(e); } } public static Method getMethod(Class<?> Class, String methodName, Class<?>... parameterTypes) { try { return GenericReflection.getMethod(Class, methodName, parameterTypes); } catch (Exception e) { throw new RuntimeException(e); } } public static Method getDeclaredMethod(Class<?> Class, String methodName, Class<?>... parameterTypes) { try { return GenericReflection.getDeclaredMethod(Class, methodName, parameterTypes); } catch (Exception e) { throw new RuntimeException(e); } } public static Object newInstance(String className, Class<?>[] parameterTypes, Object... objects) { try { return newInstance(Class.forName(className), parameterTypes, objects); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static<C> C newInstance(Class<C> _class, Class<?>[] parameterTypes, Object... objects) { try { return getDeclaredConstrutor(_class, parameterTypes).newInstance(objects); } catch (Exception e) { throw new RuntimeException(e); } } public static void setFinalAccessible(Field field) { try { Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); } catch (Exception e) { throw new RuntimeException(e); } } } public interface Condition<R extends AccessibleObject> { public abstract boolean init(R arg0); } }