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