package org.hotswap.agent.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.hotswap.agent.logging.AgentLogger;
/**
* Convenience methods on java reflection API.
*/
public class ReflectionHelper {
private static AgentLogger LOGGER = AgentLogger.getLogger(ReflectionHelper.class);
/**
* Convenience wrapper to reflection method invoke API. Invoke the method and hide checked exceptions.
*
* @param target object to invoke the method on (or null for static methods)
* @param clazz class name
* @param methodName method name
* @param parameterTypes parameter types to resolve method name
* @param args actual arguments
* @return invocation result or null
* @throws IllegalArgumentException if method not found
* @throws IllegalStateException for InvocationTargetException (exception in invoked method)
*/
public static Object invoke(Object target, Class<?> clazz, String methodName, Class[] parameterTypes, Object... args) {
try {
Method method = null;
try {
method = clazz.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
method = clazz.getDeclaredMethod(methodName, parameterTypes);
}
method.setAccessible(true);
return method.invoke(target, args);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("Illegal arguments method %s.%s(%s) on %s, params %s", clazz.getName(), methodName,
Arrays.toString(parameterTypes), target, Arrays.toString(args)), e);
} catch (InvocationTargetException e) {
throw new IllegalStateException(String.format("Error invoking method %s.%s(%s) on %s, params %s", clazz.getName(), methodName,
Arrays.toString(parameterTypes), target, Arrays.toString(args)), e);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(String.format("No such method %s.%s(%s) on %s, params %s", clazz.getName(), methodName,
Arrays.toString(parameterTypes), target, Arrays.toString(args)), e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(String.format("No such method %s.%s(%s) on %s, params %s", clazz.getName(), methodName,
Arrays.toString(parameterTypes), target, Arrays.toString(args)), e);
}
}
/**
* Convenience wrapper to reflection method invoke API. Get field value and hide checked exceptions.
* Field class is set by
*
* @param target object to get field value (or null for static methods)
* @param fieldName field name
* @return field value
* @throws IllegalArgumentException if field not found
*/
public static Object get(Object target, String fieldName) {
if (target == null)
throw new NullPointerException("Target object cannot be null.");
Class clazz = target.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
break;
} catch (NoSuchFieldException e) {
// ignore
}
clazz = clazz.getSuperclass();
}
if (clazz == null) {
throw new IllegalArgumentException(String.format("No such field %s.%s on %s", target.getClass(), fieldName, target));
}
return get(target, clazz, fieldName);
}
/**
* Convenience wrapper to reflection method invoke API. Get field value and hide checked exceptions.
*
* @param target object to get field value (or null for static methods)
* @param clazz class name
* @param fieldName field name
* @return field value
* @throws IllegalArgumentException if field not found
*/
public static Object get(Object target, Class<?> clazz, String fieldName) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(target);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException(String.format("No such field %s.%s on %s", clazz.getName(), fieldName, target), e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(String.format("Illegal access field %s.%s on %s", clazz.getName(), fieldName, target), e);
}
}
/**
* Convenience wrapper to reflection method invoke API. Get field value and swallow exceptions.
* Use this method if you have multiple framework support and the field may not exist in current version.
*
* @param target object to get field value (or null for static methods)
* @param clazz class name
* @param fieldName field name
* @return field value or null if an exception
*/
public static Object getNoException(Object target, Class<?> clazz, String fieldName) {
try {
return get(target, clazz, fieldName);
} catch (Exception e) {
LOGGER.trace("Error getting field {}.{} on object {}", e, clazz, fieldName, target);
return null;
}
}
/**
* Convenience wrapper to reflection method invoke API. Set field value and hide checked exceptions.
*
* @param target object to get field value (or null for static methods)
* @param clazz class name
* @param fieldName field name
* @param value field value
* @throws IllegalArgumentException if field not found
*/
public static void set(Object target, Class<?> clazz, String fieldName, Object value) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException(String.format("No such field %s.%s on %s", clazz.getName(), fieldName, target), e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(String.format("Illegal access field %s.%s on %s", clazz.getName(), fieldName, target), e);
}
}
}