KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > reflect > Metaobject


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist.reflect;
17
18 import java.lang.reflect.Method JavaDoc;
19 import java.io.Serializable JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.ObjectOutputStream JavaDoc;
23
24 /**
25  * A runtime metaobject.
26  *
27  * <p>A <code>Metaobject</code> is created for
28  * every object at the base level. A different reflective object is
29  * associated with a different metaobject.
30  *
31  * <p>The metaobject intercepts method calls
32  * on the reflective object at the base-level. To change the behavior
33  * of the method calls, a subclass of <code>Metaobject</code>
34  * should be defined.
35  *
36  * <p>To obtain a metaobject, calls <code>_getMetaobject()</code>
37  * on a reflective object. For example,
38  *
39  * <ul><pre>Metaobject m = ((Metalevel)reflectiveObject)._getMetaobject();
40  * </pre></ul>
41  *
42  * @see javassist.reflect.ClassMetaobject
43  * @see javassist.reflect.Metalevel
44  */

45 public class Metaobject implements Serializable JavaDoc {
46     protected ClassMetaobject classmetaobject;
47     protected Metalevel baseobject;
48     protected Method JavaDoc[] methods;
49
50     /**
51      * Constructs a <code>Metaobject</code>. The metaobject is
52      * constructed before the constructor is called on the base-level
53      * object.
54      *
55      * @param self the object that this metaobject is associated with.
56      * @param args the parameters passed to the constructor of
57      * <code>self</code>.
58      */

59     public Metaobject(Object JavaDoc self, Object JavaDoc[] args) {
60         baseobject = (Metalevel)self;
61         classmetaobject = baseobject._getClass();
62         methods = classmetaobject.getReflectiveMethods();
63     }
64
65     /**
66      * Constructs a <code>Metaobject</code> without initialization.
67      * If calling this constructor, a subclass should be responsible
68      * for initialization.
69      */

70     protected Metaobject() {
71         baseobject = null;
72         classmetaobject = null;
73         methods = null;
74     }
75
76     private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
77         out.writeObject(baseobject);
78     }
79
80     private void readObject(ObjectInputStream JavaDoc in)
81         throws IOException JavaDoc, ClassNotFoundException JavaDoc
82     {
83         baseobject = (Metalevel)in.readObject();
84         classmetaobject = baseobject._getClass();
85         methods = classmetaobject.getReflectiveMethods();
86     }
87
88     /**
89      * Obtains the class metaobject associated with this metaobject.
90      *
91      * @see javassist.reflect.ClassMetaobject
92      */

93     public final ClassMetaobject getClassMetaobject() {
94         return classmetaobject;
95     }
96
97     /**
98      * Obtains the object controlled by this metaobject.
99      */

100     public final Object JavaDoc getObject() {
101         return baseobject;
102     }
103
104     /**
105      * Changes the object controlled by this metaobject.
106      *
107      * @param self the object
108      */

109     public final void setObject(Object JavaDoc self) {
110         baseobject = (Metalevel)self;
111         classmetaobject = baseobject._getClass();
112         methods = classmetaobject.getReflectiveMethods();
113
114         // call _setMetaobject() after the metaobject is settled.
115
baseobject._setMetaobject(this);
116     }
117
118     /**
119      * Returns the name of the method specified
120      * by <code>identifier</code>.
121      */

122     public final String JavaDoc getMethodName(int identifier) {
123         String JavaDoc mname = methods[identifier].getName();
124         int j = ClassMetaobject.methodPrefixLen;
125         for (;;) {
126             char c = mname.charAt(j++);
127             if (c < '0' || '9' < c)
128                 break;
129         }
130
131         return mname.substring(j);
132     }
133
134     /**
135      * Returns an array of <code>Class</code> objects representing the
136      * formal parameter types of the method specified
137      * by <code>identifier</code>.
138      */

139     public final Class JavaDoc[] getParameterTypes(int identifier) {
140         return methods[identifier].getParameterTypes();
141     }
142
143     /**
144      * Returns a <code>Class</code> objects representing the
145      * return type of the method specified by <code>identifier</code>.
146      */

147     public final Class JavaDoc getReturnType(int identifier) {
148         return methods[identifier].getReturnType();
149     }
150
151     /**
152      * Is invoked when public fields of the base-level
153      * class are read and the runtime system intercepts it.
154      * This method simply returns the value of the field.
155      *
156      * <p>Every subclass of this class should redefine this method.
157      */

158     public Object JavaDoc trapFieldRead(String JavaDoc name) {
159         Class JavaDoc jc = getClassMetaobject().getJavaClass();
160         try {
161             return jc.getField(name).get(getObject());
162         }
163         catch (NoSuchFieldException JavaDoc e) {
164             throw new RuntimeException JavaDoc(e.toString());
165         }
166         catch (IllegalAccessException JavaDoc e) {
167             throw new RuntimeException JavaDoc(e.toString());
168         }
169     }
170
171     /**
172      * Is invoked when public fields of the base-level
173      * class are modified and the runtime system intercepts it.
174      * This method simply sets the field to the given value.
175      *
176      * <p>Every subclass of this class should redefine this method.
177      */

178     public void trapFieldWrite(String JavaDoc name, Object JavaDoc value) {
179         Class JavaDoc jc = getClassMetaobject().getJavaClass();
180         try {
181             jc.getField(name).set(getObject(), value);
182         }
183         catch (NoSuchFieldException JavaDoc e) {
184             throw new RuntimeException JavaDoc(e.toString());
185         }
186         catch (IllegalAccessException JavaDoc e) {
187             throw new RuntimeException JavaDoc(e.toString());
188         }
189     }
190
191     /**
192      * Is invoked when base-level method invocation is intercepted.
193      * This method simply executes the intercepted method invocation
194      * with the original parameters and returns the resulting value.
195      *
196      * <p>Every subclass of this class should redefine this method.
197      *
198      * <p>Note: this method is not invoked if the base-level method
199      * is invoked by a constructor in the super class. For example,
200      *
201      * <ul><pre>abstract class A {
202      * abstract void initialize();
203      * A() {
204      * initialize(); // not intercepted
205      * }
206      * }
207      *
208      * class B extends A {
209      * void initialize() { System.out.println("initialize()"); }
210      * B() {
211      * super();
212      * initialize(); // intercepted
213      * }
214      * }</pre></ul>
215      *
216      * <p>if an instance of B is created,
217      * the invocation of initialize() in B is intercepted only once.
218      * The first invocation by the constructor in A is not intercepted.
219      * This is because the link between a base-level object and a
220      * metaobject is not created until the execution of a
221      * constructor of the super class finishes.
222      */

223     public Object JavaDoc trapMethodcall(int identifier, Object JavaDoc[] args)
224         throws Throwable JavaDoc
225     {
226         try {
227             return methods[identifier].invoke(getObject(), args);
228         }
229         catch (java.lang.reflect.InvocationTargetException JavaDoc e) {
230             throw e.getTargetException();
231         }
232         catch (java.lang.IllegalAccessException JavaDoc e) {
233             throw new CannotInvokeException(e);
234         }
235     }
236 }
237
Popular Tags