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