import java.lang.reflect.*;

public class ReflectionTest {
  static class MyException extends RuntimeException {}

  public static void main(String[] args) {
    checkNewInstance();
    checkConstructor();
    checkInvokeVirtual();
    checkInvokeStatic();
  }

  // "Note that this method propagates any exception thrown by the nullary 
  // constructor, including a checked exception."
  // [http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance()]
  static void checkNewInstance() {
    try {
      ReflectionTest.class.newInstance();
    } catch(MyException e) {
      System.out.println("newInstance: pass");
    } catch(Throwable e) {
      System.out.println("newInstance: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();
    }
  }

  // For correct behavior, see the class description of the
  // following documentation:
  // [http://java.sun.com/javase/6/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)]
  static void checkConstructor() {
    try {
      Constructor<ReflectionTest> c = ReflectionTest.class.getConstructor();
      c.newInstance();
    }catch (InvocationTargetException e) {
      if (e.getCause() instanceof MyException) {
        System.out.println("constructor: pass");
      } else {        
        System.out.println("constructor: fail");
        System.out.println("unexpected cause of the Invocation target exception: ");
        e.printStackTrace();
      }
    } catch(Throwable e) {
      System.out.println("constructor: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();
    }
  }

  // For correct behavior, see the class description of the
  // following documentation:
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationTargetException.html
  static void checkInvokeVirtual() {
    try {
      ReflectionTest r = new ReflectionTest(0);
      Method mFoo = ReflectionTest.class.getMethod("foo");
      mFoo.invoke(r);
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof MyException) {
        System.out.println("invokeVirtual: pass");
      } else {        
        System.out.println("invokeVirtual: fail");
        System.out.println("unexpected cause of the Invocation target exception: ");
        e.printStackTrace();
      }
    } catch (Throwable e) {
      System.out.println("invokeVirtual: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();      
    }
  }

  // For correct behavior, see the class description of the
  // following documentation:
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationTargetException.html
  static void checkInvokeStatic() {
    try {
      ReflectionTest r = new ReflectionTest(0);
      Method mFoo = ReflectionTest.class.getMethod("bar");
      mFoo.invoke(null);
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof MyException) {
        System.out.println("invokeStatic: pass");
      } else {        
        System.out.println("invokeStatic: fail");
        System.out.println("unexpected cause of the Invocation target exception: ");
        e.printStackTrace();
      }
    } catch (Throwable e) {
      System.out.println("invokeStatic: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();      
    }
  }

  public ReflectionTest() {throw new MyException();}
  public ReflectionTest(int i) {}
  public void foo() {throw new MyException();}
  public static void bar() {throw new MyException();}
}

