package abs.backend.tests; import java.lang.reflect.Field; import java.lang.reflect.Modifier; /** * A helper class for gathering instance and static field information for unit * test. * * @author woner * */ public class ReflectionUtils { public static Object getField(Object object, String name) { return getField(object, object.getClass(), name); } /** * Get the value of a field with {@code name} from {@code object}. * * @param <V> * type of the field * @param object * @param name * @return the value of a field with {@code name} from {@code object}. * @throws IllegalStateException * if cannot get the specified field from the specified object. * * @see Class#getDeclaredField(String) * @see Field#get(Object) * @see Field#setAccessible(boolean) */ public static Object getField(Object object, Class<?> klass, String name) { try { Field field = klass.getDeclaredField(name); field.setAccessible(true); // remove final modifier from field int modifier = unfinalize(field); Object value = field.get(object); setModifier(field, modifier); field.setAccessible(false); return value; } catch (SecurityException e) { throw new IllegalStateException("Cannot get field " + name + " from object " + object, e); } catch (NoSuchFieldException e) { throw new IllegalStateException("Cannot get field " + name + " from object " + object, e); } catch (IllegalArgumentException e) { throw new IllegalStateException("Cannot get field " + name + " from object " + object, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot get field " + name + " from object " + object, e); } } public static <O, V> O setField(O object, String name, V value) { return setField(object, object.getClass(), name, value); } /** * Set field {@code name} of {@code object} with {@code value}. * * @param <O> * @param <V> * @param object * @param name * @param value * @return * @throws IllegalStateException * if cannot set the specified field of the specified object * with the value. * * @see Class#getDeclaredField(String) * @see Field#set(Object, Object) * @see Field#setAccessible(boolean) */ public static <O> O setField(O object, Class<?> klass, String name, Object value) { try { Field field = klass.getDeclaredField(name); field.setAccessible(true); // remove final modifier from field int modifier = unfinalize(field); field.set(object, value); setModifier(field, modifier); field.setAccessible(false); return object; } catch (SecurityException e) { throw new IllegalStateException("Cannot set field " + name + " from object " + object, e); } catch (NoSuchFieldException e) { throw new IllegalStateException("Cannot set field " + name + " from object " + object, e); } catch (IllegalArgumentException e) { throw new IllegalStateException("Cannot set field " + name + " from object " + object, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot set field " + name + " from object " + object, e); } } /** * Get the value of static field {@code name} from class {@code klass}. * * @param <V> * @param klass * @param name * @return the value of the static field {@code name} from class * {@code klass}. * * @throws IllegalStateException * if cannot get the static field {@code name} from class * {@code klass}. * * @see Class#getDeclaredField(String) * @see Field#get(Object) * @see Field#setAccessible(boolean) * @see Field#getModifiers() * @see Modifier */ public static Object getStaticField(Class<?> klass, String name) { try { Field field = klass.getDeclaredField(name); field.setAccessible(true); // remove final modifier from field int modifier = unfinalize(field); Object value = field.get(null); setModifier(field, modifier); field.setAccessible(false); return value; } catch (SecurityException e) { throw new IllegalStateException("Cannot get static field " + name + " from class " + klass, e); } catch (NoSuchFieldException e) { throw new IllegalStateException("Cannot get static field " + name + " from class " + klass, e); } catch (IllegalArgumentException e) { throw new IllegalStateException("Cannot get static field " + name + " from class " + klass, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot get static field " + name + " from class " + klass, e); } } /** * * Set static field {@code name} of {@code klass} with {@code value}. * * @param <V> * @param klass * @param name * @param value * * @throws IllegalStateException * if cannot set the specified static field of the specified * class with the value. * * @see Class#getDeclaredField(String) * @see Field#set(Object, Object) * @see Field#setAccessible(boolean) * @see Field#getModifiers() * @see Modifier */ public static <V> void setStaticField(Class<?> klass, String name, V value) { try { Field field = klass.getDeclaredField(name); field.setAccessible(true); // remove final modifier from field int modifier = unfinalize(field); field.set(null, value); setModifier(field, modifier); field.setAccessible(false); } catch (SecurityException e) { throw new IllegalStateException("Cannot set static field " + name + " from class " + klass, e); } catch (NoSuchFieldException e) { throw new IllegalStateException("Cannot set static field " + name + " from class " + klass, e); } catch (IllegalArgumentException e) { throw new IllegalStateException("Cannot set static field " + name + " from class " + klass, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot set static field " + name + " from class " + klass, e); } } private static int unfinalize(Field field) { try { Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); int modifier = field.getModifiers(); if (Modifier.isFinal(modifier)) { modifiersField.setInt(field, modifier & ~Modifier.FINAL); } modifiersField.setAccessible(false); return modifier; } catch (SecurityException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } catch (NoSuchFieldException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } catch (IllegalArgumentException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } } private static void setModifier(Field field, int modifier) { try { Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, modifier); modifiersField.setAccessible(false); } catch (SecurityException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } catch (NoSuchFieldException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } catch (IllegalArgumentException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot change modifier for field " + field, e); } } }