package jp;

import java.io.*;
import javax.servlet.http.*;
import com.mortbay.HTTP.*;

/**
 * A PageException is a handy way to shape control flow in a server.
 * The server builds an output page, but when it needs to throw an
 * exception that should be reported to the server, it simply throws a
 * PageException (or an appropriate subclass). The PageException itself
 * carries info about the error page to be displayed, and can be easily
 * used in a generic <code>catch {}</code> block to present the error
 * to the user.<p>
 * 
 * This is a nicer organization than trying to build
 * fancy error pages in-line where the errors are discovered. They are,
 * after all, exceptions.
 */
public class PageException
	extends Exception {

	/**
	 * Shorthand for <code>HttpServletResponse.SC_BAD_GATEWAY</code>.
	 */
	public static final int GATEWAY = HttpServletResponse.SC_BAD_GATEWAY;

	int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
	String description;
	Exception source;
		
	/**
	 * Create an exception with the given description and an
	 * SC_INTERNAL_SERVER_ERROR response code.
	 */
	public PageException(String description) {
		this.description = description;
	}

	/**
	 * Convert another exception into a PageException that knows how
	 * to display itself.
	 */
	public PageException(Exception source) {
		this.source = source;
	}

	/**
	 * Convert an exception into a PageException, supplying the numeric
	 * response code to associate with the exception report.
	 */
	public PageException(int code, Exception source) {
		this(source);
		this.code = code;
	}

	/**
	 * Create a PageException, supplying both the description and the
	 * numeric response code.
	 */
	public PageException(int code, String description) {
		this.code=code;
		this.description = description;
	}

	/**
	 * Return the exception as a vanilla text string.
	 */
	public String toString() {
		return (description!=null ? description : "")
			+(source!=null ? ("was: "+source) : "");
	}

	/**
	 * Display the exception as an HTML page.
	 *
	 * @param send the HTML page as this response.
	 */
	public void sendResponseTo(HttpServletResponse resp) {
		resp.setStatus(code);
		try {
			OutputStream os;
			try {
				os = resp.getOutputStream();
			} catch (IllegalStateException ex) {
				// bummer -- response outputStream already open as Writer().
				// dump error to stderr.
				os = System.err;
			}
			if (description!=null) {
				os.write(description.getBytes());
			}
			if (source!=null) {
				os.write("Exception occurred:<p><pre>\n".getBytes());
				source.printStackTrace(new PrintStream(os));
				os.write("</pre>\n".getBytes());
			}
			if (source==null && description==null) {
				os.write("something bad happened.".getBytes());
			}
		} catch (IOException ex) {
			// bummer.
		}
	}
}
