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