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.io.IOException; 18 import java.lang.reflect.InvocationHandler; 19 import java.lang.reflect.InvocationTargetException; 20 import java.lang.reflect.Method; 21 import java.lang.reflect.Proxy; 22 import java.lang.reflect.UndeclaredThrowableException; 23 24 /* 25 * Create a Proxy class that blah. 26 */ 27 public class WrappedThrow { main(String[] args)28 public static void main(String[] args) { 29 WTMix mix = new WTMix(); 30 InvocationHandler handler = new WTInvocationHandler(mix); 31 Object proxy; 32 33 try { 34 proxy = Proxy.newProxyInstance(WrappedThrow.class.getClassLoader(), 35 new Class<?>[] { InterfaceW1.class, InterfaceW2.class }, 36 handler); 37 } catch (IllegalArgumentException iae) { 38 System.out.println("WT init failed"); 39 return; 40 } 41 42 InterfaceW1 if1 = (InterfaceW1) proxy; 43 InterfaceW2 if2 = (InterfaceW2) proxy; 44 try { 45 if1.throwFunky(); 46 System.out.println("No exception thrown"); 47 } catch (UndeclaredThrowableException ute) { 48 System.out.println("Got expected UTE"); 49 } catch (Throwable t) { 50 System.out.println("Got unexpected exception: " + t); 51 } 52 53 try { 54 if1.throwFunky2(); 55 System.out.println("No exception thrown"); 56 } catch (IOException ioe) { 57 System.out.println("Got expected IOE"); 58 } catch (Throwable t) { 59 System.out.println("Got unexpected exception: " + t); 60 } 61 62 try { 63 if2.throwFunky2(); 64 System.out.println("No exception thrown"); 65 } catch (IOException ioe) { 66 System.out.println("Got expected IOE"); 67 } catch (Throwable t) { 68 System.out.println("Got unexpected exception: " + t); 69 } 70 71 /* 72 * Throw exceptions, walking down the hierarchy. 73 */ 74 try { 75 if1.throwException(); 76 System.out.println("No exception thrown"); 77 } catch (UndeclaredThrowableException ute) { 78 System.out.println("Got expected UTE"); 79 } catch (Throwable t) { 80 System.out.println("Got unexpected exception: " + t); 81 } 82 83 try { 84 if1.throwBase(); 85 System.out.println("No exception thrown"); 86 } catch (UndeclaredThrowableException ute) { 87 System.out.println("Got expected UTE"); 88 } catch (Throwable t) { 89 System.out.println("Got unexpected exception: " + t); 90 } 91 92 try { 93 if2.throwSub(); 94 System.out.println("No exception thrown"); 95 } catch (SubException se) { 96 System.out.println("Got expected exception"); 97 } catch (Throwable t) { 98 System.out.println("Got unexpected exception: " + t); 99 } 100 101 try { 102 if2.throwSubSub(); 103 System.out.println("No exception thrown"); 104 } catch (SubException se) { 105 System.out.println("Got expected exception"); 106 } catch (Throwable t) { 107 System.out.println("Got unexpected exception: " + t); 108 } 109 110 /* 111 * Make sure that, if the class explicitly allows the base 112 * class of an exception, that we still allow it. 113 */ 114 try { 115 if1.bothThrowBase(); 116 System.out.println("No exception thrown"); 117 } catch (BaseException se) { 118 System.out.println("Got expected exception"); 119 } catch (Throwable t) { 120 System.out.println("Got unexpected exception: " + t); 121 } 122 } 123 } 124 125 class BaseException extends Exception {} 126 class SubException extends BaseException {} 127 class SubSubException extends SubException {} 128 129 interface InterfaceW1 { throwFunky()130 public void throwFunky(); 131 throwFunky2()132 public void throwFunky2() throws BaseException, 133 NoSuchMethodException, IOException; 134 throwException()135 public void throwException() throws BaseException; throwBase()136 public void throwBase() throws BaseException; throwSub()137 public void throwSub() throws BaseException; throwSubSub()138 public void throwSubSub() throws BaseException; 139 bothThrowBase()140 public void bothThrowBase() throws BaseException, SubException, SubSubException; 141 } 142 143 interface InterfaceW2 { throwFunky2()144 public void throwFunky2() throws InterruptedException, 145 NoSuchMethodException, IOException; 146 throwException()147 public void throwException() throws SubException; throwBase()148 public void throwBase() throws SubException; throwSub()149 public void throwSub() throws SubException; throwSubSub()150 public void throwSubSub() throws SubException; 151 bothThrowBase()152 public void bothThrowBase() throws SubException, BaseException, SubSubException; 153 } 154 155 /** 156 * Implement all of the proxied interfaces. 157 */ 158 class WTMix implements InterfaceW1, InterfaceW2 { dastardlyDeed()159 public int dastardlyDeed() throws SubException { 160 System.out.println("Throwing SubException"); 161 throw new SubException(); 162 } 163 164 /* these don't actually get called; they just cause exceptions */ throwFunky()165 public void throwFunky() {} throwFunky2()166 public void throwFunky2() {} throwException()167 public void throwException() throws SubException {} throwBase()168 public void throwBase() throws SubException {} throwSub()169 public void throwSub() throws SubException {} throwSubSub()170 public void throwSubSub() throws SubException {} 171 bothThrowBase()172 public void bothThrowBase() throws BaseException, SubException {} 173 } 174 175 /** 176 * Invocation handler for our proxy class. 177 */ 178 class WTInvocationHandler implements InvocationHandler { 179 private Object mObj; 180 WTInvocationHandler(Object obj)181 public WTInvocationHandler(Object obj) { 182 mObj = obj; 183 } 184 185 /* 186 * This is called when anything gets invoked in the proxy object. 187 */ invoke(Object proxy, Method method, Object[] args)188 public Object invoke(Object proxy, Method method, Object[] args) 189 throws Throwable { 190 191 Object result = null; 192 193 // Trap Object calls. This is important here to avoid a recursive 194 // invocation of toString() in the print statements below. 195 if (method.getDeclaringClass() == java.lang.Object.class) { 196 //System.out.println("!!! object " + method.getName()); 197 if (method.getName().equals("toString")) 198 return super.toString(); 199 else if (method.getName().equals("hashCode")) 200 return Integer.valueOf(super.hashCode()); 201 else if (method.getName().equals("equals")) 202 return Boolean.valueOf(super.equals(args[0])); 203 else 204 throw new RuntimeException("huh?"); 205 } 206 207 System.out.println("Invoke " + method); 208 if (args == null || args.length == 0) { 209 System.out.println(" (no args)"); 210 } else { 211 for (int i = 0; i < args.length; i++) 212 System.out.println(" " + i + ": " + args[i]); 213 } 214 215 try { 216 if (method.getName().equals("throwFunky")) 217 throw new InterruptedException("fake"); 218 if (method.getName().equals("throwFunky2")) 219 throw new IOException("fake2"); 220 if (method.getName().equals("throwException")) 221 throw new Exception(); 222 if (method.getName().equals("throwBase")) 223 throw new BaseException(); 224 if (method.getName().equals("throwSub")) 225 throw new SubException(); 226 if (method.getName().equals("throwSubSub")) 227 throw new SubSubException(); 228 if (method.getName().equals("bothThrowBase")) 229 throw new BaseException(); 230 231 if (true) 232 result = method.invoke(mObj, args); 233 else 234 result = -1; 235 System.out.println("Success: method " + method.getName() 236 + " res=" + result); 237 } catch (InvocationTargetException ite) { 238 throw ite.getTargetException(); 239 } catch (IllegalAccessException iae) { 240 throw new RuntimeException(iae); 241 } 242 return result; 243 } 244 } 245