BasicTest.java revision 228d6b8a4f0a21c1e9b2372c3104ce4ee19f65b4
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
17import java.lang.annotation.Annotation;
18import java.lang.reflect.InvocationHandler;
19import java.lang.reflect.InvocationTargetException;
20import java.lang.reflect.Constructor;
21import java.lang.reflect.Field;
22import java.lang.reflect.Method;
23import java.lang.reflect.Proxy;
24import java.util.Arrays;
25import java.util.Comparator;
26
27/**
28 * Do some basic tests.
29 */
30public 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 */
128interface 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
139interface 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 */
150interface 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
161interface Trace {
162    public void getTrace();
163}
164
165/*
166 * Some return types.
167 */
168class R0base { int mBlah;  }
169class R0a extends R0base { int mBlah_a;  }
170class R0aa extends R0a { int mBlah_aa;  }
171
172
173/*
174 * A class that implements them all.
175 */
176class 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 */
228class 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