123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /*
- * 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 javassist.tools.reflect;
-
- import java.lang.reflect.Method;
- import java.io.Serializable;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
-
- /**
- * A runtime metaobject.
- *
- * <p>A <code>Metaobject</code> is created for
- * every object at the base level. A different reflective object is
- * associated with a different metaobject.
- *
- * <p>The metaobject intercepts method calls
- * on the reflective object at the base-level. To change the behavior
- * of the method calls, a subclass of <code>Metaobject</code>
- * should be defined.
- *
- * <p>To obtain a metaobject, calls <code>_getMetaobject()</code>
- * on a reflective object. For example,
- *
- * <pre>
- * Metaobject m = ((Metalevel)reflectiveObject)._getMetaobject();
- * </pre>
- *
- * @see javassist.tools.reflect.ClassMetaobject
- * @see javassist.tools.reflect.Metalevel
- */
- public class Metaobject implements Serializable {
- protected ClassMetaobject classmetaobject;
- protected Metalevel baseobject;
- protected Method[] methods;
-
- /**
- * Constructs a <code>Metaobject</code>. The metaobject is
- * constructed before the constructor is called on the base-level
- * object.
- *
- * @param self the object that this metaobject is associated with.
- * @param args the parameters passed to the constructor of
- * <code>self</code>.
- */
- public Metaobject(Object self, Object[] args) {
- baseobject = (Metalevel)self;
- classmetaobject = baseobject._getClass();
- methods = classmetaobject.getReflectiveMethods();
- }
-
- /**
- * Constructs a <code>Metaobject</code> without initialization.
- * If calling this constructor, a subclass should be responsible
- * for initialization.
- */
- protected Metaobject() {
- baseobject = null;
- classmetaobject = null;
- methods = null;
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException {
- out.writeObject(baseobject);
- }
-
- private void readObject(ObjectInputStream in)
- throws IOException, ClassNotFoundException
- {
- baseobject = (Metalevel)in.readObject();
- classmetaobject = baseobject._getClass();
- methods = classmetaobject.getReflectiveMethods();
- }
-
- /**
- * Obtains the class metaobject associated with this metaobject.
- *
- * @see javassist.tools.reflect.ClassMetaobject
- */
- public final ClassMetaobject getClassMetaobject() {
- return classmetaobject;
- }
-
- /**
- * Obtains the object controlled by this metaobject.
- */
- public final Object getObject() {
- return baseobject;
- }
-
- /**
- * Changes the object controlled by this metaobject.
- *
- * @param self the object
- */
- public final void setObject(Object self) {
- baseobject = (Metalevel)self;
- classmetaobject = baseobject._getClass();
- methods = classmetaobject.getReflectiveMethods();
-
- // call _setMetaobject() after the metaobject is settled.
- baseobject._setMetaobject(this);
- }
-
- /**
- * Returns the name of the method specified
- * by <code>identifier</code>.
- */
- public final String getMethodName(int identifier) {
- String mname = methods[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 <code>Class</code> objects representing the
- * formal parameter types of the method specified
- * by <code>identifier</code>.
- */
- public final Class[] getParameterTypes(int identifier) {
- return methods[identifier].getParameterTypes();
- }
-
- /**
- * Returns a <code>Class</code> objects representing the
- * return type of the method specified by <code>identifier</code>.
- */
- public final Class getReturnType(int identifier) {
- return methods[identifier].getReturnType();
- }
-
- /**
- * Is invoked when public fields of the base-level
- * class are read and the runtime system intercepts it.
- * This method simply returns the value of the field.
- *
- * <p>Every subclass of this class should redefine this method.
- */
- public Object trapFieldRead(String name) {
- Class jc = getClassMetaobject().getJavaClass();
- try {
- return jc.getField(name).get(getObject());
- }
- catch (NoSuchFieldException e) {
- throw new RuntimeException(e.toString());
- }
- catch (IllegalAccessException e) {
- throw new RuntimeException(e.toString());
- }
- }
-
- /**
- * Is invoked when public fields of the base-level
- * class are modified and the runtime system intercepts it.
- * This method simply sets the field to the given value.
- *
- * <p>Every subclass of this class should redefine this method.
- */
- public void trapFieldWrite(String name, Object value) {
- Class jc = getClassMetaobject().getJavaClass();
- try {
- jc.getField(name).set(getObject(), value);
- }
- catch (NoSuchFieldException e) {
- throw new RuntimeException(e.toString());
- }
- catch (IllegalAccessException e) {
- throw new RuntimeException(e.toString());
- }
- }
-
- /**
- * Is invoked when base-level method invocation is intercepted.
- * This method simply executes the intercepted method invocation
- * with the original parameters and returns the resulting value.
- *
- * <p>Every subclass of this class should redefine this method.
- *
- * <p>Note: this method is not invoked if the base-level method
- * is invoked by a constructor in the super class. For example,
- *
- * <pre>
- * abstract class A {
- * abstract void initialize();
- * A() {
- * initialize(); // not intercepted
- * }
- * }
- *
- * class B extends A {
- * void initialize() { System.out.println("initialize()"); }
- * B() {
- * super();
- * initialize(); // intercepted
- * }
- * }</pre>
- *
- * <p>if an instance of B is created,
- * the invocation of initialize() in B is intercepted only once.
- * The first invocation by the constructor in A is not intercepted.
- * This is because the link between a base-level object and a
- * metaobject is not created until the execution of a
- * constructor of the super class finishes.
- */
- public Object trapMethodcall(int identifier, Object[] args)
- throws Throwable
- {
- try {
- return methods[identifier].invoke(getObject(), args);
- }
- catch (java.lang.reflect.InvocationTargetException e) {
- throw e.getTargetException();
- }
- catch (java.lang.IllegalAccessException e) {
- throw new CannotInvokeException(e);
- }
- }
- }
|