    001    /*
    002     * The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
    003     *
    004     * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
    005     * Software Foundation; either version 2.1 of the License, or any later version.
    006     *
    007     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
    008     * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    009     *
    010     * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
    011     * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    012     */
    013    package cpw.mods.fml.relauncher;
    014
    015    import java.lang.reflect.Field;
    016    import java.lang.reflect.Method;
    017    /**
    018     * Some reflection helper code.
    019     *
    020     * @author cpw
    021     *
    022     */
    023    public class ReflectionHelper
    024    {
    025        public static class UnableToFindMethodException extends RuntimeException
    026        {
    027            private String[] methodNames;
    028
    029            public UnableToFindMethodException(String[] methodNames, Exception failed)
    030            {
    031                super(failed);
    032                this.methodNames = methodNames;
    033            }
    034
    035        }
    036
    037        public static class UnableToFindClassException extends RuntimeException
    038        {
    039            private String[] classNames;
    040
    041            public UnableToFindClassException(String[] classNames, Exception err)
    042            {
    043                super(err);
    044                this.classNames = classNames;
    045            }
    046
    047        }
    048
    049        public static class UnableToAccessFieldException extends RuntimeException
    050        {
    051
    052            private String[] fieldNameList;
    053
    054            public UnableToAccessFieldException(String[] fieldNames, Exception e)
    055            {
    056                super(e);
    057                this.fieldNameList = fieldNames;
    058            }
    059        }
    060
    061        public static class UnableToFindFieldException extends RuntimeException
    062        {
    063            private String[] fieldNameList;
    064            public UnableToFindFieldException(String[] fieldNameList, Exception e)
    065            {
    066                super(e);
    067                this.fieldNameList = fieldNameList;
    068            }
    069        }
    070
    071        public static Field findField(Class<?> clazz, String... fieldNames)
    072        {
    073            Exception failed = null;
    074            for (String fieldName : fieldNames)
    075            {
    076                try
    077                {
    078                    Field f = clazz.getDeclaredField(fieldName);
    079                    f.setAccessible(true);
    080                    return f;
    081                }
    082                catch (Exception e)
    083                {
    084                    failed = e;
    085                }
    086            }
    087            throw new UnableToFindFieldException(fieldNames, failed);
    088        }
    089
    090        @SuppressWarnings("unchecked")
    091        public static <T, E> T getPrivateValue(Class <? super E > classToAccess, E instance, int fieldIndex)
    092        {
    093            try
    094            {
    095                Field f = classToAccess.getDeclaredFields()[fieldIndex];
    096                f.setAccessible(true);
    097                return (T) f.get(instance);
    098            }
    099            catch (Exception e)
    100            {
    101                throw new UnableToAccessFieldException(new String[0], e);
    102            }
    103        }
    104
    105        @SuppressWarnings("unchecked")
    106        public static <T, E> T getPrivateValue(Class <? super E > classToAccess, E instance, String... fieldNames)
    107        {
    108            try
    109            {
    110                return (T) findField(classToAccess, fieldNames).get(instance);
    111            }
    112            catch (Exception e)
    113            {
    114                throw new UnableToAccessFieldException(fieldNames, e);
    115            }
    116        }
    117
    118        public static <T, E> void setPrivateValue(Class <? super T > classToAccess, T instance, E value, int fieldIndex)
    119        {
    120            try
    121            {
    122                Field f = classToAccess.getDeclaredFields()[fieldIndex];
    123                f.setAccessible(true);
    124                f.set(instance, value);
    125            }
    126            catch (Exception e)
    127            {
    128                throw new UnableToAccessFieldException(new String[0] , e);
    129            }
    130        }
    131
    132        public static <T, E> void setPrivateValue(Class <? super T > classToAccess, T instance, E value, String... fieldNames)
    133        {
    134            try
    135            {
    136                findField(classToAccess, fieldNames).set(instance, value);
    137            }
    138            catch (Exception e)
    139            {
    140                throw new UnableToAccessFieldException(fieldNames, e);
    141            }
    142        }
    143
    144        public static Class<? super Object> getClass(ClassLoader loader, String... classNames)
    145        {
    146            Exception err = null;
    147            for (String className : classNames)
    148            {
    149                try
    150                {
    151                    return (Class<? super Object>) Class.forName(className, false, loader);
    152                }
    153                catch (Exception e)
    154                {
    155                    err = e;
    156                }
    157            }
    158
    159            throw new UnableToFindClassException(classNames, err);
    160        }
    161
    162
    163        public static <E> Method findMethod(Class<? super E> clazz, E instance, String[] methodNames, Class<?>... methodTypes)
    164        {
    165            Exception failed = null;
    166            for (String methodName : methodNames)
    167            {
    168                try
    169                {
    170                    Method m = clazz.getDeclaredMethod(methodName, methodTypes);
    171                    m.setAccessible(true);
    172                    return m;
    173                }
    174                catch (Exception e)
    175                {
    176                    failed = e;
    177                }
    178            }
    179            throw new UnableToFindMethodException(methodNames, failed);
    180        }
    181    }