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