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 java.lang.reflect.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Arrays; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.Serializable; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ObjectInputStream; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ObjectOutputStream; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A runtime class metaobject. 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>A <code>ClassMetaobject</code> is created for every 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class of reflective objects. It can be used to hold values 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * shared among the reflective objects of the same class. 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>To obtain a class metaobject, calls <code>_getClass()</code> 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * on a reflective object. For example, 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>ClassMetaobject cm = ((Metalevel)reflectiveObject)._getClass(); 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metaobject 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metalevel 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ClassMetaobject implements Serializable { 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The base-level methods controlled by a metaobject 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * are renamed so that they begin with 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>methodPrefix "_m_"</code>. 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String methodPrefix = "_m_"; 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final int methodPrefixLen = 3; 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Class javaClass; 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Constructor[] constructors; 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Method[] methods; 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Specifies how a <code>java.lang.Class</code> object is loaded. 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If true, it is loaded by: 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>Thread.currentThread().getContextClassLoader().loadClass()</pre></ul> 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If false, it is loaded by <code>Class.forName()</code>. 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The default value is false. 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static boolean useContextClassLoader = false; 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a <code>ClassMetaobject</code>. 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param params <code>params[0]</code> is the name of the class 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * of the reflective objects. 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ClassMetaobject(String[] params) 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal javaClass = getClassObject(params[0]); 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (ClassNotFoundException e) { 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("not found: " + params[0] 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + ", useContextClassLoader: " 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + Boolean.toString(useContextClassLoader), e); 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal constructors = javaClass.getConstructors(); 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal methods = null; 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void writeObject(ObjectOutputStream out) throws IOException { 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeUTF(javaClass.getName()); 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void readObject(ObjectInputStream in) 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, ClassNotFoundException 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal javaClass = getClassObject(in.readUTF()); 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal constructors = javaClass.getConstructors(); 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal methods = null; 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Class getClassObject(String name) throws ClassNotFoundException { 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (useContextClassLoader) 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Thread.currentThread().getContextClassLoader() 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal .loadClass(name); 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Class.forName(name); 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Obtains the <code>java.lang.Class</code> representing this class. 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final Class getJavaClass() { 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return javaClass; 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Obtains the name of this class. 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final String getName() { 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return javaClass.getName(); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if <code>obj</code> is an instance of this class. 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final boolean isInstance(Object obj) { 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return javaClass.isInstance(obj); 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Creates a new instance of the class. 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param args the arguments passed to the constructor. 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final Object newInstance(Object[] args) 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCreateException 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = constructors.length; 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return constructors[i].newInstance(args); 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IllegalArgumentException e) { 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // try again 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (InstantiationException e) { 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCreateException(e); 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IllegalAccessException e) { 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCreateException(e); 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (InvocationTargetException e) { 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCreateException(e); 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCreateException("no constructor matches"); 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Is invoked when <code>static</code> fields of the base-level 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class are read and the runtime system intercepts it. 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method simply returns the value of the field. 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Every subclass of this class should redefine this method. 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object trapFieldRead(String name) { 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class jc = getJavaClass(); 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return jc.getField(name).get(null); 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NoSuchFieldException e) { 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException(e.toString()); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IllegalAccessException e) { 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException(e.toString()); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Is invoked when <code>static</code> fields of the base-level 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class are modified and the runtime system intercepts it. 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method simply sets the field to the given value. 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Every subclass of this class should redefine this method. 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void trapFieldWrite(String name, Object value) { 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class jc = getJavaClass(); 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal jc.getField(name).set(null, value); 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NoSuchFieldException e) { 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException(e.toString()); 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IllegalAccessException e) { 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException(e.toString()); 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invokes a method whose name begins with 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>methodPrefix "_m_"</code> and the identifier. 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @exception CannotInvokeException if the invocation fails. 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static public Object invoke(Object target, int identifier, Object[] args) 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws Throwable 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method[] allmethods = target.getClass().getMethods(); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = allmethods.length; 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String head = methodPrefix + identifier; 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (allmethods[i].getName().startsWith(head)) { 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return allmethods[i].invoke(target, args); 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } catch (java.lang.reflect.InvocationTargetException e) { 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e.getTargetException(); 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } catch (java.lang.IllegalAccessException e) { 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotInvokeException(e); 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotInvokeException("cannot find a method"); 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Is invoked when <code>static</code> methods of the base-level 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class are called and the runtime system intercepts it. 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method simply executes the intercepted method invocation 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * with the original parameters and returns the resulting value. 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Every subclass of this class should redefine this method. 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object trapMethodcall(int identifier, Object[] args) 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws Throwable 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method[] m = getReflectiveMethods(); 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return m[identifier].invoke(null, args); 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (java.lang.reflect.InvocationTargetException e) { 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e.getTargetException(); 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (java.lang.IllegalAccessException e) { 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotInvokeException(e); 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns an array of the methods defined on the given reflective 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * object. This method is for the internal use only. 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final Method[] getReflectiveMethods() { 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (methods != null) 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return methods; 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class baseclass = getJavaClass(); 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method[] allmethods = baseclass.getDeclaredMethods(); 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = allmethods.length; 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] index = new int[n]; 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int max = 0; 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method m = allmethods[i]; 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String mname = m.getName(); 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mname.startsWith(methodPrefix)) { 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int k = 0; 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int j = methodPrefixLen;; ++j) { 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = mname.charAt(j); 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if ('0' <= c && c <= '9') 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal k = k * 10 + c - '0'; 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index[i] = ++k; 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (k > max) 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal max = k; 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal methods = new Method[max]; 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (index[i] > 0) 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal methods[index[i] - 1] = allmethods[i]; 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return methods; 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the <code>java.lang.reflect.Method</code> object representing 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the method specified by <code>identifier</code>. 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Note that the actual method returned will be have an altered, 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * reflective name i.e. <code>_m_2_..</code>. 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param identifier the identifier index 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * given to <code>trapMethodcall()</code> etc. 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see Metaobject#trapMethodcall(int,Object[]) 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see #trapMethodcall(int,Object[]) 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final Method getMethod(int identifier) { 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getReflectiveMethods()[identifier]; 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the name of the method specified 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by <code>identifier</code>. 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final String getMethodName(int identifier) { 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String mname = getReflectiveMethods()[identifier].getName(); 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int j = ClassMetaobject.methodPrefixLen; 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = mname.charAt(j++); 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c < '0' || '9' < c) 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return mname.substring(j); 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns an array of <code>Class</code> objects representing the 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * formal parameter types of the method specified 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by <code>identifier</code>. 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final Class[] getParameterTypes(int identifier) { 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getReflectiveMethods()[identifier].getParameterTypes(); 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns a <code>Class</code> objects representing the 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * return type of the method specified by <code>identifier</code>. 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final Class getReturnType(int identifier) { 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getReflectiveMethods()[identifier].getReturnType(); 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the identifier index of the method, as identified by its 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * original name. 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This method is useful, in conjuction with 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <link>ClassMetaobject#getMethod()</link>, to obtain a quick reference 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * to the original method in the reflected class (i.e. not the proxy 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * method), using the original name of the method. 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Written by Brett Randall and Shigeru Chiba. 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param originalName The original name of the reflected method 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param argTypes array of Class specifying the method signature 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the identifier index of the original method 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @throws NoSuchMethodException if the method does not exist 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see ClassMetaobject#getMethod(int) 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final int getMethodIndex(String originalName, Class[] argTypes) 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NoSuchMethodException 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method[] mthds = getReflectiveMethods(); 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < mthds.length; i++) { 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mthds[i] == null) 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal continue; 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // check name and parameter types match 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (getMethodName(i).equals(originalName) 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && Arrays.equals(argTypes, mthds[i].getParameterTypes())) 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return i; 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new NoSuchMethodException("Method " + originalName 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + " not found"); 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 370