/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.swt.runtime.internal.macosx;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionUtil {
/**
* Return the value (as an Object) of the given field from the given object.
* @return the {@link Object} value of field with given name.
*/
public static Object getFieldObject(final Object object, final String name) {
Class<?> refClass = getRefClass(object);
Object refObject = getRefObject(object);
Field field = getFieldByName(refClass, name);
if (field == null) {
throw new IllegalArgumentException("Unable to find '" + name + "' in " + refClass);
}
Throwable thrown = null;
try {
return field.get(refObject);
} catch (IllegalAccessException ex) {
thrown = ex;
} catch (IllegalArgumentException ex) {
thrown = ex;
} catch (NullPointerException ex) {
thrown = ex;
} catch (ExceptionInInitializerError ex) {
thrown = ex;
}
// DEBUG
thrown.printStackTrace();
throw new RuntimeException("ERROR in getFieldObject() " + thrown.getMessage());
}
/**
* Return the value (as an int) of the given field from the given object.
* @return the <code>int</code> value of field with given name.
*/
public static int getFieldInt(Object object, String name) {
return ((Integer) getFieldObject(object, name)).intValue();
}
/**
* @return the <code>long</code> value of field with given name.
*/
public static long getFieldLong(Object object, String name) {
return ((Long) getFieldObject(object, name)).longValue();
}
/**
* Return the field with the given name in the given class.
* TODO Verify search order corresponds to Java spec.
* @return the {@link Field} of given class with given name or <code>null</code> if no such {@link Field} found.
*/
public static Field getFieldByName(Class<?> theClass, String name) {
Class<?> clazz = theClass;
// check fields of given class and its super classes
while (clazz != null) {
// check all declared field
Field[] declaredFields = clazz.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i];
if (field.getName().equals(name)) {
field.setAccessible(true);
return field;
}
}
// check interfaces
Class<?>[] interfaceClasses = clazz.getInterfaces();
for (int i = 0; i < interfaceClasses.length; i++) {
Class<?> interfaceClass = interfaceClasses[i];
Field field = getFieldByName(interfaceClass, name);
if (field != null) {
return field;
}
}
// check superclass
clazz = clazz.getSuperclass();
}
return null; // not found
}
/**
* @return the {@link Class} of given {@link Object} or casted object, if it is {@link Class} itself.
*/
private static Class<?> getRefClass(Object object) {
return object instanceof Class<?> ? (Class<?>) object : object.getClass();
}
/**
* @return the {@link Object} that should be used as argument for {@link Field#get(Object)} and
* {@link Method#invoke(Object, Object[])}.
*/
private static Object getRefObject(Object object) {
return object instanceof Class<?> ? null : object;
}
}