1 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 ; 17 import java.lang.reflect.InvocationTargetException ; 18 import java.lang.reflect.Method ; 19 import java.lang.reflect.Modifier ; 20 21 public class FieldUtils { 22 public final static String CLASS = "com/tc/util/FieldUtils"; 23 24 public final static String GET_DESC = "(Ljava/lang/Object;Ljava/lang/reflect/Field;Lsun/reflect/FieldAccessor;)"; 25 26 private static ThreadLocal allowAccess = new ThreadLocal (); 27 28 private static boolean isTCField(Field field) { 29 return field.getName().startsWith(ByteCodeUtil.TC_FIELD_PREFIX); 30 } 31 32 public static Object get(Object obj, Field 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 return fieldAccessor.get(obj); 47 } 48 49 private static void throwIllegalArgumentException(String type) { 50 StringBuffer sb = new StringBuffer ("The argument of type "); 51 sb.append(type); 52 sb.append(" is illegal."); 53 throw new IllegalArgumentException (type); 54 } 55 56 public static boolean setBoolean(Object obj, boolean value, Field field) throws IllegalAccessException { 57 if (Type.getType(field.getType()).getSort() != Type.BOOLEAN) { 58 throwIllegalArgumentException(field.getType().getName()); 59 } 60 61 return set(obj, new Boolean (value), field); 62 } 63 64 public static boolean setFloat(Object obj, float value, Field field) throws IllegalAccessException { 65 Type fieldType = Type.getType(field.getType()); 66 67 switch (fieldType.getSort()) { 68 case Type.FLOAT: 69 return set(obj, new Float (value), field); 70 default: 71 return setDouble(obj, value, field); 72 } 73 } 74 75 public static boolean setDouble(Object obj, double value, Field field) throws IllegalAccessException { 76 if (Type.getType(field.getType()).getSort() != Type.DOUBLE) { 77 throwIllegalArgumentException(field.getType().getName()); 78 } 79 80 return set(obj, new Double (value), field); 81 } 82 83 public static boolean setChar(Object obj, char value, Field field) throws IllegalAccessException { 84 Type fieldType = Type.getType(field.getType()); 85 86 switch (fieldType.getSort()) { 87 case Type.CHAR: 88 return set(obj, new Character (value), field); 89 default: 90 return setInt(obj, value, field); 91 } 92 } 93 94 public static boolean setByte(Object obj, byte value, Field field) throws IllegalAccessException { 95 Type fieldType = Type.getType(field.getType()); 96 97 switch (fieldType.getSort()) { 98 case Type.BYTE: 99 return set(obj, new Byte (value), field); 100 default: 101 return setShort(obj, value, field); 102 } 103 } 104 105 public static boolean setShort(Object obj, short value, Field field) throws IllegalAccessException { 106 Type fieldType = Type.getType(field.getType()); 107 108 switch (fieldType.getSort()) { 109 case Type.SHORT: 110 return set(obj, new Short (value), field); 111 default: 112 return setInt(obj, value, field); 113 } 114 } 115 116 public static boolean setInt(Object obj, int value, Field field) throws IllegalAccessException { 117 Type fieldType = Type.getType(field.getType()); 118 119 switch (fieldType.getSort()) { 120 case Type.INT: 121 return set(obj, new Integer (value), field); 122 default: 123 return setLong(obj, value, field); 124 } 125 } 126 127 public static boolean setLong(Object obj, long value, Field field) throws IllegalAccessException { 128 Type fieldType = Type.getType(field.getType()); 129 130 switch (fieldType.getSort()) { 131 case Type.LONG: 132 return set(obj, new Long (value), field); 133 default: 134 return setFloat(obj, value, field); 135 } 136 } 137 138 142 public static void tcSet(Object target, Object value, Field field) throws IllegalArgumentException , 143 IllegalAccessException { 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 field) { 154 return field == allowAccess.get(); 155 } 156 157 public static boolean set(Object obj, Object value, Field field) throws IllegalAccessException { 158 if (isTCField(field)) { return true; } 159 160 if (accessAllowed(field)) { 161 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 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 throw new IllegalAccessException ( 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 throw new IllegalAccessException ( 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 setValue((TransparentAccess) obj, field, value); 196 return true; 197 } 198 } 199 200 return false; 201 } 202 203 private static boolean isStaticField(Field field) { 204 return Modifier.isStatic(field.getModifiers()); 205 } 206 207 private static boolean isStaticAndNonRootField(Field field) { 208 return isStaticField(field) && !ManagerUtil.isRoot(field.getDeclaringClass().getName(), field.getName()); 209 } 210 211 private static Object resolveReference(TransparentAccess obj, Field field) { 212 return obj.__tc_getmanagedfield(fullFieldName(field)); 214 } 215 216 private static Object resolveReference(Object obj, Field field) { 217 String fieldGetterMethodName = fieldGetterMethod(field.getName()); 218 try { 219 Method m = field.getDeclaringClass().getDeclaredMethod(fieldGetterMethodName, null); 220 m.setAccessible(true); 221 Object retValue = m.invoke(obj, null); 222 return retValue; 223 } catch (NoSuchMethodException e) { 224 throw new TCRuntimeException(e); 225 } catch (InvocationTargetException e) { 226 throw new TCRuntimeException(e); 227 } catch (IllegalArgumentException e) { 228 throw new TCRuntimeException(e); 229 } catch (IllegalAccessException e) { 230 throw new TCRuntimeException(e); 231 } 232 } 233 234 private static void setValue(Object obj, Field field, Object value) { 235 String fieldSetterMethodName = fieldSetterMethod(field.getName()); 236 Class [] setterArgumentsTypes = new Class [] { field.getType() }; 237 try { 238 Method m = field.getDeclaringClass().getDeclaredMethod(fieldSetterMethodName, setterArgumentsTypes); 239 m.setAccessible(true); 240 m.invoke(obj, new Object [] { value }); 241 } catch (NoSuchMethodException e) { 242 throw new TCRuntimeException(e); 243 } catch (InvocationTargetException e) { 244 throw new TCRuntimeException(e); 245 } catch (IllegalArgumentException e) { 246 throw new TCRuntimeException(e); 247 } catch (IllegalAccessException e) { 248 throw new TCRuntimeException(e); 249 } 250 251 } 252 253 private static void setValue(TransparentAccess obj, Field field, Object value) { 254 obj.__tc_setmanagedfield(fullFieldName(field), value); 256 } 257 258 private static String fullFieldName(Field field) { 259 return new StringBuffer (field.getDeclaringClass().getName()).append('.').append(field.getName()).toString(); 260 } 261 262 266 private static String fieldGetterMethod(String fieldName) { 267 return ByteCodeUtil.TC_METHOD_PREFIX + "get" + fieldName; 268 } 269 270 private static String fieldSetterMethod(String fieldName) { 271 return ByteCodeUtil.TC_METHOD_PREFIX + "set" + fieldName; 272 } 273 } 274 | Popular Tags |