blob: 7f301f667bd98a4d1ff0205207e4b100f42bd51b [file] [log] [blame]
jeffhao5d1ac922011-09-29 17:41:15 -07001/*
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;
Ian Rogers466bb252011-10-14 03:29:56 -070025import java.util.Comparator;
jeffhao5d1ac922011-09-29 17:41:15 -070026
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()))
Kevin Brodskyf6c66c32015-12-17 14:13:00 +000037 System.out.println("not a proxy class?");
jeffhao5d1ac922011-09-29 17:41:15 -070038 if (Proxy.getInvocationHandler(proxy) == null)
Kevin Brodskyf6c66c32015-12-17 14:13:00 +000039 System.out.println("ERROR: Proxy.getInvocationHandler is null");
jeffhao5d1ac922011-09-29 17:41:15 -070040
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();
Jeff Hao228d6b82013-12-03 15:00:05 -080054 Trace trace = (Trace) proxy;
55 trace.getTrace();
jeffhao5d1ac922011-09-29 17:41:15 -070056
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();
Ian Rogers466bb252011-10-14 03:29:56 -070076 Arrays.sort(methods, new Comparator<Method>() {
77 public int compare(Method o1, Method o2) {
Jesse Wilsonecbce8f2011-10-21 19:57:36 -040078 int result = o1.getName().compareTo(o2.getName());
79 if (result != 0) {
80 return result;
81 }
82 return o1.getReturnType().getName().compareTo(o2.getReturnType().getName());
Ian Rogers466bb252011-10-14 03:29:56 -070083 }
84 });
Elliott Hughes2ed52c42012-03-21 16:56:56 -070085 System.out.println("Proxy interfaces: " +
86 Arrays.deepToString(proxy.getClass().getInterfaces()));
Hiroshi Yamauchi75d50532015-12-04 16:18:49 -080087 System.out.println("Proxy methods: " +
88 Main.replaceProxyClassNamesForOutput(Arrays.deepToString(methods)));
jeffhao5d1ac922011-09-29 17:41:15 -070089 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));
Brian Carlstrom4460ea62014-03-12 08:42:34 -070094 System.out.println("Modifiers: " + meth.getModifiers());
jeffhao5d1ac922011-09-29 17:41:15 -070095 }
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 */
Andreas Gampe166aaee2016-07-18 08:27:23 -0700102 Class<?> proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(),
103 Quads.class, Colors.class, Trace.class);
Hiroshi Yamauchi75d50532015-12-04 16:18:49 -0800104 Main.registerProxyClassName(proxyClass.getCanonicalName());
jeffhao5d1ac922011-09-29 17:41:15 -0700105
106 /* create a proxy object, passing the handler object in */
107 Object proxy = null;
108 try {
Andreas Gampe166aaee2016-07-18 08:27:23 -0700109 Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
jeffhao5d1ac922011-09-29 17:41:15 -0700110 //System.out.println("Constructor is " + cons);
Andreas Gampe166aaee2016-07-18 08:27:23 -0700111 proxy = cons.newInstance(handler);
jeffhao5d1ac922011-09-29 17:41:15 -0700112 } catch (NoSuchMethodException nsme) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000113 System.out.println("failed: " + nsme);
jeffhao5d1ac922011-09-29 17:41:15 -0700114 } catch (InstantiationException ie) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000115 System.out.println("failed: " + ie);
jeffhao5d1ac922011-09-29 17:41:15 -0700116 } catch (IllegalAccessException ie) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000117 System.out.println("failed: " + ie);
jeffhao5d1ac922011-09-29 17:41:15 -0700118 } catch (InvocationTargetException ite) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000119 System.out.println("failed: " + ite);
jeffhao5d1ac922011-09-29 17:41:15 -0700120 }
121
122 return proxy;
123 }
124}
125
126/*
127 * Some interfaces.
128 */
129interface Shapes {
130 public void circle(int r);
131 public int rectangle(int x, int y);
132
133 public String blob();
134
135 public R0base checkMe();
136 public void upChuck();
137 public void upCheck() throws InterruptedException;
138}
139
140interface Quads extends Shapes {
141 public int rectangle(int x, int y);
142 public int square(int x, int y);
143 public int trapezoid(int x, double off, int y);
144
145 public R0a checkMe();
146}
147
148/*
149 * More interfaces.
150 */
151interface Colors {
152 public int red(float howRed);
153 public int green(double howGreen);
154 public double blue(int howBlue);
155 public int mauve(String apology);
156
157 public String blob();
158
159 public R0aa checkMe();
160}
161
Jeff Hao228d6b82013-12-03 15:00:05 -0800162interface Trace {
163 public void getTrace();
164}
165
jeffhao5d1ac922011-09-29 17:41:15 -0700166/*
167 * Some return types.
168 */
169class R0base { int mBlah; }
170class R0a extends R0base { int mBlah_a; }
171class R0aa extends R0a { int mBlah_aa; }
172
173
174/*
175 * A class that implements them all.
176 */
177class Mix implements Quads, Colors {
178 public void circle(int r) {
179 System.out.println("--- circle " + r);
180 }
181 public int rectangle(int x, int y) {
182 System.out.println("--- rectangle " + x + "," + y);
183 return 4;
184 }
185 public int square(int x, int y) {
186 System.out.println("--- square " + x + "," + y);
187 return 4;
188 }
189 public int trapezoid(int x, double off, int y) {
190 System.out.println("--- trap " + x + "," + y + "," + off);
191 return 8;
192 }
193 public String blob() {
194 System.out.println("--- blob");
195 return "mix";
196 }
197
198 public int red(float howRed) {
199 System.out.println("--- red " + howRed);
200 return 0;
201 }
202 public int green(double howGreen) {
203 System.out.println("--- green " + howGreen);
204 return 1;
205 }
206 public double blue(int howBlue) {
207 System.out.println("--- blue " + howBlue);
208 return 2.54;
209 }
210 public int mauve(String apology) {
211 System.out.println("--- mauve " + apology);
212 return 3;
213 }
214
215 public R0aa checkMe() {
216 return null;
217 }
218 public void upChuck() {
219 throw new IndexOutOfBoundsException("upchuck");
220 }
221 public void upCheck() throws InterruptedException {
222 throw new InterruptedException("upcheck");
223 }
224}
225
226/*
227 * Invocation handler, defining the implementation of the proxy functions.
228 */
229class MyInvocationHandler implements InvocationHandler {
230 Object mObj;
231
232 public MyInvocationHandler(Object obj) {
233 mObj = obj;
234 }
235
236 /*
237 * This is called when anything gets invoked in the proxy object.
238 */
239 public Object invoke(Object proxy, Method method, Object[] args)
240 throws Throwable {
241
242 Object result = null;
243
244 // Trap Object calls. This is important here to avoid a recursive
245 // invocation of toString() in the print statements below.
246 if (method.getDeclaringClass() == java.lang.Object.class) {
247 //System.out.println("!!! object " + method.getName());
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700248 if (method.getName().equals("toString")) {
jeffhao5d1ac922011-09-29 17:41:15 -0700249 return super.toString();
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700250 } else if (method.getName().equals("hashCode")) {
jeffhao5d1ac922011-09-29 17:41:15 -0700251 return Integer.valueOf(super.hashCode());
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700252 } else if (method.getName().equals("equals")) {
jeffhao5d1ac922011-09-29 17:41:15 -0700253 return Boolean.valueOf(super.equals(args[0]));
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700254 } else {
jeffhao5d1ac922011-09-29 17:41:15 -0700255 throw new RuntimeException("huh?");
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700256 }
jeffhao5d1ac922011-09-29 17:41:15 -0700257 }
258
Jeff Hao228d6b82013-12-03 15:00:05 -0800259 if (method.getDeclaringClass() == Trace.class) {
260 if (method.getName().equals("getTrace")) {
261 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
262 for (int i = 0; i < stackTrace.length; i++) {
263 StackTraceElement ste = stackTrace[i];
264 if (ste.getMethodName().equals("getTrace")) {
Hiroshi Yamauchi75d50532015-12-04 16:18:49 -0800265 String outputClassName = Main.replaceProxyClassNamesForOutput(ste.getClassName());
266 System.out.println(outputClassName + "." + ste.getMethodName() + " " +
Jeff Hao228d6b82013-12-03 15:00:05 -0800267 ste.getFileName() + ":" + ste.getLineNumber());
268 }
269 }
270 return null;
271 }
272 }
273
Jeff Hao3addc292013-12-03 15:00:05 -0800274 if (method.getDeclaringClass() == Trace.class) {
275 if (method.getName().equals("getTrace")) {
276 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
277 for (int i = 0; i < stackTrace.length; i++) {
278 StackTraceElement ste = stackTrace[i];
279 if (ste.getMethodName().equals("getTrace")) {
Hiroshi Yamauchi75d50532015-12-04 16:18:49 -0800280 String outputClassName = Main.replaceProxyClassNamesForOutput(ste.getClassName());
281 System.out.println(outputClassName + "." + ste.getMethodName() + " " +
Jeff Hao3addc292013-12-03 15:00:05 -0800282 ste.getFileName() + ":" + ste.getLineNumber());
283 }
284 }
285 return null;
286 }
287 }
288
jeffhao5d1ac922011-09-29 17:41:15 -0700289 System.out.println("Invoke " + method);
290 if (args == null || args.length == 0) {
291 System.out.println(" (no args)");
292 } else {
293 for (int i = 0; i < args.length; i++)
294 System.out.println(" " + i + ": " + args[i]);
295 }
296
297 try {
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700298 if (true) {
jeffhao5d1ac922011-09-29 17:41:15 -0700299 result = method.invoke(mObj, args);
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700300 } else {
jeffhao5d1ac922011-09-29 17:41:15 -0700301 result = -1;
Brian Carlstrom4460ea62014-03-12 08:42:34 -0700302 }
jeffhao5d1ac922011-09-29 17:41:15 -0700303 System.out.println("Success: method " + method.getName()
304 + " res=" + result);
305 } catch (InvocationTargetException ite) {
306 throw ite.getTargetException();
307 } catch (IllegalAccessException iae) {
308 throw new RuntimeException(iae);
309 }
310 return result;
311 }
312}