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.

RuntimeSupport.java 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- 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. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.util.proxy;
  17. import java.lang.reflect.Method;
  18. import java.io.Serializable;
  19. /**
  20. * Runtime support routines that the classes generated by ProxyFactory use.
  21. *
  22. * @see ProxyFactory
  23. */
  24. public class RuntimeSupport {
  25. /**
  26. * A method handler that only executes a method.
  27. */
  28. public static MethodHandler default_interceptor = new DefaultMethodHandler();
  29. static class DefaultMethodHandler implements MethodHandler, Serializable {
  30. public Object invoke(Object self, Method m,
  31. Method proceed, Object[] args)
  32. throws Exception
  33. {
  34. return proceed.invoke(self, args);
  35. }
  36. };
  37. /**
  38. * Finds two methods specified by the parameters and stores them
  39. * into the given array.
  40. *
  41. * @throws RuntimeException if the methods are not found.
  42. * @see javassist.util.proxy.ProxyFactory
  43. */
  44. public static void find2Methods(Class clazz, String superMethod,
  45. String thisMethod, int index,
  46. String desc, java.lang.reflect.Method[] methods)
  47. {
  48. methods[index + 1] = thisMethod == null ? null
  49. : findMethod(clazz, thisMethod, desc);
  50. methods[index] = findSuperClassMethod(clazz, superMethod, desc);
  51. }
  52. /**
  53. * Finds two methods specified by the parameters and stores them
  54. * into the given array.
  55. *
  56. * <p>Added back for JBoss Seam. See JASSIST-206.</p>
  57. *
  58. * @throws RuntimeException if the methods are not found.
  59. * @see javassist.util.proxy.ProxyFactory
  60. * @deprecated replaced by {@link #find2Methods(Class, String, String, int, String, Method[])}
  61. */
  62. public static void find2Methods(Object self, String superMethod,
  63. String thisMethod, int index,
  64. String desc, java.lang.reflect.Method[] methods)
  65. {
  66. methods[index + 1] = thisMethod == null ? null
  67. : findMethod(self, thisMethod, desc);
  68. methods[index] = findSuperMethod(self, superMethod, desc);
  69. }
  70. /**
  71. * Finds a method with the given name and descriptor.
  72. * It searches only the class of self.
  73. *
  74. * <p>Added back for JBoss Seam. See JASSIST-206.</p>
  75. *
  76. * @throws RuntimeException if the method is not found.
  77. * @deprecated replaced by {@link #findMethod(Class, String, String)}
  78. */
  79. public static Method findMethod(Object self, String name, String desc) {
  80. Method m = findMethod2(self.getClass(), name, desc);
  81. if (m == null)
  82. error(self.getClass(), name, desc);
  83. return m;
  84. }
  85. /**
  86. * Finds a method with the given name and descriptor.
  87. * It searches only the class of self.
  88. *
  89. * @throws RuntimeException if the method is not found.
  90. */
  91. public static Method findMethod(Class clazz, String name, String desc) {
  92. Method m = findMethod2(clazz, name, desc);
  93. if (m == null)
  94. error(clazz, name, desc);
  95. return m;
  96. }
  97. /**
  98. * Finds a method that has the given name and descriptor and is declared
  99. * in the super class.
  100. *
  101. * @throws RuntimeException if the method is not found.
  102. */
  103. public static Method findSuperMethod(Object self, String name, String desc) {
  104. // for JBoss Seam. See JASSIST-183.
  105. Class clazz = self.getClass();
  106. return findSuperClassMethod(clazz, name, desc);
  107. }
  108. /**
  109. * Finds a method that has the given name and descriptor and is declared
  110. * in the super class.
  111. *
  112. * @throws RuntimeException if the method is not found.
  113. */
  114. public static Method findSuperClassMethod(Class clazz, String name, String desc) {
  115. Method m = findSuperMethod2(clazz.getSuperclass(), name, desc);
  116. if (m == null)
  117. m = searchInterfaces(clazz, name, desc);
  118. if (m == null)
  119. error(clazz, name, desc);
  120. return m;
  121. }
  122. private static void error(Class clazz, String name, String desc) {
  123. throw new RuntimeException("not found " + name + ":" + desc
  124. + " in " + clazz.getName());
  125. }
  126. private static Method findSuperMethod2(Class clazz, String name, String desc) {
  127. Method m = findMethod2(clazz, name, desc);
  128. if (m != null)
  129. return m;
  130. Class superClass = clazz.getSuperclass();
  131. if (superClass != null) {
  132. m = findSuperMethod2(superClass, name, desc);
  133. if (m != null)
  134. return m;
  135. }
  136. return searchInterfaces(clazz, name, desc);
  137. }
  138. private static Method searchInterfaces(Class clazz, String name, String desc) {
  139. Method m = null;
  140. Class[] interfaces = clazz.getInterfaces();
  141. for (int i = 0; i < interfaces.length; i++) {
  142. m = findSuperMethod2(interfaces[i], name, desc);
  143. if (m != null)
  144. return m;
  145. }
  146. return m;
  147. }
  148. private static Method findMethod2(Class clazz, String name, String desc) {
  149. Method[] methods = SecurityActions.getDeclaredMethods(clazz);
  150. int n = methods.length;
  151. for (int i = 0; i < n; i++)
  152. if (methods[i].getName().equals(name)
  153. && makeDescriptor(methods[i]).equals(desc))
  154. return methods[i];
  155. return null;
  156. }
  157. /**
  158. * Makes a descriptor for a given method.
  159. */
  160. public static String makeDescriptor(Method m) {
  161. Class[] params = m.getParameterTypes();
  162. return makeDescriptor(params, m.getReturnType());
  163. }
  164. /**
  165. * Makes a descriptor for a given method.
  166. *
  167. * @param params parameter types.
  168. * @param retType return type.
  169. */
  170. public static String makeDescriptor(Class[] params, Class retType) {
  171. StringBuffer sbuf = new StringBuffer();
  172. sbuf.append('(');
  173. for (int i = 0; i < params.length; i++)
  174. makeDesc(sbuf, params[i]);
  175. sbuf.append(')');
  176. if (retType != null)
  177. makeDesc(sbuf, retType);
  178. return sbuf.toString();
  179. }
  180. /**
  181. * Makes a descriptor for a given method.
  182. *
  183. * @param params the descriptor of parameter types.
  184. * @param retType return type.
  185. */
  186. public static String makeDescriptor(String params, Class retType) {
  187. StringBuffer sbuf = new StringBuffer(params);
  188. makeDesc(sbuf, retType);
  189. return sbuf.toString();
  190. }
  191. private static void makeDesc(StringBuffer sbuf, Class type) {
  192. if (type.isArray()) {
  193. sbuf.append('[');
  194. makeDesc(sbuf, type.getComponentType());
  195. }
  196. else if (type.isPrimitive()) {
  197. if (type == Void.TYPE)
  198. sbuf.append('V');
  199. else if (type == Integer.TYPE)
  200. sbuf.append('I');
  201. else if (type == Byte.TYPE)
  202. sbuf.append('B');
  203. else if (type == Long.TYPE)
  204. sbuf.append('J');
  205. else if (type == Double.TYPE)
  206. sbuf.append('D');
  207. else if (type == Float.TYPE)
  208. sbuf.append('F');
  209. else if (type == Character.TYPE)
  210. sbuf.append('C');
  211. else if (type == Short.TYPE)
  212. sbuf.append('S');
  213. else if (type == Boolean.TYPE)
  214. sbuf.append('Z');
  215. else
  216. throw new RuntimeException("bad type: " + type.getName());
  217. }
  218. else
  219. sbuf.append('L').append(type.getName().replace('.', '/'))
  220. .append(';');
  221. }
  222. /**
  223. * Converts a proxy object to an object that is writable to an
  224. * object stream. This method is called by <code>writeReplace()</code>
  225. * in a proxy class.
  226. *
  227. * @since 3.4
  228. */
  229. public static SerializedProxy makeSerializedProxy(Object proxy)
  230. throws java.io.InvalidClassException
  231. {
  232. Class clazz = proxy.getClass();
  233. MethodHandler methodHandler = null;
  234. if (proxy instanceof ProxyObject)
  235. methodHandler = ((ProxyObject)proxy).getHandler();
  236. else if (proxy instanceof Proxy)
  237. methodHandler = ProxyFactory.getHandler((Proxy)proxy);
  238. return new SerializedProxy(clazz, ProxyFactory.getFilterSignature(clazz), methodHandler);
  239. }
  240. }