169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.tools.reflect; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtMethod.ConstParameter; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The class implementing the behavioral reflection mechanism. 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If a class is reflective, 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * then all the method invocations on every 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * instance of that class are intercepted by the runtime 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * metaobject controlling that instance. The methods inherited from the 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * super classes are also intercepted except final methods. To intercept 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a final method in a super class, that super class must be also reflective. 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>To do this, the original class file representing a reflective class: 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre> 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class Person { 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int f(int i) { return i + 1; } 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int value; 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * } 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>is modified so that it represents a class: 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre> 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class Person implements Metalevel { 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int _original_f(int i) { return i + 1; } 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int f(int i) { <i>delegate to the metaobject</i> } 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int value; 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public int _r_value() { <i>read "value"</i> } 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public void _w_value(int v) { <i>write "value"</i> } 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public ClassMetaobject _getClass() { <i>return a class metaobject</i> } 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public Metaobject _getMetaobject() { <i>return a metaobject</i> } 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public void _setMetaobject(Metaobject m) { <i>change a metaobject</i> } 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * } 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.ClassMetaobject 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metaobject 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Loader 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Compiler 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Reflection implements Translator { 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String classobjectField = "_classobject"; 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String classobjectAccessor = "_getClass"; 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String metaobjectField = "_metaobject"; 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String metaobjectGetter = "_getMetaobject"; 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String metaobjectSetter = "_setMetaobject"; 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String readPrefix = "_r_"; 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String writePrefix = "_w_"; 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String metaobjectClassName = "javassist.tools.reflect.Metaobject"; 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String classMetaobjectClassName 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = "javassist.tools.reflect.ClassMetaobject"; 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected CtMethod trapMethod, trapStaticMethod; 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected CtMethod trapRead, trapWrite; 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected CtClass[] readParam; 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected ClassPool classPool; 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected CodeConverter converter; 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean isExcluded(String name) { 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return name.startsWith(ClassMetaobject.methodPrefix) 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || name.equals(classobjectAccessor) 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || name.equals(metaobjectSetter) 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || name.equals(metaobjectGetter) 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || name.startsWith(readPrefix) 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || name.startsWith(writePrefix); 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a new <code>Reflection</code> object. 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Reflection() { 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool = null; 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal converter = new CodeConverter(); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Initializes the object. 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void start(ClassPool pool) throws NotFoundException { 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool = pool; 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal final String msg 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = "javassist.tools.reflect.Sample is not found or broken."; 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass c = classPool.get("javassist.tools.reflect.Sample"); 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal trapMethod = c.getDeclaredMethod("trap"); 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal trapStaticMethod = c.getDeclaredMethod("trapStatic"); 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal trapRead = c.getDeclaredMethod("trapRead"); 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal trapWrite = c.getDeclaredMethod("trapWrite"); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal readParam 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new CtClass[] { classPool.get("java.lang.Object") }; 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException(msg); 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Inserts hooks for intercepting accesses to the fields declared 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in reflective classes. 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void onLoad(ClassPool pool, String classname) 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass clazz = pool.get(classname); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.instrument(converter); 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Produces a reflective class. 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If the super class is also made reflective, it must be done 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * before the sub class. 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classname the name of the reflective class 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param metaobject the class name of metaobjects. 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param metaclass the class name of the class metaobject. 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return <code>false</code> if the class is already reflective. 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metaobject 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.ClassMetaobject 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean makeReflective(String classname, 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String metaobject, String metaclass) 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return makeReflective(classPool.get(classname), 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool.get(metaobject), 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool.get(metaclass)); 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Produces a reflective class. 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If the super class is also made reflective, it must be done 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * before the sub class. 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param clazz the reflective class. 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param metaobject the class of metaobjects. 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It must be a subclass of 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Metaobject</code>. 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param metaclass the class of the class metaobject. 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It must be a subclass of 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>ClassMetaobject</code>. 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return <code>false</code> if the class is already reflective. 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metaobject 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.ClassMetaobject 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean makeReflective(Class clazz, 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class metaobject, Class metaclass) 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return makeReflective(clazz.getName(), metaobject.getName(), 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal metaclass.getName()); 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Produces a reflective class. It modifies the given 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>CtClass</code> object and makes it reflective. 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If the super class is also made reflective, it must be done 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * before the sub class. 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param clazz the reflective class. 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param metaobject the class of metaobjects. 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It must be a subclass of 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Metaobject</code>. 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param metaclass the class of the class metaobject. 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It must be a subclass of 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>ClassMetaobject</code>. 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return <code>false</code> if the class is already reflective. 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metaobject 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.ClassMetaobject 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean makeReflective(CtClass clazz, 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass metaobject, CtClass metaclass) 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, CannotReflectException, 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal NotFoundException 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (clazz.isInterface()) 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotReflectException( 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "Cannot reflect an interface: " + clazz.getName()); 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (clazz.subclassOf(classPool.get(classMetaobjectClassName))) 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotReflectException( 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "Cannot reflect a subclass of ClassMetaobject: " 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + clazz.getName()); 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (clazz.subclassOf(classPool.get(metaobjectClassName))) 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotReflectException( 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "Cannot reflect a subclass of Metaobject: " 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + clazz.getName()); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal registerReflectiveClass(clazz); 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return modifyClassfile(clazz, metaobject, metaclass); 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Registers a reflective class. The field accesses to the instances 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * of this class are instrumented. 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void registerReflectiveClass(CtClass clazz) { 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtField[] fs = clazz.getDeclaredFields(); 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < fs.length; ++i) { 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtField f = fs[i]; 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int mod = f.getModifiers(); 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if ((mod & Modifier.PUBLIC) != 0 && (mod & Modifier.FINAL) == 0) { 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = f.getName(); 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal converter.replaceFieldRead(f, clazz, readPrefix + name); 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal converter.replaceFieldWrite(f, clazz, writePrefix + name); 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean modifyClassfile(CtClass clazz, CtClass metaobject, 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass metaclass) 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (clazz.getAttribute("Reflective") != null) 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; // this is already reflective. 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.setAttribute("Reflective", new byte[0]); 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass mlevel = classPool.get("javassist.tools.reflect.Metalevel"); 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean addMeta = !clazz.subtypeOf(mlevel); 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (addMeta) 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addInterface(mlevel); 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal processMethods(clazz, addMeta); 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal processFields(clazz); 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtField f; 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (addMeta) { 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal f = new CtField(classPool.get("javassist.tools.reflect.Metaobject"), 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal metaobjectField, clazz); 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal f.setModifiers(Modifier.PROTECTED); 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addField(f, CtField.Initializer.byNewWithParams(metaobject)); 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(CtNewMethod.getter(metaobjectGetter, f)); 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(CtNewMethod.setter(metaobjectSetter, f)); 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal f = new CtField(classPool.get("javassist.tools.reflect.ClassMetaobject"), 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classobjectField, clazz); 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal f.setModifiers(Modifier.PRIVATE | Modifier.STATIC); 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addField(f, CtField.Initializer.byNew(metaclass, 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new String[] { clazz.getName() })); 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(CtNewMethod.getter(classobjectAccessor, f)); 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void processMethods(CtClass clazz, boolean dontSearch) 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod[] ms = clazz.getMethods(); 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < ms.length; ++i) { 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod m = ms[i]; 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int mod = m.getModifiers(); 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal processMethods0(mod, clazz, m, i, dontSearch); 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void processMethods0(int mod, CtClass clazz, 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod m, int identifier, boolean dontSearch) 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod body; 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = m.getName(); 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isExcluded(name)) // internally-used method inherited 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; // from a reflective class. 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod m2; 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (m.getDeclaringClass() == clazz) { 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isNative(mod)) 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m2 = m; 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isFinal(mod)) { 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mod &= ~Modifier.FINAL; 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m2.setModifiers(mod); 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isFinal(mod)) 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mod &= ~Modifier.NATIVE; 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m2 = CtNewMethod.delegator(findOriginal(m, dontSearch), clazz); 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m2.setModifiers(mod); 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(m2); 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m2.setName(ClassMetaobject.methodPrefix + identifier 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + "_" + name); 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Modifier.isStatic(mod)) 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body = trapStaticMethod; 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body = trapMethod; 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod wmethod 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = CtNewMethod.wrapped(m.getReturnType(), name, 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal m.getParameterTypes(), m.getExceptionTypes(), 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body, ConstParameter.integer(identifier), 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz); 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal wmethod.setModifiers(mod); 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(wmethod); 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private CtMethod findOriginal(CtMethod m, boolean dontSearch) 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NotFoundException 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (dontSearch) 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return m; 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = m.getName(); 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod[] ms = m.getDeclaringClass().getDeclaredMethods(); 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < ms.length; ++i) { 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String orgName = ms[i].getName(); 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (orgName.endsWith(name) 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && orgName.startsWith(ClassMetaobject.methodPrefix) 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && ms[i].getSignature().equals(m.getSignature())) 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return ms[i]; 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return m; 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void processFields(CtClass clazz) 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, NotFoundException 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtField[] fs = clazz.getDeclaredFields(); 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < fs.length; ++i) { 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtField f = fs[i]; 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int mod = f.getModifiers(); 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if ((mod & Modifier.PUBLIC) != 0 && (mod & Modifier.FINAL) == 0) { 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal mod |= Modifier.STATIC; 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = f.getName(); 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass ftype = f.getType(); 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod wmethod 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = CtNewMethod.wrapped(ftype, readPrefix + name, 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal readParam, null, trapRead, 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstParameter.string(name), 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz); 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal wmethod.setModifiers(mod); 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(wmethod); 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] writeParam = new CtClass[2]; 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeParam[0] = classPool.get("java.lang.Object"); 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeParam[1] = ftype; 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal wmethod = CtNewMethod.wrapped(CtClass.voidType, 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writePrefix + name, 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeParam, null, trapWrite, 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstParameter.string(name), clazz); 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal wmethod.setModifiers(mod); 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(wmethod); 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 385