package uk.ac.cam.cl.dtg.teaching.exceptions;

import java.net.Inet4Address;
import java.net.UnknownHostException;

/**
 * A class containing exception information which can be serialized to JSON and deserialized again.
 * 
 * @author acr31
 *
 */
public class SerializableException  {

	private String className;

	private String message;

	private SerializableException cause;

	private SerializableStackTraceElement[] stackTrace;
		
	public SerializableException() {
	}

	private static String getHostName() {
		try {
			return Inet4Address.getLocalHost().getHostName();
		} catch (UnknownHostException e) {
			throw new Error("Failed to find name for local host",e);
		}
	}
	
	public SerializableException(Throwable toSerialize) {
		this(toSerialize,getHostName());
	}
	
	public SerializableException(Throwable toSerialize,String host) {
		this.message = toSerialize.getMessage();
		this.className = toSerialize.getClass().getName();
		if (toSerialize.getCause() != null) {
			this.cause = new SerializableException(toSerialize.getCause(),host);
		}
		StackTraceElement[] stackTrace = toSerialize.getStackTrace();
		this.stackTrace = new SerializableStackTraceElement[stackTrace.length];
		for (int i = 0; i < stackTrace.length; ++i) {
			this.stackTrace[i] = new SerializableStackTraceElement(stackTrace[i],host);
		}
	}

	SerializableException(
			String className,
			String message,
			SerializableException cause,
			SerializableStackTraceElement[] stackTrace) {
		super();
		this.className = className;
		this.message = message;
		this.cause = cause;
		this.stackTrace = stackTrace;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public SerializableStackTraceElement[] getStackTrace() {
		return stackTrace;
	}

	public void setStackTrace(
			SerializableStackTraceElement[] serializableStackTrace) {
		this.stackTrace = serializableStackTrace;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public void setCause(SerializableException cause) {
		this.cause = cause;
	}

	public String getMessage() {
		return this.message;
	}

	public synchronized SerializableException getCause() {
		return this.cause;
	}
	
	@Override
	public String toString() {
		String message = getMessage();
		return this.className + (message == null ? "" : ": " + message);
	}
}

@@ -279,16 +279,17 @@
 tion  %7B%0A
+%09
 %0A%09privat
@@ -763,26 +763,25 @@
 Name());%0A%09%7D%0A
-%09
 %0A
+
 %09public Seri
@@ -831,24 +831,33 @@
 ing host) %7B%0A
+%09%09try %7B%0A%09
 %09%09this.messa
@@ -883,24 +883,154 @@
 tMessage();%0A
+%09%09%7D%0A%09%09catch (Throwable e) %7B%0A%09%09%09this.message = toSerialize.getClass().getName()+%22.getMessage() threw %22+e.getClass().getName();%0A%09%09%7D%0A
 %09%09this.class

Handle the case when getMessage() itself throws an exception