You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Metaobject.java 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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. package javassist.tools.reflect;
  16. import java.lang.reflect.Method;
  17. import java.io.Serializable;
  18. import java.io.IOException;
  19. import java.io.ObjectInputStream;
  20. import java.io.ObjectOutputStream;
  21. /**
  22. * A runtime metaobject.
  23. *
  24. * <p>A <code>Metaobject</code> is created for
  25. * every object at the base level. A different reflective object is
  26. * associated with a different metaobject.
  27. *
  28. * <p>The metaobject intercepts method calls
  29. * on the reflective object at the base-level. To change the behavior
  30. * of the method calls, a subclass of <code>Metaobject</code>
  31. * should be defined.
  32. *
  33. * <p>To obtain a metaobject, calls <code>_getMetaobject()</code>
  34. * on a reflective object. For example,
  35. *
  36. * <ul><pre>Metaobject m = ((Metalevel)reflectiveObject)._getMetaobject();
  37. * </pre></ul>
  38. *
  39. * @see javassist.tools.reflect.ClassMetaobject
  40. * @see javassist.tools.reflect.Metalevel
  41. */
  42. public class Metaobject implements Serializable {
  43. protected ClassMetaobject classmetaobject;
  44. protected Metalevel baseobject;
  45. protected Method[] methods;
  46. /**
  47. * Constructs a <code>Metaobject</code>. The metaobject is
  48. * constructed before the constructor is called on the base-level
  49. * object.
  50. *
  51. * @param self the object that this metaobject is associated with.
  52. * @param args the parameters passed to the constructor of
  53. * <code>self</code>.
  54. */
  55. public Metaobject(Object self, Object[] args) {
  56. baseobject = (Metalevel)self;
  57. classmetaobject = baseobject._getClass();
  58. methods = classmetaobject.getReflectiveMethods();
  59. }
  60. /**
  61. * Constructs a <code>Metaobject</code> without initialization.
  62. * If calling this constructor, a subclass should be responsible
  63. * for initialization.
  64. */
  65. protected Metaobject() {
  66. baseobject = null;
  67. classmetaobject = null;
  68. methods = null;
  69. }
  70. private void writeObject(ObjectOutputStream out) throws IOException {
  71. out.writeObject(baseobject);
  72. }
  73. private void readObject(ObjectInputStream in)
  74. throws IOException, ClassNotFoundException
  75. {
  76. baseobject = (Metalevel)in.readObject();
  77. classmetaobject = baseobject._getClass();
  78. methods = classmetaobject.getReflectiveMethods();
  79. }
  80. /**
  81. * Obtains the class metaobject associated with this metaobject.
  82. *
  83. * @see javassist.tools.reflect.ClassMetaobject
  84. */
  85. public final ClassMetaobject getClassMetaobject() {
  86. return classmetaobject;
  87. }
  88. /**
  89. * Obtains the object controlled by this metaobject.
  90. */
  91. public final Object getObject() {
  92. return baseobject;
  93. }
  94. /**
  95. * Changes the object controlled by this metaobject.
  96. *
  97. * @param self the object
  98. */
  99. public final void setObject(Object self) {
  100. baseobject = (Metalevel)self;
  101. classmetaobject = baseobject._getClass();
  102. methods = classmetaobject.getReflectiveMethods();
  103. // call _setMetaobject() after the metaobject is settled.
  104. baseobject._setMetaobject(this);
  105. }
  106. /**
  107. * Returns the name of the method specified
  108. * by <code>identifier</code>.
  109. */
  110. public final String getMethodName(int identifier) {
  111. String mname = methods[identifier].getName();
  112. int j = ClassMetaobject.methodPrefixLen;
  113. for (;;) {
  114. char c = mname.charAt(j++);
  115. if (c < '0' || '9' < c)
  116. break;
  117. }
  118. return mname.substring(j);
  119. }
  120. /**
  121. * Returns an array of <code>Class</code> objects representing the
  122. * formal parameter types of the method specified
  123. * by <code>identifier</code>.
  124. */
  125. public final Class[] getParameterTypes(int identifier) {
  126. return methods[identifier].getParameterTypes();
  127. }
  128. /**
  129. * Returns a <code>Class</code> objects representing the
  130. * return type of the method specified by <code>identifier</code>.
  131. */
  132. public final Class getReturnType(int identifier) {
  133. return methods[identifier].getReturnType();
  134. }
  135. /**
  136. * Is invoked when public fields of the base-level
  137. * class are read and the runtime system intercepts it.
  138. * This method simply returns the value of the field.
  139. *
  140. * <p>Every subclass of this class should redefine this method.
  141. */
  142. public Object trapFieldRead(String name) {
  143. Class jc = getClassMetaobject().getJavaClass();
  144. try {
  145. return jc.getField(name).get(getObject());
  146. }
  147. catch (NoSuchFieldException e) {
  148. throw new RuntimeException(e.toString());
  149. }
  150. catch (IllegalAccessException e) {
  151. throw new RuntimeException(e.toString());
  152. }
  153. }
  154. /**
  155. * Is invoked when public fields of the base-level
  156. * class are modified and the runtime system intercepts it.
  157. * This method simply sets the field to the given value.
  158. *
  159. * <p>Every subclass of this class should redefine this method.
  160. */
  161. public void trapFieldWrite(String name, Object value) {
  162. Class jc = getClassMetaobject().getJavaClass();
  163. try {
  164. jc.getField(name).set(getObject(), value);
  165. }
  166. catch (NoSuchFieldException e) {
  167. throw new RuntimeException(e.toString());
  168. }
  169. catch (IllegalAccessException e) {
  170. throw new RuntimeException(e.toString());
  171. }
  172. }
  173. /**
  174. * Is invoked when base-level method invocation is intercepted.
  175. * This method simply executes the intercepted method invocation
  176. * with the original parameters and returns the resulting value.
  177. *
  178. * <p>Every subclass of this class should redefine this method.
  179. *
  180. * <p>Note: this method is not invoked if the base-level method
  181. * is invoked by a constructor in the super class. For example,
  182. *
  183. * <ul><pre>abstract class A {
  184. * abstract void initialize();
  185. * A() {
  186. * initialize(); // not intercepted
  187. * }
  188. * }
  189. *
  190. * class B extends A {
  191. * void initialize() { System.out.println("initialize()"); }
  192. * B() {
  193. * super();
  194. * initialize(); // intercepted
  195. * }
  196. * }</pre></ul>
  197. *
  198. * <p>if an instance of B is created,
  199. * the invocation of initialize() in B is intercepted only once.
  200. * The first invocation by the constructor in A is not intercepted.
  201. * This is because the link between a base-level object and a
  202. * metaobject is not created until the execution of a
  203. * constructor of the super class finishes.
  204. */
  205. public Object trapMethodcall(int identifier, Object[] args)
  206. throws Throwable
  207. {
  208. try {
  209. return methods[identifier].invoke(getObject(), args);
  210. }
  211. catch (java.lang.reflect.InvocationTargetException e) {
  212. throw e.getTargetException();
  213. }
  214. catch (java.lang.IllegalAccessException e) {
  215. throw new CannotInvokeException(e);
  216. }
  217. }
  218. }