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 }