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