1 15 16 package javassist.reflect; 17 18 import javassist.*; 19 import javassist.CtMethod.ConstParameter; 20 21 62 public class Reflection implements Translator { 63 64 static final String classobjectField = "_classobject"; 65 static final String classobjectAccessor = "_getClass"; 66 static final String metaobjectField = "_metaobject"; 67 static final String metaobjectGetter = "_getMetaobject"; 68 static final String metaobjectSetter = "_setMetaobject"; 69 static final String readPrefix = "_r_"; 70 static final String writePrefix = "_w_"; 71 72 static final String metaobjectClassName = "javassist.reflect.Metaobject"; 73 static final String classMetaobjectClassName 74 = "javassist.reflect.ClassMetaobject"; 75 76 protected CtMethod trapMethod, trapStaticMethod; 77 protected CtMethod trapRead, trapWrite; 78 protected CtClass[] readParam; 79 80 protected ClassPool classPool; 81 protected CodeConverter converter; 82 83 private boolean isExcluded(String name) { 84 return name.startsWith(ClassMetaobject.methodPrefix) 85 || name.equals(classobjectAccessor) 86 || name.equals(metaobjectSetter) 87 || name.equals(metaobjectGetter) 88 || name.startsWith(readPrefix) 89 || name.startsWith(writePrefix); 90 } 91 92 95 public Reflection() { 96 classPool = null; 97 converter = new CodeConverter(); 98 } 99 100 103 public void start(ClassPool pool) throws NotFoundException { 104 classPool = pool; 105 final String msg 106 = "javassist.reflect.Sample is not found or broken."; 107 try { 108 CtClass c = classPool.get("javassist.reflect.Sample"); 109 trapMethod = c.getDeclaredMethod("trap"); 110 trapStaticMethod = c.getDeclaredMethod("trapStatic"); 111 trapRead = c.getDeclaredMethod("trapRead"); 112 trapWrite = c.getDeclaredMethod("trapWrite"); 113 readParam 114 = new CtClass[] { classPool.get("java.lang.Object") }; 115 } 116 catch (NotFoundException e) { 117 throw new RuntimeException (msg); 118 } 119 } 120 121 125 public void onLoad(ClassPool pool, String classname) 126 throws CannotCompileException, NotFoundException 127 { 128 CtClass clazz = pool.get(classname); 129 clazz.instrument(converter); 130 } 131 132 145 public boolean makeReflective(String classname, 146 String metaobject, String metaclass) 147 throws CannotCompileException, NotFoundException 148 { 149 return makeReflective(classPool.get(classname), 150 classPool.get(metaobject), 151 classPool.get(metaclass)); 152 } 153 154 171 public boolean makeReflective(Class clazz, 172 Class metaobject, Class metaclass) 173 throws CannotCompileException, NotFoundException 174 { 175 return makeReflective(clazz.getName(), metaobject.getName(), 176 metaclass.getName()); 177 } 178 179 197 public boolean makeReflective(CtClass clazz, 198 CtClass metaobject, CtClass metaclass) 199 throws CannotCompileException, CannotReflectException, 200 NotFoundException 201 { 202 if (clazz.isInterface()) 203 throw new CannotReflectException( 204 "Cannot reflect an interface: " + clazz.getName()); 205 206 if (clazz.subclassOf(classPool.get(classMetaobjectClassName))) 207 throw new CannotReflectException( 208 "Cannot reflect a subclass of ClassMetaobject: " 209 + clazz.getName()); 210 211 if (clazz.subclassOf(classPool.get(metaobjectClassName))) 212 throw new CannotReflectException( 213 "Cannot reflect a subclass of Metaobject: " 214 + clazz.getName()); 215 216 registerReflectiveClass(clazz); 217 return modifyClassfile(clazz, metaobject, metaclass); 218 } 219 220 224 private void registerReflectiveClass(CtClass clazz) { 225 CtField[] fs = clazz.getDeclaredFields(); 226 for (int i = 0; i < fs.length; ++i) { 227 CtField f = fs[i]; 228 int mod = f.getModifiers(); 229 if ((mod & Modifier.PUBLIC) != 0 && (mod & Modifier.FINAL) == 0) { 230 String name = f.getName(); 231 converter.replaceFieldRead(f, clazz, readPrefix + name); 232 converter.replaceFieldWrite(f, clazz, writePrefix + name); 233 } 234 } 235 } 236 237 private boolean modifyClassfile(CtClass clazz, CtClass metaobject, 238 CtClass metaclass) 239 throws CannotCompileException, NotFoundException 240 { 241 if (clazz.getAttribute("Reflective") != null) 242 return false; else 244 clazz.setAttribute("Reflective", new byte[0]); 245 246 CtClass mlevel = classPool.get("javassist.reflect.Metalevel"); 247 boolean addMeta = !clazz.subtypeOf(mlevel); 248 if (addMeta) 249 clazz.addInterface(mlevel); 250 251 processMethods(clazz, addMeta); 252 processFields(clazz); 253 254 CtField f; 255 if (addMeta) { 256 f = new CtField(classPool.get("javassist.reflect.Metaobject"), 257 metaobjectField, clazz); 258 f.setModifiers(Modifier.PROTECTED); 259 clazz.addField(f, CtField.Initializer.byNewWithParams(metaobject)); 260 261 clazz.addMethod(CtNewMethod.getter(metaobjectGetter, f)); 262 clazz.addMethod(CtNewMethod.setter(metaobjectSetter, f)); 263 } 264 265 f = new CtField(classPool.get("javassist.reflect.ClassMetaobject"), 266 classobjectField, clazz); 267 f.setModifiers(Modifier.PRIVATE | Modifier.STATIC); 268 clazz.addField(f, CtField.Initializer.byNew(metaclass, 269 new String [] { clazz.getName() })); 270 271 clazz.addMethod(CtNewMethod.getter(classobjectAccessor, f)); 272 return true; 273 } 274 275 private void processMethods(CtClass clazz, boolean dontSearch) 276 throws CannotCompileException, NotFoundException 277 { 278 CtMethod[] ms = clazz.getMethods(); 279 int identifier = 0; 280 for (int i = 0; i < ms.length; ++i) { 281 CtMethod m = ms[i]; 282 int mod = m.getModifiers(); 283 if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) 284 processMethods0(mod, clazz, m, i, dontSearch); 285 } 286 } 287 288 private void processMethods0(int mod, CtClass clazz, 289 CtMethod m, int identifier, boolean dontSearch) 290 throws CannotCompileException, NotFoundException 291 { 292 CtMethod body; 293 String name = m.getName(); 294 295 if (isExcluded(name)) return; 298 CtMethod m2; 299 if (m.getDeclaringClass() == clazz) { 300 if (Modifier.isNative(mod)) 301 return; 302 303 m2 = m; 304 if (Modifier.isFinal(mod)) { 305 mod &= ~Modifier.FINAL; 306 m2.setModifiers(mod); 307 } 308 } 309 else { 310 if (Modifier.isFinal(mod)) 311 return; 312 313 mod &= ~Modifier.NATIVE; 314 m2 = CtNewMethod.delegator(findOriginal(m, dontSearch), clazz); 315 m2.setModifiers(mod); 316 clazz.addMethod(m2); 317 } 318 319 m2.setName(ClassMetaobject.methodPrefix + identifier 320 + "_" + name); 321 322 if (Modifier.isStatic(mod)) 323 body = trapStaticMethod; 324 else 325 body = trapMethod; 326 327 CtMethod wmethod 328 = CtNewMethod.wrapped(m.getReturnType(), name, 329 m.getParameterTypes(), m.getExceptionTypes(), 330 body, ConstParameter.integer(identifier), 331 clazz); 332 wmethod.setModifiers(mod); 333 clazz.addMethod(wmethod); 334 } 335 336 private CtMethod findOriginal(CtMethod m, boolean dontSearch) 337 throws NotFoundException 338 { 339 if (dontSearch) 340 return m; 341 342 String name = m.getName(); 343 CtMethod[] ms = m.getDeclaringClass().getDeclaredMethods(); 344 for (int i = 0; i < ms.length; ++i) { 345 String orgName = ms[i].getName(); 346 if (orgName.endsWith(name) 347 && orgName.startsWith(ClassMetaobject.methodPrefix) 348 && ms[i].getSignature().equals(m.getSignature())) 349 return ms[i]; 350 } 351 352 return m; 353 } 354 355 private void processFields(CtClass clazz) 356 throws CannotCompileException, NotFoundException 357 { 358 CtField[] fs = clazz.getDeclaredFields(); 359 for (int i = 0; i < fs.length; ++i) { 360 CtField f = fs[i]; 361 int mod = f.getModifiers(); 362 if ((mod & Modifier.PUBLIC) != 0 && (mod & Modifier.FINAL) == 0) { 363 mod |= Modifier.STATIC; 364 String name = f.getName(); 365 CtClass ftype = f.getType(); 366 CtMethod wmethod 367 = CtNewMethod.wrapped(ftype, readPrefix + name, 368 readParam, null, trapRead, 369 ConstParameter.string(name), 370 clazz); 371 wmethod.setModifiers(mod); 372 clazz.addMethod(wmethod); 373 CtClass[] writeParam = new CtClass[2]; 374 writeParam[0] = classPool.get("java.lang.Object"); 375 writeParam[1] = ftype; 376 wmethod = CtNewMethod.wrapped(CtClass.voidType, 377 writePrefix + name, 378 writeParam, null, trapWrite, 379 ConstParameter.string(name), clazz); 380 wmethod.setModifiers(mod); 381 clazz.addMethod(wmethod); 382 } 383 } 384 } 385 } 386 | Popular Tags |