Skip to content

Instantly share code, notes, and snippets.

@garcia-jj
Last active August 29, 2015 14:08
Show Gist options
  • Save garcia-jj/07a0258dbde3f5b98e95 to your computer and use it in GitHub Desktop.
Save garcia-jj/07a0258dbde3f5b98e95 to your computer and use it in GitHub Desktop.
package br.com.otavio.vraptor.custom;
import static java.lang.Character.toUpperCase;
import static java.util.Arrays.asList;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Default implementation for {@link ReflectionProvider} that uses pure Java Reflection API.
*
* @author Otávio S Garcia
*/
public class JdkReflectionProvider implements ReflectionProvider {
private static final List<String> GETTER_PREFIX_LIST = asList("is", "get");
@Override
public List<Method> getMethodsFor(Class<?> clazz) {
checkNotNull(clazz, "Input class can't be null");
List<Method> out = new ArrayList<Method>();
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) {
for (Method method : current.getDeclaredMethods()) {
makeAcessible(method);
out.add(method);
}
}
return out;
}
@Override
public Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
checkNotNull(clazz, "Input class can't be null");
checkNotNull(methodName, "Method name can't be null");
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) {
for (Method method : current.getDeclaredMethods()) {
if (method.getName().equals(methodName) && typesAreEquals(method.getParameterTypes(), parameterTypes)) {
makeAcessible(method);
return method;
}
}
}
return null;
}
@Override
public Object invoke(Object instance, Method method, Object... args) {
checkNotNull(instance, "Input instance can't be null");
checkNotNull(method, "Input method can't be null");
try {
makeAcessible(method);
return method.invoke(instance, args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
@Override
public Object invoke(Object instance, String methodName, Object... args) {
checkNotNull(instance, "Input instance can't be null");
checkNotNull(methodName, "Input method name can't be null");
Class<?>[] parameterTypes = extractParameterTypes(args);
Method method = getMethod(instance.getClass(), methodName, parameterTypes);
checkNotNull(method, "Method %s isn't found on %s", method, instance.getClass());
makeAcessible(method);
return invoke(instance, method, args);
}
@Override
public Object invokeGetter(Object instance, String fieldName) {
checkNotNull(instance, "Input instance can't be null");
checkNotNull(fieldName, "Field name can't be null");
String capitalizedName = captalize(fieldName);
Method method = findGetter(instance, capitalizedName);
checkNotNull(method, "A getter for %s isn't found on %s", fieldName, instance.getClass());
return invoke(instance, method);
}
private Method findGetter(Object instance, String capitalizedName) {
for (String prefix : GETTER_PREFIX_LIST) {
Method method = getMethod(instance.getClass(), prefix + capitalizedName);
if (method != null) {
return method;
}
}
return null;
}
@Override
public List<Field> getFieldsFor(Class<?> clazz) {
checkNotNull(clazz, "Input class can't be null");
List<Field> out = new ArrayList<Field>();
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) {
for (Field field : current.getDeclaredFields()) {
makeAcessible(field);
out.add(field);
}
}
return out;
}
@Override
public Field getField(Class<?> clazz, String fieldName) {
checkNotNull(clazz, "Input class can't be null");
checkNotNull(fieldName, "Field name can't be null");
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) {
for (Field field : current.getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
makeAcessible(field);
return field;
}
}
}
return null;
}
/**
* Set field or method as acessible to speed up reflection access.
*/
private void makeAcessible(AccessibleObject object) {
if (!object.isAccessible()) {
object.setAccessible(true);
}
}
private Class<?>[] extractParameterTypes(Object... args) {
Class<?>[] parameterTypes = new Class<?>[args.length];
for (int j = 0; j < args.length; j++) {
parameterTypes[j] = args[j].getClass();
}
return parameterTypes;
}
private String captalize(String fieldName) {
if (fieldName.length() == 1) {
return fieldName.toUpperCase();
}
return toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
}
private boolean typesAreEquals(Class<?>[] parameterTypes, Class<?>[] expectedTypes) {
return parameterTypes.length == expectedTypes.length
&& Arrays.equals(parameterTypes, expectedTypes);
}
private void checkNotNull(Object object, String message, Object... messageParams) {
if (object == null) {
throw new NullPointerException(String.format(message, messageParams));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment