001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.util;
020
021import java.lang.reflect.Field;
022import java.lang.reflect.InvocationTargetException;
023import java.lang.reflect.Method;
024
025/**
026 * Reflection tools class.
027 * 
028 * @author Stephane
029 */
030public class ReflectionUtil
031{
032    /**
033     * Return the Method object corresponding to the specified method name and parameters.
034     */
035    public static Method getMethod(Class<?> objectClass, String methodName, boolean forceAccess,
036            Class<?>... parameterTypes) throws SecurityException, NoSuchMethodException
037    {
038        Class<?> clazz = objectClass;
039        Method result = null;
040
041        while ((clazz != null) && (result == null))
042        {
043            try
044            {
045                result = clazz.getDeclaredMethod(methodName, parameterTypes);
046            }
047            catch (NoSuchMethodException e)
048            {
049                // ignore
050            }
051
052            clazz = clazz.getSuperclass();
053        }
054
055        if (result == null)
056            throw new NoSuchMethodException("Method " + methodName + "(..) not found in class " + objectClass.getName());
057
058        if (forceAccess)
059            result.setAccessible(true);
060
061        return result;
062    }
063
064    /**
065     * Return the Method object corresponding to the specified method name and parameters.
066     * 
067     * @deprecated Use {@link #getMethod(Class, String, boolean, Class...)} instead.
068     */
069    @Deprecated
070    public static Method getMethod(Object object, String methodName, boolean forceAccess, Class<?>... parameterTypes)
071            throws SecurityException, NoSuchMethodException
072    {
073        return getMethod(object.getClass(), methodName, forceAccess, parameterTypes);
074    }
075
076    /**
077     * Invoke the method of <code>object</code> corresponding to the specified name and with
078     * specified parameters values.
079     */
080    public static Object invokeMethod(Object object, String methodName, boolean forceAccess, Object... args)
081            throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
082            InvocationTargetException
083    {
084        final Class<?>[] parameterTypes = new Class<?>[args.length];
085
086        // build parameter types
087        for (int i = 0; i < args.length; i++)
088            parameterTypes[i] = args[i].getClass();
089
090        // get method
091        final Method method = getMethod(object, methodName, forceAccess, parameterTypes);
092        // invoke method
093        return method.invoke(object, args);
094    }
095
096    /**
097     * Return the Field object corresponding to the specified field name.
098     */
099    public static Field getField(Class<?> objectClass, String fieldName, boolean forceAccess) throws SecurityException,
100            NoSuchFieldException
101    {
102        Class<?> clazz = objectClass;
103        Field result = null;
104
105        while ((clazz != null) && (result == null))
106        {
107            try
108            {
109                result = clazz.getDeclaredField(fieldName);
110            }
111            catch (NoSuchFieldException e)
112            {
113                // ignore
114            }
115
116            clazz = clazz.getSuperclass();
117        }
118
119        if (result == null)
120            throw new NoSuchFieldException(" Field " + fieldName + " not found in class " + objectClass.getName());
121
122        if (forceAccess)
123            result.setAccessible(true);
124
125        return result;
126    }
127
128    /**
129     * Return the Field object corresponding to the specified field name.
130     * 
131     * @deprecated Use {@link #getField(Class, String, boolean)} instead.
132     */
133    @Deprecated
134    public static Field getField(Object object, String fieldName, boolean forceAccess) throws SecurityException,
135            NoSuchFieldException
136    {
137        return getField(object.getClass(), fieldName, forceAccess);
138    }
139
140    /**
141     * Return the object instance corresponding to the specified field name.
142     */
143    public static Object getFieldObject(Object object, String fieldName, boolean forceAccess)
144            throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException
145    {
146        return getField(object.getClass(), fieldName, forceAccess).get(object);
147    }
148}