KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > util > FieldUtils


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.util;
6
7 import sun.reflect.FieldAccessor;
8
9 import com.tc.asm.Type;
10 import com.tc.exception.TCRuntimeException;
11 import com.tc.object.bytecode.ByteCodeUtil;
12 import com.tc.object.bytecode.Manageable;
13 import com.tc.object.bytecode.ManagerUtil;
14 import com.tc.object.bytecode.TransparentAccess;
15
16 import java.lang.reflect.Field JavaDoc;
17 import java.lang.reflect.InvocationTargetException JavaDoc;
18 import java.lang.reflect.Method JavaDoc;
19 import java.lang.reflect.Modifier JavaDoc;
20
21 public class FieldUtils {
22   public final static String JavaDoc CLASS = "com/tc/util/FieldUtils";
23
24   public final static String JavaDoc GET_DESC = "(Ljava/lang/Object;Ljava/lang/reflect/Field;Lsun/reflect/FieldAccessor;)";
25
26   private static ThreadLocal JavaDoc allowAccess = new ThreadLocal JavaDoc();
27
28   private static boolean isTCField(Field JavaDoc field) {
29     return field.getName().startsWith(ByteCodeUtil.TC_FIELD_PREFIX);
30   }
31
32   public static Object JavaDoc get(Object JavaDoc obj, Field JavaDoc field, FieldAccessor fieldAccessor) {
33     if (isTCField(field)) {
34       return null;
35     } else if (!isStaticAndNonRootField(field)) {
36       if (ManagerUtil.isRoot(field.getDeclaringClass().getName(), field.getName())
37           || ManagerUtil.isPhysicallyInstrumented(field.getDeclaringClass())) {
38         if ((obj instanceof TransparentAccess) && !isStaticField(field)) {
39           return resolveReference((TransparentAccess) obj, field);
40         } else {
41           return resolveReference(obj, field);
42         }
43       }
44     }
45     // XXX: disallow field reads of shared logical objects?
46
return fieldAccessor.get(obj);
47   }
48
49   private static void throwIllegalArgumentException(String JavaDoc type) {
50     StringBuffer JavaDoc sb = new StringBuffer JavaDoc("The argument of type ");
51     sb.append(type);
52     sb.append(" is illegal.");
53     throw new IllegalArgumentException JavaDoc(type);
54   }
55
56   public static boolean setBoolean(Object JavaDoc obj, boolean value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
57     if (Type.getType(field.getType()).getSort() != Type.BOOLEAN) {
58       throwIllegalArgumentException(field.getType().getName());
59     }
60
61     return set(obj, new Boolean JavaDoc(value), field);
62   }
63
64   public static boolean setFloat(Object JavaDoc obj, float value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
65     Type fieldType = Type.getType(field.getType());
66
67     switch (fieldType.getSort()) {
68       case Type.FLOAT:
69         return set(obj, new Float JavaDoc(value), field);
70       default:
71         return setDouble(obj, value, field);
72     }
73   }
74
75   public static boolean setDouble(Object JavaDoc obj, double value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
76     if (Type.getType(field.getType()).getSort() != Type.DOUBLE) {
77       throwIllegalArgumentException(field.getType().getName());
78     }
79
80     return set(obj, new Double JavaDoc(value), field);
81   }
82
83   public static boolean setChar(Object JavaDoc obj, char value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
84     Type fieldType = Type.getType(field.getType());
85
86     switch (fieldType.getSort()) {
87       case Type.CHAR:
88         return set(obj, new Character JavaDoc(value), field);
89       default:
90         return setInt(obj, value, field);
91     }
92   }
93
94   public static boolean setByte(Object JavaDoc obj, byte value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
95     Type fieldType = Type.getType(field.getType());
96
97     switch (fieldType.getSort()) {
98       case Type.BYTE:
99         return set(obj, new Byte JavaDoc(value), field);
100       default:
101         return setShort(obj, value, field);
102     }
103   }
104
105   public static boolean setShort(Object JavaDoc obj, short value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
106     Type fieldType = Type.getType(field.getType());
107
108     switch (fieldType.getSort()) {
109       case Type.SHORT:
110         return set(obj, new Short JavaDoc(value), field);
111       default:
112         return setInt(obj, value, field);
113     }
114   }
115
116   public static boolean setInt(Object JavaDoc obj, int value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
117     Type fieldType = Type.getType(field.getType());
118
119     switch (fieldType.getSort()) {
120       case Type.INT:
121         return set(obj, new Integer JavaDoc(value), field);
122       default:
123         return setLong(obj, value, field);
124     }
125   }
126
127   public static boolean setLong(Object JavaDoc obj, long value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
128     Type fieldType = Type.getType(field.getType());
129
130     switch (fieldType.getSort()) {
131       case Type.LONG:
132         return set(obj, new Long JavaDoc(value), field);
133       default:
134         return setFloat(obj, value, field);
135     }
136   }
137
138   /*
139    * This method bypasses our check to set values to shared objects thru reflection. This is used from TC code base when
140    * this is needed. (like subclass of TreeMap, LinkedHashMap cases)
141    */

142   public static void tcSet(Object JavaDoc target, Object JavaDoc value, Field JavaDoc field) throws IllegalArgumentException JavaDoc,
143       IllegalAccessException JavaDoc {
144     allowAccess.set(field);
145     try {
146       field.set(target, value);
147     } finally {
148       allowAccess.set(null);
149     }
150
151   }
152
153   private static boolean accessAllowed(Field JavaDoc field) {
154     return field == allowAccess.get();
155   }
156
157   public static boolean set(Object JavaDoc obj, Object JavaDoc value, Field JavaDoc field) throws IllegalAccessException JavaDoc {
158     if (isTCField(field)) { return true; }
159
160     if (accessAllowed(field)) {
161       // returning false allows the orignial uninstrumented code to run.
162
return false;
163     }
164
165     if (isStaticAndNonRootField(field)) { return false; }
166
167     if (ManagerUtil.isRoot(field.getDeclaringClass().getName(), field.getName())) {
168       if ((obj instanceof TransparentAccess) && !isStaticField(field)) {
169         setValue((TransparentAccess) obj, field, value);
170       } else {
171         // This is an exception handling since we allow defining a field of an non-
172
// instrumented class to be a root.
173
setValue(obj, field, value);
174       }
175       return true;
176     }
177
178     if ((obj instanceof Manageable) && (((Manageable) obj).__tc_managed() != null)) {
179       if (ManagerUtil.isLogical(obj)) {
180         //
181
throw new IllegalAccessException JavaDoc(
182                                          "Field modification through reflection for non-physical shared object of type "
183                                              + obj.getClass().getName() + " is not supported!");
184       }
185
186       if (!TransparentAccess.class.isAssignableFrom(field.getDeclaringClass())) {
187         //
188
throw new IllegalAccessException JavaDoc(
189                                          "Field modification through reflection for fields of non-physically instrumented type "
190                                              + obj.getClass().getName() + " is not supported!");
191       }
192
193       if (obj instanceof TransparentAccess) {
194         // field of physically managed object
195
setValue((TransparentAccess) obj, field, value);
196         return true;
197       }
198     }
199
200     return false;
201   }
202
203   private static boolean isStaticField(Field JavaDoc field) {
204     return Modifier.isStatic(field.getModifiers());
205   }
206
207   private static boolean isStaticAndNonRootField(Field JavaDoc field) {
208     return isStaticField(field) && !ManagerUtil.isRoot(field.getDeclaringClass().getName(), field.getName());
209   }
210
211   private static Object JavaDoc resolveReference(TransparentAccess obj, Field JavaDoc field) {
212     // XXX: deal with statics
213
return obj.__tc_getmanagedfield(fullFieldName(field));
214   }
215
216   private static Object JavaDoc resolveReference(Object JavaDoc obj, Field JavaDoc field) {
217     String JavaDoc fieldGetterMethodName = fieldGetterMethod(field.getName());
218     try {
219       Method JavaDoc m = field.getDeclaringClass().getDeclaredMethod(fieldGetterMethodName, null);
220       m.setAccessible(true);
221       Object JavaDoc retValue = m.invoke(obj, null);
222       return retValue;
223     } catch (NoSuchMethodException JavaDoc e) {
224       throw new TCRuntimeException(e);
225     } catch (InvocationTargetException JavaDoc e) {
226       throw new TCRuntimeException(e);
227     } catch (IllegalArgumentException JavaDoc e) {
228       throw new TCRuntimeException(e);
229     } catch (IllegalAccessException JavaDoc e) {
230       throw new TCRuntimeException(e);
231     }
232   }
233
234   private static void setValue(Object JavaDoc obj, Field JavaDoc field, Object JavaDoc value) {
235     String JavaDoc fieldSetterMethodName = fieldSetterMethod(field.getName());
236     Class JavaDoc[] setterArgumentsTypes = new Class JavaDoc[] { field.getType() };
237     try {
238       Method JavaDoc m = field.getDeclaringClass().getDeclaredMethod(fieldSetterMethodName, setterArgumentsTypes);
239       m.setAccessible(true);
240       m.invoke(obj, new Object JavaDoc[] { value });
241     } catch (NoSuchMethodException JavaDoc e) {
242       throw new TCRuntimeException(e);
243     } catch (InvocationTargetException JavaDoc e) {
244       throw new TCRuntimeException(e);
245     } catch (IllegalArgumentException JavaDoc e) {
246       throw new TCRuntimeException(e);
247     } catch (IllegalAccessException JavaDoc e) {
248       throw new TCRuntimeException(e);
249     }
250
251   }
252
253   private static void setValue(TransparentAccess obj, Field JavaDoc field, Object JavaDoc value) {
254     // XXX: deal with statics
255
obj.__tc_setmanagedfield(fullFieldName(field), value);
256   }
257
258   private static String JavaDoc fullFieldName(Field JavaDoc field) {
259     return new StringBuffer JavaDoc(field.getDeclaringClass().getName()).append('.').append(field.getName()).toString();
260   }
261
262   /**
263    * fieldGetterMethod and fieldSetterMethod methods are copied from ByteCodeUtil in order not to put ByteCodeUtil in
264    * the boot jar.
265    */

266   private static String JavaDoc fieldGetterMethod(String JavaDoc fieldName) {
267     return ByteCodeUtil.TC_METHOD_PREFIX + "get" + fieldName;
268   }
269
270   private static String JavaDoc fieldSetterMethod(String JavaDoc fieldName) {
271     return ByteCodeUtil.TC_METHOD_PREFIX + "set" + fieldName;
272   }
273 }
274
Popular Tags