All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.javassist.tools.reflect.ClassMetaobject Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.3.0
Show newest version
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package com.feilong.lib.javassist.tools.reflect;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * A runtime class metaobject.
 *
 * 

* A ClassMetaobject is created for every * class of reflective objects. It can be used to hold values * shared among the reflective objects of the same class. * *

* To obtain a class metaobject, calls _getClass() * on a reflective object. For example, * *

 * 
 * ClassMetaobject cm = ((Metalevel) reflectiveObject)._getClass();
 * 
* * @see com.feilong.lib.javassist.tools.reflect.Metalevel */ public class ClassMetaobject implements Serializable{ /** default serialVersionUID */ private static final long serialVersionUID = 1L; /** * The base-level methods controlled by a metaobject * are renamed so that they begin with * methodPrefix "_m_". */ static final String methodPrefix = "_m_"; static final int methodPrefixLen = 3; private Class javaClass; private Constructor[] constructors; private Method[] methods; /** * Specifies how a java.lang.Class object is loaded. * *

* If true, it is loaded by: * *

     * Thread.currentThread().getContextClassLoader().loadClass()
     * 
*

* If false, it is loaded by Class.forName(). * The default value is false. */ public static boolean useContextClassLoader = false; /** * Constructs a ClassMetaobject. * * @param params * params[0] is the name of the class * of the reflective objects. */ public ClassMetaobject(String[] params){ try{ javaClass = getClassObject(params[0]); }catch (ClassNotFoundException e){ throw new RuntimeException( "not found: " + params[0] + ", useContextClassLoader: " + Boolean.toString(useContextClassLoader), e); } constructors = javaClass.getConstructors(); methods = null; } private void writeObject(ObjectOutputStream out) throws IOException{ out.writeUTF(javaClass.getName()); } private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{ javaClass = getClassObject(in.readUTF()); constructors = javaClass.getConstructors(); methods = null; } private Class getClassObject(String name) throws ClassNotFoundException{ if (useContextClassLoader){ return Thread.currentThread().getContextClassLoader().loadClass(name); } return Class.forName(name); } /** * Obtains the java.lang.Class representing this class. */ public final Class getJavaClass(){ return javaClass; } /** * Obtains the name of this class. */ public final String getName(){ return javaClass.getName(); } /** * Returns true if obj is an instance of this class. */ public final boolean isInstance(Object obj){ return javaClass.isInstance(obj); } /** * Creates a new instance of the class. * * @param args * the arguments passed to the constructor. */ public final Object newInstance(Object[] args) throws CannotCreateException{ int n = constructors.length; for (int i = 0; i < n; ++i){ try{ return constructors[i].newInstance(args); }catch (IllegalArgumentException e){ // try again }catch (InstantiationException e){ throw new CannotCreateException(e); }catch (IllegalAccessException e){ throw new CannotCreateException(e); }catch (InvocationTargetException e){ throw new CannotCreateException(e); } } throw new CannotCreateException("no constructor matches"); } /** * Is invoked when static fields of the base-level * class are read and the runtime system intercepts it. * This method simply returns the value of the field. * *

* Every subclass of this class should redefine this method. */ public Object trapFieldRead(String name){ Class jc = getJavaClass(); try{ return jc.getField(name).get(null); }catch (NoSuchFieldException e){ throw new RuntimeException(e.toString()); }catch (IllegalAccessException e){ throw new RuntimeException(e.toString()); } } /** * Is invoked when static fields of the base-level * class are modified and the runtime system intercepts it. * This method simply sets the field to the given value. * *

* Every subclass of this class should redefine this method. */ public void trapFieldWrite(String name,Object value){ Class jc = getJavaClass(); try{ jc.getField(name).set(null, value); }catch (NoSuchFieldException e){ throw new RuntimeException(e.toString()); }catch (IllegalAccessException e){ throw new RuntimeException(e.toString()); } } /** * Invokes a method whose name begins with * methodPrefix "_m_" and the identifier. * * @exception CannotInvokeException * if the invocation fails. */ static public Object invoke(Object target,int identifier,Object[] args) throws Throwable{ Method[] allmethods = target.getClass().getMethods(); int n = allmethods.length; String head = methodPrefix + identifier; for (int i = 0; i < n; ++i){ if (allmethods[i].getName().startsWith(head)){ try{ return allmethods[i].invoke(target, args); }catch (java.lang.reflect.InvocationTargetException e){ throw e.getTargetException(); }catch (java.lang.IllegalAccessException e){ throw new CannotInvokeException(e); } } } throw new CannotInvokeException("cannot find a method"); } /** * Is invoked when static methods of the base-level * class are called and the runtime system intercepts it. * This method simply executes the intercepted method invocation * with the original parameters and returns the resulting value. * *

* Every subclass of this class should redefine this method. */ public Object trapMethodcall(int identifier,Object[] args) throws Throwable{ try{ Method[] m = getReflectiveMethods(); return m[identifier].invoke(null, args); }catch (java.lang.reflect.InvocationTargetException e){ throw e.getTargetException(); }catch (java.lang.IllegalAccessException e){ throw new CannotInvokeException(e); } } /** * Returns an array of the methods defined on the given reflective * object. This method is for the internal use only. */ public final Method[] getReflectiveMethods(){ if (methods != null){ return methods; } Class baseclass = getJavaClass(); Method[] allmethods = baseclass.getDeclaredMethods(); int n = allmethods.length; int[] index = new int[n]; int max = 0; for (int i = 0; i < n; ++i){ Method m = allmethods[i]; String mname = m.getName(); if (mname.startsWith(methodPrefix)){ int k = 0; for (int j = methodPrefixLen;; ++j){ char c = mname.charAt(j); if ('0' <= c && c <= '9'){ k = k * 10 + c - '0'; }else{ break; } } index[i] = ++k; if (k > max){ max = k; } } } methods = new Method[max]; for (int i = 0; i < n; ++i){ if (index[i] > 0){ methods[index[i] - 1] = allmethods[i]; } } return methods; } /** * Returns the java.lang.reflect.Method object representing * the method specified by identifier. * *

* Note that the actual method returned will be have an altered, * reflective name i.e. _m_2_... * * @param identifier * the identifier index * given to trapMethodcall() etc. * @see #trapMethodcall(int,Object[]) */ public final Method getMethod(int identifier){ return getReflectiveMethods()[identifier]; } /** * Returns the name of the method specified * by identifier. */ public final String getMethodName(int identifier){ String mname = getReflectiveMethods()[identifier].getName(); int j = ClassMetaobject.methodPrefixLen; for (;;){ char c = mname.charAt(j++); if (c < '0' || '9' < c){ break; } } return mname.substring(j); } /** * Returns an array of Class objects representing the * formal parameter types of the method specified * by identifier. */ public final Class[] getParameterTypes(int identifier){ return getReflectiveMethods()[identifier].getParameterTypes(); } /** * Returns a Class objects representing the * return type of the method specified by identifier. */ public final Class getReturnType(int identifier){ return getReflectiveMethods()[identifier].getReturnType(); } /** * Returns the identifier index of the method, as identified by its * original name. * *

* This method is useful, in conjuction with * {@link ClassMetaobject#getMethod(int)}, to obtain a quick reference * to the original method in the reflected class (i.e. not the proxy * method), using the original name of the method. * *

* Written by Brett Randall and Shigeru Chiba. * * @param originalName * The original name of the reflected method * @param argTypes * array of Class specifying the method signature * @return the identifier index of the original method * @throws NoSuchMethodException * if the method does not exist * * @see ClassMetaobject#getMethod(int) */ public final int getMethodIndex(String originalName,Class[] argTypes) throws NoSuchMethodException{ Method[] mthds = getReflectiveMethods(); for (int i = 0; i < mthds.length; i++){ if (mthds[i] == null){ continue; } // check name and parameter types match if (getMethodName(i).equals(originalName) && Arrays.equals(argTypes, mthds[i].getParameterTypes())){ return i; } } throw new NoSuchMethodException("Method " + originalName + " not found"); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy