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