Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import java.lang.annotation.Annotation;
     18 import java.lang.reflect.InvocationHandler;
     19 import java.lang.reflect.InvocationTargetException;
     20 import java.lang.reflect.Constructor;
     21 import java.lang.reflect.Field;
     22 import java.lang.reflect.Method;
     23 import java.lang.reflect.Proxy;
     24 import java.util.Arrays;
     25 import java.util.Comparator;
     26 
     27 /**
     28  * Do some basic tests.
     29  */
     30 public class BasicTest {
     31 
     32     public static void main(String[] args) {
     33         Mix proxyMe = new Mix();
     34         Object proxy = createProxy(proxyMe);
     35 
     36         if (!Proxy.isProxyClass(proxy.getClass()))
     37             System.err.println("not a proxy class?");
     38         if (Proxy.getInvocationHandler(proxy) == null)
     39             System.err.println("ERROR: Proxy.getInvocationHandler is null");
     40 
     41         /* take it for a spin; verifies instanceof constraint */
     42         Shapes shapes = (Shapes) proxy;
     43         shapes.circle(3);
     44         shapes.rectangle(10, 20);
     45         shapes.blob();
     46         Quads quads = (Quads) proxy;
     47         quads.rectangle(15, 25);
     48         quads.trapezoid(6, 81.18, 4);
     49         Colors colors = (Colors) proxy;
     50         colors.red(1.0f);
     51         colors.blue(777);
     52         colors.mauve("sorry");
     53         colors.blob();
     54         Trace trace = (Trace) proxy;
     55         trace.getTrace();
     56 
     57         try {
     58             shapes.upChuck();
     59             System.out.println("Didn't get expected exception");
     60         } catch (IndexOutOfBoundsException ioobe) {
     61             System.out.println("Got expected ioobe");
     62         }
     63         try {
     64             shapes.upCheck();
     65             System.out.println("Didn't get expected exception");
     66         } catch (InterruptedException ie) {
     67             System.out.println("Got expected ie");
     68         }
     69 
     70         /*
     71          * Exercise annotations on Proxy classes.  This is mostly to ensure
     72          * that annotation calls work correctly on generated classes.
     73          */
     74         System.out.println("");
     75         Method[] methods = proxy.getClass().getDeclaredMethods();
     76         Arrays.sort(methods, new Comparator<Method>() {
     77           public int compare(Method o1, Method o2) {
     78             int result = o1.getName().compareTo(o2.getName());
     79             if (result != 0) {
     80                 return result;
     81             }
     82             return o1.getReturnType().getName().compareTo(o2.getReturnType().getName());
     83           }
     84         });
     85         System.out.println("Proxy interfaces: " +
     86             Arrays.deepToString(proxy.getClass().getInterfaces()));
     87         System.out.println("Proxy methods: " +
     88             Main.replaceProxyClassNamesForOutput(Arrays.deepToString(methods)));
     89         Method meth = methods[methods.length -1];
     90         System.out.println("Decl annos: " + Arrays.deepToString(meth.getDeclaredAnnotations()));
     91         Annotation[][] paramAnnos = meth.getParameterAnnotations();
     92         System.out.println("Param annos (" + paramAnnos.length + ") : "
     93             + Arrays.deepToString(paramAnnos));
     94         System.out.println("Modifiers: " + meth.getModifiers());
     95     }
     96 
     97     static Object createProxy(Object proxyMe) {
     98         /* declare an object that will handle the method calls */
     99         InvocationHandler handler = new MyInvocationHandler(proxyMe);
    100 
    101         /* create the proxy class */
    102         Class<?> proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(),
    103                 Quads.class, Colors.class, Trace.class);
    104         Main.registerProxyClassName(proxyClass.getCanonicalName());
    105 
    106         /* create a proxy object, passing the handler object in */
    107         Object proxy = null;
    108         try {
    109             Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
    110             //System.out.println("Constructor is " + cons);
    111             proxy = cons.newInstance(handler);
    112         } catch (NoSuchMethodException nsme) {
    113             System.err.println("failed: " + nsme);
    114         } catch (InstantiationException ie) {
    115             System.err.println("failed: " + ie);
    116         } catch (IllegalAccessException ie) {
    117             System.err.println("failed: " + ie);
    118         } catch (InvocationTargetException ite) {
    119             System.err.println("failed: " + ite);
    120         }
    121 
    122         return proxy;
    123     }
    124 }
    125 
    126 /*
    127  * Some interfaces.
    128  */
    129 interface Shapes {
    130     public void circle(int r);
    131     public int rectangle(int x, int y);
    132 
    133     public String blob();
    134 
    135     public R0base checkMe();
    136     public void upChuck();
    137     public void upCheck() throws InterruptedException;
    138 }
    139 
    140 interface Quads extends Shapes {
    141     public int rectangle(int x, int y);
    142     public int square(int x, int y);
    143     public int trapezoid(int x, double off, int y);
    144 
    145     public R0a checkMe();
    146 }
    147 
    148 /*
    149  * More interfaces.
    150  */
    151 interface Colors {
    152     public int red(float howRed);
    153     public int green(double howGreen);
    154     public double blue(int howBlue);
    155     public int mauve(String apology);
    156 
    157     public String blob();
    158 
    159     public R0aa checkMe();
    160 }
    161 
    162 interface Trace {
    163     public void getTrace();
    164 }
    165 
    166 /*
    167  * Some return types.
    168  */
    169 class R0base { int mBlah;  }
    170 class R0a extends R0base { int mBlah_a;  }
    171 class R0aa extends R0a { int mBlah_aa;  }
    172 
    173 
    174 /*
    175  * A class that implements them all.
    176  */
    177 class Mix implements Quads, Colors {
    178     public void circle(int r) {
    179         System.out.println("--- circle " + r);
    180     }
    181     public int rectangle(int x, int y) {
    182         System.out.println("--- rectangle " + x + "," + y);
    183         return 4;
    184     }
    185     public int square(int x, int y) {
    186         System.out.println("--- square " + x + "," + y);
    187         return 4;
    188     }
    189     public int trapezoid(int x, double off, int y) {
    190         System.out.println("--- trap " + x + "," + y + "," + off);
    191         return 8;
    192     }
    193     public String blob() {
    194         System.out.println("--- blob");
    195         return "mix";
    196     }
    197 
    198     public int red(float howRed) {
    199         System.out.println("--- red " + howRed);
    200         return 0;
    201     }
    202     public int green(double howGreen) {
    203         System.out.println("--- green " + howGreen);
    204         return 1;
    205     }
    206     public double blue(int howBlue) {
    207         System.out.println("--- blue " + howBlue);
    208         return 2.54;
    209     }
    210     public int mauve(String apology) {
    211         System.out.println("--- mauve " + apology);
    212         return 3;
    213     }
    214 
    215     public R0aa checkMe() {
    216         return null;
    217     }
    218     public void upChuck() {
    219         throw new IndexOutOfBoundsException("upchuck");
    220     }
    221     public void upCheck() throws InterruptedException {
    222         throw new InterruptedException("upcheck");
    223     }
    224 }
    225 
    226 /*
    227  * Invocation handler, defining the implementation of the proxy functions.
    228  */
    229 class MyInvocationHandler implements InvocationHandler {
    230     Object mObj;
    231 
    232     public MyInvocationHandler(Object obj) {
    233         mObj = obj;
    234     }
    235 
    236     /*
    237      * This is called when anything gets invoked in the proxy object.
    238      */
    239     public Object invoke(Object proxy, Method method, Object[] args)
    240         throws Throwable {
    241 
    242         Object result = null;
    243 
    244         // Trap Object calls.  This is important here to avoid a recursive
    245         // invocation of toString() in the print statements below.
    246         if (method.getDeclaringClass() == java.lang.Object.class) {
    247             //System.out.println("!!! object " + method.getName());
    248             if (method.getName().equals("toString")) {
    249                 return super.toString();
    250             } else if (method.getName().equals("hashCode")) {
    251                 return Integer.valueOf(super.hashCode());
    252             } else if (method.getName().equals("equals")) {
    253                 return Boolean.valueOf(super.equals(args[0]));
    254             } else {
    255                 throw new RuntimeException("huh?");
    256             }
    257         }
    258 
    259         if (method.getDeclaringClass() == Trace.class) {
    260           if (method.getName().equals("getTrace")) {
    261             StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    262             for (int i = 0; i < stackTrace.length; i++) {
    263                 StackTraceElement ste = stackTrace[i];
    264                 if (ste.getMethodName().equals("getTrace")) {
    265                   String outputClassName = Main.replaceProxyClassNamesForOutput(ste.getClassName());
    266                   System.out.println(outputClassName + "." + ste.getMethodName() + " " +
    267                                      ste.getFileName() + ":" + ste.getLineNumber());
    268                 }
    269             }
    270             return null;
    271           }
    272         }
    273 
    274         if (method.getDeclaringClass() == Trace.class) {
    275           if (method.getName().equals("getTrace")) {
    276             StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    277             for (int i = 0; i < stackTrace.length; i++) {
    278                 StackTraceElement ste = stackTrace[i];
    279                 if (ste.getMethodName().equals("getTrace")) {
    280                   String outputClassName = Main.replaceProxyClassNamesForOutput(ste.getClassName());
    281                   System.out.println(outputClassName + "." + ste.getMethodName() + " " +
    282                                      ste.getFileName() + ":" + ste.getLineNumber());
    283                 }
    284             }
    285             return null;
    286           }
    287         }
    288 
    289         System.out.println("Invoke " + method);
    290         if (args == null || args.length == 0) {
    291             System.out.println(" (no args)");
    292         } else {
    293             for (int i = 0; i < args.length; i++)
    294                 System.out.println(" " + i + ": " + args[i]);
    295         }
    296 
    297         try {
    298             if (true) {
    299                 result = method.invoke(mObj, args);
    300             } else {
    301                 result = -1;
    302             }
    303             System.out.println("Success: method " + method.getName()
    304                 + " res=" + result);
    305         } catch (InvocationTargetException ite) {
    306             throw ite.getTargetException();
    307         } catch (IllegalAccessException iae) {
    308             throw new RuntimeException(iae);
    309         }
    310         return result;
    311     }
    312 }
    313