Home | History | Annotate | Download | only in proxy
      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 {
     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      */
     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      */
     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      */
     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 
     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 
     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 
    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 
    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      */
    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      */
    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 
    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      */
    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