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