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;
25
26/**
27 * Do some basic tests.
28 */
29public 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 */
116interface 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
127interface 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 */
138interface 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 */
152class R0base { int mBlah;  }
153class R0a extends R0base { int mBlah_a;  }
154class R0aa extends R0a { int mBlah_aa;  }
155
156
157/*
158 * A class that implements them all.
159 */
160class 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 */
212class 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