blob: 1cbec0082858c78ab6831fd82422d128aed51ad9 [file] [log] [blame]
/*
* Copyright (c) 2014 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
* Christian W. Damus (CEA) - bug 376620: switch on primitive types
*/
package org.eclipse.oomph.util;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Various static helper methods for dealing with Java reflection.
*
* @author Eike Stepper
*/
public final class ReflectUtil
{
private ReflectUtil()
{
}
public static <T> Constructor<T> getConstructor(Class<T> c, Class<?>... parameterTypes)
{
try
{
Constructor<T> constructor = c.getDeclaredConstructor(parameterTypes);
makeAccessible(constructor);
return constructor;
}
catch (RuntimeException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
public static <T> T newInstance(Constructor<T> constructor, Object... arguments)
{
try
{
return constructor.newInstance(arguments);
}
catch (RuntimeException ex)
{
throw ex;
}
catch (InvocationTargetException ex)
{
Throwable cause = ex.getCause();
if (cause != null && "org.eclipse.core.runtime.OperationCanceledException".equals(cause.getClass().getName()))
{
throw (RuntimeException)cause;
}
throw new ReflectionException(cause);
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
public static Method getMethod(Object target, String methodName, Class<?>... parameterTypes)
{
return getMethod(target.getClass(), methodName, parameterTypes);
}
public static Method getMethod(Class<?> c, String methodName, Class<?>... parameterTypes)
{
try
{
try
{
Method method = c.getDeclaredMethod(methodName, parameterTypes);
makeAccessible(method);
return method;
}
catch (NoSuchMethodException ex)
{
Class<?> superclass = c.getSuperclass();
if (superclass != null)
{
return getMethod(superclass, methodName, parameterTypes);
}
throw ex;
}
}
catch (RuntimeException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
public static Object invokeMethod(Method method, Object target, Object... arguments)
{
try
{
return method.invoke(target, arguments);
}
catch (RuntimeException ex)
{
throw ex;
}
catch (InvocationTargetException ex)
{
Throwable cause = ex.getCause();
if (cause != null && "org.eclipse.core.runtime.OperationCanceledException".equals(cause.getClass().getName()))
{
throw (RuntimeException)cause;
}
throw new ReflectionException(cause);
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
public static Object invokeMethod(String methodName, Object target)
{
if (target instanceof Class)
{
return invokeMethod(getMethod((Class<?>)target, methodName), null);
}
return invokeMethod(getMethod(target.getClass(), methodName), target);
}
public static Field getField(Class<?> c, String fieldName)
{
try
{
try
{
Field field = c.getDeclaredField(fieldName);
makeAccessible(field);
return field;
}
catch (NoSuchFieldException ex)
{
Class<?> superclass = c.getSuperclass();
if (superclass != null)
{
return getField(superclass, fieldName);
}
return null;
}
}
catch (RuntimeException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
public static <T> T getValue(Field field, Object target)
{
try
{
@SuppressWarnings("unchecked")
T value = (T)field.get(target);
return value;
}
catch (RuntimeException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
public static <T> T getValue(String fieldName, Object target)
{
if (target instanceof Class)
{
return getValue(getField((Class<?>)target, fieldName), null);
}
return getValue(getField(target.getClass(), fieldName), target);
}
public static void setValue(String fieldName, Object target, Object value)
{
if (target instanceof Class)
{
setValue(getField((Class<?>)target, fieldName), null, value);
}
else
{
setValue(getField(target.getClass(), fieldName), target, value);
}
}
public static void setValue(Field field, Object target, Object value)
{
setValue(field, target, value, false);
}
public static void setValue(Field field, Object target, Object value, boolean force)
{
try
{
if ((field.getModifiers() & Modifier.FINAL) != 0 && force)
{
Field modifiersField = Field.class.getDeclaredField("modifiers");
makeAccessible(modifiersField);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
}
Class<?> type = field.getType();
if (type.isPrimitive())
{
if (boolean.class == type)
{
field.setBoolean(target, (Boolean)value);
}
else if (char.class == type)
{
field.setChar(target, (Character)value);
}
else if (byte.class == type)
{
field.setByte(target, (Byte)value);
}
else if (short.class == type)
{
field.setShort(target, (Short)value);
}
else if (int.class == type)
{
field.setInt(target, (Integer)value);
}
else if (long.class == type)
{
field.setLong(target, (Long)value);
}
else if (float.class == type)
{
field.setFloat(target, (Float)value);
}
else if (double.class == type)
{
field.setDouble(target, (Double)value);
}
}
else
{
field.set(target, value);
}
}
catch (RuntimeException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new ReflectionException(ex);
}
}
private static <T> void makeAccessible(AccessibleObject accessibleObject)
{
if (!accessibleObject.isAccessible())
{
accessibleObject.setAccessible(true);
}
}
/**
* @author Eike Stepper
*/
public static class ReflectionException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public ReflectionException()
{
}
public ReflectionException(String message, Throwable cause)
{
super(message, cause);
}
public ReflectionException(String message)
{
super(message);
}
public ReflectionException(Throwable cause)
{
super(cause);
}
}
}