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 55 try { 56 shapes.upChuck(); 57 System.out.println("Didn't get expected exception"); 58 } catch (IndexOutOfBoundsException ioobe) { 59 System.out.println("Got expected ioobe"); 60 } 61 try { 62 shapes.upCheck(); 63 System.out.println("Didn't get expected exception"); 64 } catch (InterruptedException ie) { 65 System.out.println("Got expected ie"); 66 } 67 68 /* 69 * Exercise annotations on Proxy classes. This is mostly to ensure 70 * that annotation calls work correctly on generated classes. 71 */ 72 System.out.println(""); 73 Method[] methods = proxy.getClass().getDeclaredMethods(); 74 Arrays.sort(methods, new Comparator<Method>() { 75 public int compare(Method o1, Method o2) { 76 int result = o1.getName().compareTo(o2.getName()); 77 if (result != 0) { 78 return result; 79 } 80 return o1.getReturnType().getName().compareTo(o2.getReturnType().getName()); 81 } 82 }); 83 System.out.println("Proxy interfaces: " + 84 Arrays.deepToString(proxy.getClass().getInterfaces())); 85 System.out.println("Proxy methods: " + Arrays.deepToString(methods)); 86 Method meth = methods[methods.length -1]; 87 System.out.println("Decl annos: " + Arrays.deepToString(meth.getDeclaredAnnotations())); 88 Annotation[][] paramAnnos = meth.getParameterAnnotations(); 89 System.out.println("Param annos (" + paramAnnos.length + ") : " 90 + Arrays.deepToString(paramAnnos)); 91 } 92 93 static Object createProxy(Object proxyMe) { 94 /* declare an object that will handle the method calls */ 95 InvocationHandler handler = new MyInvocationHandler(proxyMe); 96 97 /* create the proxy class */ 98 Class proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(), 99 new Class[] { Quads.class, Colors.class }); 100 101 /* create a proxy object, passing the handler object in */ 102 Object proxy = null; 103 try { 104 Constructor<Class> cons; 105 cons = proxyClass.getConstructor( 106 new Class[] { InvocationHandler.class }); 107 //System.out.println("Constructor is " + cons); 108 proxy = cons.newInstance(new Object[] { handler }); 109 } catch (NoSuchMethodException nsme) { 110 System.err.println("failed: " + nsme); 111 } catch (InstantiationException ie) { 112 System.err.println("failed: " + ie); 113 } catch (IllegalAccessException ie) { 114 System.err.println("failed: " + ie); 115 } catch (InvocationTargetException ite) { 116 System.err.println("failed: " + ite); 117 } 118 119 return proxy; 120 } 121 } 122 123 /* 124 * Some interfaces. 125 */ 126 interface Shapes { 127 public void circle(int r); 128 public int rectangle(int x, int y); 129 130 public String blob(); 131 132 public R0base checkMe(); 133 public void upChuck(); 134 public void upCheck() throws InterruptedException; 135 } 136 137 interface Quads extends Shapes { 138 public int rectangle(int x, int y); 139 public int square(int x, int y); 140 public int trapezoid(int x, double off, int y); 141 142 public R0a checkMe(); 143 } 144 145 /* 146 * More interfaces. 147 */ 148 interface Colors { 149 public int red(float howRed); 150 public int green(double howGreen); 151 public double blue(int howBlue); 152 public int mauve(String apology); 153 154 public String blob(); 155 156 public R0aa checkMe(); 157 } 158 159 /* 160 * Some return types. 161 */ 162 class R0base { int mBlah; } 163 class R0a extends R0base { int mBlah_a; } 164 class R0aa extends R0a { int mBlah_aa; } 165 166 167 /* 168 * A class that implements them all. 169 */ 170 class Mix implements Quads, Colors { 171 public void circle(int r) { 172 System.out.println("--- circle " + r); 173 } 174 public int rectangle(int x, int y) { 175 System.out.println("--- rectangle " + x + "," + y); 176 return 4; 177 } 178 public int square(int x, int y) { 179 System.out.println("--- square " + x + "," + y); 180 return 4; 181 } 182 public int trapezoid(int x, double off, int y) { 183 System.out.println("--- trap " + x + "," + y + "," + off); 184 return 8; 185 } 186 public String blob() { 187 System.out.println("--- blob"); 188 return "mix"; 189 } 190 191 public int red(float howRed) { 192 System.out.println("--- red " + howRed); 193 return 0; 194 } 195 public int green(double howGreen) { 196 System.out.println("--- green " + howGreen); 197 return 1; 198 } 199 public double blue(int howBlue) { 200 System.out.println("--- blue " + howBlue); 201 return 2.54; 202 } 203 public int mauve(String apology) { 204 System.out.println("--- mauve " + apology); 205 return 3; 206 } 207 208 public R0aa checkMe() { 209 return null; 210 } 211 public void upChuck() { 212 throw new IndexOutOfBoundsException("upchuck"); 213 } 214 public void upCheck() throws InterruptedException { 215 throw new InterruptedException("upcheck"); 216 } 217 } 218 219 /* 220 * Invocation handler, defining the implementation of the proxy functions. 221 */ 222 class MyInvocationHandler implements InvocationHandler { 223 Object mObj; 224 225 public MyInvocationHandler(Object obj) { 226 mObj = obj; 227 } 228 229 /* 230 * This is called when anything gets invoked in the proxy object. 231 */ 232 public Object invoke(Object proxy, Method method, Object[] args) 233 throws Throwable { 234 235 Object result = null; 236 237 // Trap Object calls. This is important here to avoid a recursive 238 // invocation of toString() in the print statements below. 239 if (method.getDeclaringClass() == java.lang.Object.class) { 240 //System.out.println("!!! object " + method.getName()); 241 if (method.getName().equals("toString")) 242 return super.toString(); 243 else if (method.getName().equals("hashCode")) 244 return Integer.valueOf(super.hashCode()); 245 else if (method.getName().equals("equals")) 246 return Boolean.valueOf(super.equals(args[0])); 247 else 248 throw new RuntimeException("huh?"); 249 } 250 251 System.out.println("Invoke " + method); 252 if (args == null || args.length == 0) { 253 System.out.println(" (no args)"); 254 } else { 255 for (int i = 0; i < args.length; i++) 256 System.out.println(" " + i + ": " + args[i]); 257 } 258 259 try { 260 if (true) 261 result = method.invoke(mObj, args); 262 else 263 result = -1; 264 System.out.println("Success: method " + method.getName() 265 + " res=" + result); 266 } catch (InvocationTargetException ite) { 267 throw ite.getTargetException(); 268 } catch (IllegalAccessException iae) { 269 throw new RuntimeException(iae); 270 } 271 return result; 272 } 273 } 274