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