
import javax.swing.JOptionPane;

class Exception1 extends Exception {

    public String toString() {
        return "ERROR: Exception1";
    }
}

class Exception2 extends Exception {

    public String toString() {
        return "ERROR: Exception2";
    }
}

public class ExceptionsExample {

    static String out = "";

    public static void main(String[] args) {
        try {
            method1();
            out += "Back from method1\n";
            try {
                method4();
                out += "Back from method4\n";
            } catch (Exception2 e) {
                out += e + " caught in main.\n";
            }
            method3();
        } catch (Exception e) {
            out += e + " caught in main.\n";
            // This next statement is used for debugging
            e.printStackTrace();
        }
        JOptionPane.showMessageDialog(null, out);
    } // end main;

    static void method1() throws Exception2 {
        try {
            method2();
        } catch (Exception1 e) {
            out += e + " caught in method1\n";
        } catch (Exception2 e) {
            out += e + " caught in method1\n";
        }
    } // end method1

    static void method2() throws Exception1, Exception2 {
        method3();
        if (false) {
            throw new Exception2();
        }
        if (false) {
            throw new Exception1();
        }
        out += "Back from method3\n";
    } // end method2

    static void method3() throws Exception1 {
        throw new Exception1();
    } // end method3

    static void method4() throws Exception2 {
        method5();
    } // end method4

    static void method5() throws Exception2 {
        try {
            throw new Exception2();
        } finally {
            out += "finally clauses are always executed\n";
        }
    } // end method5
} // end ExceptionsExample


