/core/src/main/java/org/fakereplace/reflection/FieldReflection.java

https://github.com/stuartwdouglas/fakereplace · Java · 374 lines · 305 code · 45 blank · 24 comment · 82 complexity · faa944c4dd792465c0b21fbcd93579e9 MD5 · raw file

  1. /*
  2. * Copyright 2012, Stuart Douglas, and individual contributors as indicated
  3. * by the @authors tag.
  4. *
  5. * This is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU Lesser General Public License as
  7. * published by the Free Software Foundation; either version 2.1 of
  8. * the License, or (at your option) any later version.
  9. *
  10. * This software is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this software; if not, write to the Free
  17. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  18. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  19. */
  20. package org.fakereplace.reflection;
  21. import java.lang.reflect.Field;
  22. import java.lang.reflect.Modifier;
  23. import java.util.ArrayList;
  24. import java.util.Collection;
  25. import java.util.List;
  26. import javassist.bytecode.AccessFlag;
  27. import javassist.bytecode.Descriptor;
  28. import org.fakereplace.core.Constants;
  29. import org.fakereplace.data.ClassData;
  30. import org.fakereplace.data.ClassDataStore;
  31. import org.fakereplace.data.FieldData;
  32. import org.fakereplace.data.MemberType;
  33. import sun.reflect.Reflection;
  34. /**
  35. * Class that handles access to re-written fields.
  36. *
  37. * @author stuart
  38. */
  39. public class FieldReflection {
  40. public static Class<?> getDeclaringClass(Field f) {
  41. Class<?> c = f.getDeclaringClass();
  42. if (c.getName().startsWith(Constants.GENERATED_CLASS_PACKAGE)) {
  43. return ClassDataStore.instance().getRealClassFromProxyName(c.getName());
  44. }
  45. return c;
  46. }
  47. public static Field[] getDeclaredFields(Class<?> clazz) {
  48. if (!ClassDataStore.instance().isClassReplaced(clazz)) {
  49. return clazz.getDeclaredFields();
  50. }
  51. try {
  52. ClassData cd = ClassDataStore.instance().getModifiedClassData(clazz.getClassLoader(), Descriptor.toJvmName(clazz.getName()));
  53. Field[] meth = clazz.getDeclaredFields();
  54. Collection<FieldData> fieldData = cd.getFields();
  55. List<Field> visible = new ArrayList<Field>(meth.length);
  56. for (int i = 0; i < meth.length; ++i) {
  57. for (FieldData f : fieldData) {
  58. if (f.getAccessFlags() == meth[i].getModifiers() && f.getName().equals(meth[i].getName())) {
  59. if (f.getMemberType() == MemberType.NORMAL) {
  60. visible.add(meth[i]);
  61. break;
  62. }
  63. }
  64. }
  65. }
  66. for (FieldData i : cd.getFields()) {
  67. if (i.getMemberType() == MemberType.FAKE) {
  68. Class<?> c = clazz.getClassLoader().loadClass(i.getClassName());
  69. visible.add(i.getField(c));
  70. }
  71. }
  72. Field[] ret = new Field[visible.size()];
  73. for (int i = 0; i < visible.size(); ++i) {
  74. ret[i] = visible.get(i);
  75. }
  76. return ret;
  77. } catch (Exception e) {
  78. throw new RuntimeException(e);
  79. }
  80. }
  81. public static Field[] getFields(Class<?> clazz) {
  82. if (!ClassDataStore.instance().isClassReplaced(clazz)) {
  83. return clazz.getFields();
  84. }
  85. try {
  86. ClassData cd = ClassDataStore.instance().getModifiedClassData(clazz.getClassLoader(), Descriptor.toJvmName(clazz.getName()));
  87. if (cd == null) {
  88. return clazz.getDeclaredFields();
  89. }
  90. Field[] meth = clazz.getFields();
  91. Collection<FieldData> fieldData = cd.getFields();
  92. List<Field> visible = new ArrayList<Field>(meth.length);
  93. for (int i = 0; i < meth.length; ++i) {
  94. for (FieldData f : fieldData) {
  95. if (f.getAccessFlags() == meth[i].getModifiers() && f.getName().equals(meth[i].getName())) {
  96. if (f.getMemberType() == MemberType.NORMAL) {
  97. visible.add(meth[i]);
  98. break;
  99. }
  100. }
  101. }
  102. }
  103. ClassData cta = cd;
  104. while (cta != null) {
  105. for (FieldData i : cta.getFields()) {
  106. if (i.getMemberType() == MemberType.FAKE && AccessFlag.isPublic(i.getAccessFlags())) {
  107. Class<?> c = clazz.getClassLoader().loadClass(i.getClassName());
  108. visible.add(i.getField(c));
  109. }
  110. }
  111. cta = cta.getSuperClassInformation();
  112. }
  113. Field[] ret = new Field[visible.size()];
  114. for (int i = 0; i < visible.size(); ++i) {
  115. ret[i] = visible.get(i);
  116. }
  117. return ret;
  118. } catch (Exception e) {
  119. throw new RuntimeException(e);
  120. }
  121. }
  122. public static Field getField(Class<?> clazz, String name) throws NoSuchFieldException {
  123. if (!ClassDataStore.instance().isClassReplaced(clazz)) {
  124. return clazz.getField(name);
  125. }
  126. ClassData cd = ClassDataStore.instance().getModifiedClassData(clazz.getClassLoader(), Descriptor.toJvmName(clazz.getName()));
  127. if (cd == null) {
  128. return clazz.getField(name);
  129. }
  130. FieldData fd = cd.getField(name);
  131. if (fd == null) {
  132. return clazz.getField(name);
  133. }
  134. if (!AccessFlag.isPublic(fd.getAccessFlags())) {
  135. throw new NoSuchFieldException(clazz.getName() + "." + name);
  136. }
  137. switch (fd.getMemberType()) {
  138. case NORMAL:
  139. return clazz.getField(name);
  140. case FAKE:
  141. try {
  142. Class<?> c = clazz.getClassLoader().loadClass(fd.getClassName());
  143. return c.getField(name);
  144. } catch (NoSuchFieldException e) {
  145. throw e;
  146. } catch (Exception e) {
  147. throw new RuntimeException(e);
  148. }
  149. }
  150. throw new NoSuchFieldException();
  151. }
  152. public static Field getDeclaredField(Class<?> clazz, String name) throws NoSuchFieldException {
  153. if (!ClassDataStore.instance().isClassReplaced(clazz)) {
  154. return clazz.getDeclaredField(name);
  155. }
  156. ClassData cd = ClassDataStore.instance().getModifiedClassData(clazz.getClassLoader(), Descriptor.toJvmName(clazz.getName()));
  157. if (cd == null) {
  158. return clazz.getDeclaredField(name);
  159. }
  160. FieldData fd = cd.getField(name);
  161. if (fd == null) {
  162. return clazz.getDeclaredField(name);
  163. }
  164. switch (fd.getMemberType()) {
  165. case NORMAL:
  166. return clazz.getDeclaredField(name);
  167. case FAKE:
  168. try {
  169. Class<?> c = clazz.getClassLoader().loadClass(fd.getClassName());
  170. return c.getDeclaredField(name);
  171. } catch (NoSuchFieldException e) {
  172. throw e;
  173. } catch (Exception e) {
  174. throw new RuntimeException(e);
  175. }
  176. }
  177. throw new NoSuchFieldException();
  178. }
  179. public static void set(Field f, Object object, Object val) throws IllegalAccessException {
  180. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  181. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  182. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  183. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  184. }
  185. accessor.set(object, val);
  186. }
  187. public static void setBoolean(Field f, Object object, boolean val) throws IllegalAccessException {
  188. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  189. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  190. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  191. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  192. }
  193. accessor.set(object, val);
  194. }
  195. public static void setByte(Field f, Object object, byte val) throws IllegalAccessException {
  196. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  197. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  198. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  199. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  200. }
  201. accessor.set(object, val);
  202. }
  203. public static void setChar(Field f, Object object, char val) throws IllegalAccessException {
  204. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  205. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  206. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  207. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  208. }
  209. accessor.set(object, val);
  210. }
  211. public static void setDouble(Field f, Object object, double val) throws IllegalAccessException {
  212. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  213. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  214. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  215. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  216. }
  217. accessor.set(object, val);
  218. }
  219. public static void setFloat(Field f, Object object, float val) throws IllegalAccessException {
  220. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  221. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  222. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  223. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  224. }
  225. accessor.set(object, val);
  226. }
  227. public static void setInt(Field f, Object object, int val) throws IllegalAccessException {
  228. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  229. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  230. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  231. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  232. }
  233. accessor.set(object, val);
  234. }
  235. public static void setLong(Field f, Object object, long val) throws IllegalAccessException {
  236. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  237. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  238. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  239. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  240. }
  241. accessor.set(object, val);
  242. }
  243. public static void setShort(Field f, Object object, short val) throws IllegalAccessException {
  244. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  245. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  246. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  247. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  248. }
  249. accessor.set(object, val);
  250. }
  251. public static Object get(Field f, Object object) throws IllegalAccessException {
  252. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  253. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  254. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  255. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  256. }
  257. return accessor.get(object);
  258. }
  259. public static boolean getBoolean(Field f, Object object) throws IllegalAccessException {
  260. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  261. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  262. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  263. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  264. }
  265. return (Boolean) accessor.get(object);
  266. }
  267. public static byte getByte(Field f, Object object) throws IllegalAccessException {
  268. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  269. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  270. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  271. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  272. }
  273. return (Byte) accessor.get(object);
  274. }
  275. public static char getChar(Field f, Object object) throws IllegalAccessException {
  276. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  277. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  278. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  279. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  280. }
  281. return (Character) accessor.get(object);
  282. }
  283. public static Double getDouble(Field f, Object object) throws IllegalAccessException {
  284. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  285. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  286. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  287. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  288. }
  289. return (Double) accessor.get(object);
  290. }
  291. public static float getFloat(Field f, Object object) throws IllegalAccessException {
  292. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  293. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  294. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  295. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  296. }
  297. return (Float) accessor.get(object);
  298. }
  299. public static int getInt(Field f, Object object) throws IllegalAccessException {
  300. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  301. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  302. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  303. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  304. }
  305. return (Integer) accessor.get(object);
  306. }
  307. public static long getLong(Field f, Object object) throws IllegalAccessException {
  308. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  309. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  310. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  311. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  312. }
  313. return (Long) accessor.get(object);
  314. }
  315. public static Object getShort(Field f, Object object) throws IllegalAccessException {
  316. FieldAccessor accessor = ClassDataStore.instance().getFieldAccessor(f.getDeclaringClass().getName());
  317. if (!Modifier.isPublic(f.getModifiers()) && !f.isAccessible()) {
  318. Class<?> caller = sun.reflect.Reflection.getCallerClass(2);
  319. Reflection.ensureMemberAccess(caller, accessor.getDeclaringClass(), null, f.getModifiers());
  320. }
  321. return (Short) accessor.get(object);
  322. }
  323. public static boolean isFakeField(Field f) {
  324. if ((f.getModifiers() & Modifier.STATIC) == 0 && f.getDeclaringClass().getName().startsWith(org.fakereplace.core.Constants.GENERATED_CLASS_PACKAGE)) {
  325. return true;
  326. }
  327. return false;
  328. }
  329. }