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