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: " + Arrays.deepToString(methods));
     88         Method meth = methods[methods.length -1];
     89         System.out.println("Decl annos: " + Arrays.deepToString(meth.getDeclaredAnnotations()));
     90         Annotation[][] paramAnnos = meth.getParameterAnnotations();
     91         System.out.println("Param annos (" + paramAnnos.length + ") : "
     92             + Arrays.deepToString(paramAnnos));
     93     }
     94 
     95     static Object createProxy(Object proxyMe) {
     96         /* declare an object that will handle the method calls */
     97         InvocationHandler handler = new MyInvocationHandler(proxyMe);
     98 
     99         /* create the proxy class */
    100         Class proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(),
    101                             new Class[] { Quads.class, Colors.class, Trace.class });
    102 
    103         /* create a proxy object, passing the handler object in */
    104         Object proxy = null;
    105         try {
    106             Constructor<Class> cons;
    107             cons = proxyClass.getConstructor(
    108                             new Class[] { InvocationHandler.class });
    109             //System.out.println("Constructor is " + cons);
    110             proxy = cons.newInstance(new Object[] { handler });
    111         } catch (NoSuchMethodException nsme) {
    112             System.err.println("failed: " + nsme);
    113         } catch (InstantiationException ie) {
    114             System.err.println("failed: " + ie);
    115         } catch (IllegalAccessException ie) {
    116             System.err.println("failed: " + ie);
    117         } catch (InvocationTargetException ite) {
    118             System.err.println("failed: " + ite);
    119         }
    120 
    121         return proxy;
    122     }
    123 }
    124 
    125 /*
    126  * Some interfaces.
    127  */
    128 interface Shapes {
    129     public void circle(int r);
    130     public int rectangle(int x, int y);
    131 
    132     public String blob();
    133 
    134     public R0base checkMe();
    135     public void upChuck();
    136     public void upCheck() throws InterruptedException;
    137 }
    138 
    139 interface Quads extends Shapes {
    140     public int rectangle(int x, int y);
    141     public int square(int x, int y);
    142     public int trapezoid(int x, double off, int y);
    143 
    144     public R0a checkMe();
    145 }
    146 
    147 /*
    148  * More interfaces.
    149  */
    150 interface Colors {
    151     public int red(float howRed);
    152     public int green(double howGreen);
    153     public double blue(int howBlue);
    154     public int mauve(String apology);
    155 
    156     public String blob();
    157 
    158     public R0aa checkMe();
    159 }
    160 
    161 interface Trace {
    162     public void getTrace();
    163 }
    164 
    165 /*
    166  * Some return types.
    167  */
    168 class R0base { int mBlah;  }
    169 class R0a extends R0base { int mBlah_a;  }
    170 class R0aa extends R0a { int mBlah_aa;  }
    171 
    172 
    173 /*
    174  * A class that implements them all.
    175  */
    176 class Mix implements Quads, Colors {
    177     public void circle(int r) {
    178         System.out.println("--- circle " + r);
    179     }
    180     public int rectangle(int x, int y) {
    181         System.out.println("--- rectangle " + x + "," + y);
    182         return 4;
    183     }
    184     public int square(int x, int y) {
    185         System.out.println("--- square " + x + "," + y);
    186         return 4;
    187     }
    188     public int trapezoid(int x, double off, int y) {
    189         System.out.println("--- trap " + x + "," + y + "," + off);
    190         return 8;
    191     }
    192     public String blob() {
    193         System.out.println("--- blob");
    194         return "mix";
    195     }
    196 
    197     public int red(float howRed) {
    198         System.out.println("--- red " + howRed);
    199         return 0;
    200     }
    201     public int green(double howGreen) {
    202         System.out.println("--- green " + howGreen);
    203         return 1;
    204     }
    205     public double blue(int howBlue) {
    206         System.out.println("--- blue " + howBlue);
    207         return 2.54;
    208     }
    209     public int mauve(String apology) {
    210         System.out.println("--- mauve " + apology);
    211         return 3;
    212     }
    213 
    214     public R0aa checkMe() {
    215         return null;
    216     }
    217     public void upChuck() {
    218         throw new IndexOutOfBoundsException("upchuck");
    219     }
    220     public void upCheck() throws InterruptedException {
    221         throw new InterruptedException("upcheck");
    222     }
    223 }
    224 
    225 /*
    226  * Invocation handler, defining the implementation of the proxy functions.
    227  */
    228 class MyInvocationHandler implements InvocationHandler {
    229     Object mObj;
    230 
    231     public MyInvocationHandler(Object obj) {
    232         mObj = obj;
    233     }
    234 
    235     /*
    236      * This is called when anything gets invoked in the proxy object.
    237      */
    238     public Object invoke(Object proxy, Method method, Object[] args)
    239         throws Throwable {
    240 
    241         Object result = null;
    242 
    243         // Trap Object calls.  This is important here to avoid a recursive
    244         // invocation of toString() in the print statements below.
    245         if (method.getDeclaringClass() == java.lang.Object.class) {
    246             //System.out.println("!!! object " + method.getName());
    247             if (method.getName().equals("toString"))
    248                 return super.toString();
    249             else if (method.getName().equals("hashCode"))
    250                 return Integer.valueOf(super.hashCode());
    251             else if (method.getName().equals("equals"))
    252                 return Boolean.valueOf(super.equals(args[0]));
    253             else
    254                 throw new RuntimeException("huh?");
    255         }
    256 
    257         if (method.getDeclaringClass() == Trace.class) {
    258           if (method.getName().equals("getTrace")) {
    259             StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    260             for (int i = 0; i < stackTrace.length; i++) {
    261                 StackTraceElement ste = stackTrace[i];
    262                 if (ste.getMethodName().equals("getTrace")) {
    263                   System.out.println(ste.getClassName() + "." + ste.getMethodName() + " " +
    264                                      ste.getFileName() + ":" + ste.getLineNumber());
    265                 }
    266             }
    267             return null;
    268           }
    269         }
    270 
    271         System.out.println("Invoke " + method);
    272         if (args == null || args.length == 0) {
    273             System.out.println(" (no args)");
    274         } else {
    275             for (int i = 0; i < args.length; i++)
    276                 System.out.println(" " + i + ": " + args[i]);
    277         }
    278 
    279         try {
    280             if (true)
    281                 result = method.invoke(mObj, args);
    282             else
    283                 result = -1;
    284             System.out.println("Success: method " + method.getName()
    285                 + " res=" + result);
    286         } catch (InvocationTargetException ite) {
    287             throw ite.getTargetException();
    288         } catch (IllegalAccessException iae) {
    289             throw new RuntimeException(iae);
    290         }
    291         return result;
    292     }
    293 }
    294