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