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
17import java.io.IOException;
18import java.lang.reflect.InvocationHandler;
19import java.lang.reflect.InvocationTargetException;
20import java.lang.reflect.Method;
21import java.lang.reflect.Proxy;
22import java.lang.reflect.UndeclaredThrowableException;
23
24/*
25 * Create a Proxy class that blah.
26 */
27public class WrappedThrow {
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.err.println("No exception thrown");
47        } catch (UndeclaredThrowableException ute) {
48            System.out.println("Got expected UTE");
49        } catch (Throwable t) {
50            System.err.println("Got unexpected exception: " + t);
51        }
52
53        try {
54            if1.throwFunky2();
55            System.err.println("No exception thrown");
56        } catch (IOException ioe) {
57            System.out.println("Got expected IOE");
58        } catch (Throwable t) {
59            System.err.println("Got unexpected exception: " + t);
60        }
61
62        try {
63            if2.throwFunky2();
64            System.err.println("No exception thrown");
65        } catch (IOException ioe) {
66            System.out.println("Got expected IOE");
67        } catch (Throwable t) {
68            System.err.println("Got unexpected exception: " + t);
69        }
70
71        /*
72         * Throw exceptions, walking down the hierarchy.
73         */
74        try {
75            if1.throwException();
76            System.err.println("No exception thrown");
77        } catch (UndeclaredThrowableException ute) {
78            System.out.println("Got expected UTE");
79        } catch (Throwable t) {
80            System.err.println("Got unexpected exception: " + t);
81        }
82
83        try {
84            if1.throwBase();
85            System.err.println("No exception thrown");
86        } catch (UndeclaredThrowableException ute) {
87            System.out.println("Got expected UTE");
88        } catch (Throwable t) {
89            System.err.println("Got unexpected exception: " + t);
90        }
91
92        try {
93            if2.throwSub();
94            System.err.println("No exception thrown");
95        } catch (SubException se) {
96            System.out.println("Got expected exception");
97        } catch (Throwable t) {
98            System.err.println("Got unexpected exception: " + t);
99        }
100
101        try {
102            if2.throwSubSub();
103            System.err.println("No exception thrown");
104        } catch (SubException se) {
105            System.out.println("Got expected exception");
106        } catch (Throwable t) {
107            System.err.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.err.println("No exception thrown");
117        } catch (BaseException se) {
118            System.out.println("Got expected exception");
119        } catch (Throwable t) {
120            System.err.println("Got unexpected exception: " + t);
121        }
122    }
123}
124
125class BaseException extends Exception {}
126class SubException extends BaseException {}
127class SubSubException extends SubException {}
128
129interface InterfaceW1 {
130    public void throwFunky();
131
132    public void throwFunky2() throws BaseException,
133           NoSuchMethodException, IOException;
134
135    public void throwException() throws BaseException;
136    public void throwBase() throws BaseException;
137    public void throwSub() throws BaseException;
138    public void throwSubSub() throws BaseException;
139
140    public void bothThrowBase() throws BaseException, SubException, SubSubException;
141}
142
143interface InterfaceW2 {
144    public void throwFunky2() throws InterruptedException,
145           NoSuchMethodException, IOException;
146
147    public void throwException() throws SubException;
148    public void throwBase() throws SubException;
149    public void throwSub() throws SubException;
150    public void throwSubSub() throws SubException;
151
152    public void bothThrowBase() throws SubException, BaseException, SubSubException;
153}
154
155/**
156 * Implement all of the proxied interfaces.
157 */
158class WTMix implements InterfaceW1, InterfaceW2 {
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 */
165    public void throwFunky() {}
166    public void throwFunky2() {}
167    public void throwException() throws SubException {}
168    public void throwBase() throws SubException {}
169    public void throwSub() throws SubException {}
170    public void throwSubSub() throws SubException {}
171
172    public void bothThrowBase() throws BaseException, SubException {}
173}
174
175/**
176 * Invocation handler for our proxy class.
177 */
178class WTInvocationHandler implements InvocationHandler {
179    private Object mObj;
180
181    public WTInvocationHandler(Object obj) {
182        mObj = obj;
183    }
184
185    /*
186     * This is called when anything gets invoked in the proxy object.
187     */
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