/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
/*
* Create a Proxy class that blah.
*/
public class WrappedThrow {
public static void main(String[] args) {
WTMix mix = new WTMix();
InvocationHandler handler = new WTInvocationHandler(mix);
Object proxy;
try {
proxy = Proxy.newProxyInstance(WrappedThrow.class.getClassLoader(),
new Class<?>[] { InterfaceW1.class, InterfaceW2.class },
handler);
} catch (IllegalArgumentException iae) {
System.out.println("WT init failed");
return;
}
InterfaceW1 if1 = (InterfaceW1) proxy;
InterfaceW2 if2 = (InterfaceW2) proxy;
try {
if1.throwFunky();
System.out.println("No exception thrown");
} catch (UndeclaredThrowableException ute) {
System.out.println("Got expected UTE");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
try {
if1.throwFunky2();
System.out.println("No exception thrown");
} catch (IOException ioe) {
System.out.println("Got expected IOE");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
try {
if2.throwFunky2();
System.out.println("No exception thrown");
} catch (IOException ioe) {
System.out.println("Got expected IOE");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
/*
* Throw exceptions, walking down the hierarchy.
*/
try {
if1.throwException();
System.out.println("No exception thrown");
} catch (UndeclaredThrowableException ute) {
System.out.println("Got expected UTE");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
try {
if1.throwBase();
System.out.println("No exception thrown");
} catch (UndeclaredThrowableException ute) {
System.out.println("Got expected UTE");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
try {
if2.throwSub();
System.out.println("No exception thrown");
} catch (SubException se) {
System.out.println("Got expected exception");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
try {
if2.throwSubSub();
System.out.println("No exception thrown");
} catch (SubException se) {
System.out.println("Got expected exception");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
/*
* Make sure that, if the class explicitly allows the base
* class of an exception, that we still allow it.
*/
try {
if1.bothThrowBase();
System.out.println("No exception thrown");
} catch (BaseException se) {
System.out.println("Got expected exception");
} catch (Throwable t) {
System.out.println("Got unexpected exception: " + t);
}
}
}
class BaseException extends Exception {}
class SubException extends BaseException {}
class SubSubException extends SubException {}
interface InterfaceW1 {
public void throwFunky();
public void throwFunky2() throws BaseException,
NoSuchMethodException, IOException;
public void throwException() throws BaseException;
public void throwBase() throws BaseException;
public void throwSub() throws BaseException;
public void throwSubSub() throws BaseException;
public void bothThrowBase() throws BaseException, SubException, SubSubException;
}
interface InterfaceW2 {
public void throwFunky2() throws InterruptedException,
NoSuchMethodException, IOException;
public void throwException() throws SubException;
public void throwBase() throws SubException;
public void throwSub() throws SubException;
public void throwSubSub() throws SubException;
public void bothThrowBase() throws SubException, BaseException, SubSubException;
}
/**
* Implement all of the proxied interfaces.
*/
class WTMix implements InterfaceW1, InterfaceW2 {
public int dastardlyDeed() throws SubException {
System.out.println("Throwing SubException");
throw new SubException();
}
/* these don't actually get called; they just cause exceptions */
public void throwFunky() {}
public void throwFunky2() {}
public void throwException() throws SubException {}
public void throwBase() throws SubException {}
public void throwSub() throws SubException {}
public void throwSubSub() throws SubException {}
public void bothThrowBase() throws BaseException, SubException {}
}
/**
* Invocation handler for our proxy class.
*/
class WTInvocationHandler implements InvocationHandler {
private Object mObj;
public WTInvocationHandler(Object obj) {
mObj = obj;
}
/*
* This is called when anything gets invoked in the proxy object.
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
// Trap Object calls. This is important here to avoid a recursive
// invocation of toString() in the print statements below.
if (method.getDeclaringClass() == java.lang.Object.class) {
//System.out.println("!!! object " + method.getName());
if (method.getName().equals("toString"))
return super.toString();
else if (method.getName().equals("hashCode"))
return Integer.valueOf(super.hashCode());
else if (method.getName().equals("equals"))
return Boolean.valueOf(super.equals(args[0]));
else
throw new RuntimeException("huh?");
}
System.out.println("Invoke " + method);
if (args == null || args.length == 0) {
System.out.println(" (no args)");
} else {
for (int i = 0; i < args.length; i++)
System.out.println(" " + i + ": " + args[i]);
}
try {
if (method.getName().equals("throwFunky"))
throw new InterruptedException("fake");
if (method.getName().equals("throwFunky2"))
throw new IOException("fake2");
if (method.getName().equals("throwException"))
throw new Exception();
if (method.getName().equals("throwBase"))
throw new BaseException();
if (method.getName().equals("throwSub"))
throw new SubException();
if (method.getName().equals("throwSubSub"))
throw new SubSubException();
if (method.getName().equals("bothThrowBase"))
throw new BaseException();
if (true)
result = method.invoke(mObj, args);
else
result = -1;
System.out.println("Success: method " + method.getName()
+ " res=" + result);
} catch (InvocationTargetException ite) {
throw ite.getTargetException();
} catch (IllegalAccessException iae) {
throw new RuntimeException(iae);
}
return result;
}
}