view core/src/luan/LuanException.java @ 689:51a134a8c89b

fix LuanException
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 18 Apr 2016 17:02:16 -0600
parents 67dd1449e354
children ca169567ce07
line wrap: on
line source

package luan;

import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.List;
import java.util.ArrayList;


public final class LuanException extends Exception implements DeepCloneable {
	private LuanTable table;

	public LuanException(String msg,Throwable cause) {
		super(msg,cause);
		initTable();
	}

	public LuanException(String msg) {
		super(msg);
		initTable();
	}

	public LuanException(Throwable cause) {
		super(cause);
		initTable();
	}

	private LuanException(String msg,Throwable cause,int nonsense) {
		super(msg,cause);
	}

	@Override public LuanException shallowClone() {
		return new LuanException(getMessage(),getCause(),99);
	}

	@Override public void deepenClone(DeepCloneable dc,DeepCloner cloner) {
		LuanException clone = (LuanException)dc;
		clone.table = (LuanTable)cloner.get(table);
	}

	public LuanTable table() {
		return table;
	}

	private void initTable() {
		table = new LuanTable();
		table.rawPut( "java", this );
		LuanTable metatable = new LuanTable();
		table.setMetatable(metatable);
		try {
			table.rawPut( "get_message", new LuanJavaFunction(
				LuanException.class.getMethod( "getMessage" ), this
			) );
			table.rawPut( "throw", new LuanJavaFunction(
				LuanException.class.getMethod( "throwThis" ), this
			) );
			table.rawPut( "get_java_stack_trace_string", new LuanJavaFunction(
				LuanException.class.getMethod( "getJavaStackTraceString" ), this
			) );
			metatable.rawPut( "__to_string", new LuanJavaFunction(
				LuanException.class.getMethod( "getFullMessage" ), this
			) );
		} catch(NoSuchMethodException e) {
			throw new RuntimeException(e);
		}
	}

	public void throwThis() throws LuanException {
		throw this;
	}

	public String getFullMessage() {
		return getLuanStackTraceString();
/*
		StringBuilder buf = new StringBuilder();

		Object msg = table.rawGet("message");
		String msgStr = (String)table.rawGet("message_string");
		buf.append( msgStr );

		for( int i = table.rawLength(); i>=1; i-- ) {
			LuanTable tbl = (LuanTable)table.rawGet(i);
			buf.append( "\n\t" ).append( tbl.rawGet("source") ).append( " line " ).append( tbl.rawGet("line") );
			Object callTo = tbl.rawGet("call_to");
			if( callTo != null )
				buf.append( " in call to '" ).append( callTo ).append( "'" );
		}

		if( msg instanceof Throwable ) {
			buf.append( "\nCaused by: " );
			Throwable cause = (Throwable)msg;
			StringWriter sw = new StringWriter();
			cause.printStackTrace(new PrintWriter(sw));
			buf.append( sw );
		}

		return buf.toString();
*/
	}

	public String getJavaStackTraceString() {
		return getJavaStackTraceString(this);
	}

	private static String getJavaStackTraceString(Throwable th) {
		StringWriter sw = new StringWriter();
		th.printStackTrace(new PrintWriter(sw));
		return sw.toString();
	}

	private List<StackTraceElement> justLuan() {
		List<StackTraceElement> list = new ArrayList<StackTraceElement>();
		StackTraceElement[] orig = getStackTrace();
		for( int i=0; i<orig.length; i++ ) {
			StackTraceElement ste = orig[i];
			if( !ste.getClassName().startsWith("luan.impl.EXP") )
				continue;
			list.add(ste);
			if( !ste.getMethodName().equals("doCall") )
				i++;
		}
		return list;
	}

	public String getLuanStackTraceString() {
		StringBuilder sb = new StringBuilder();
		sb.append( getMessage() );
		for( StackTraceElement ste : justLuan() ) {
			sb.append( "\n\t" ).append( ste.getFileName() ).append( " line " ).append( ste.getLineNumber() );
			String method = ste.getMethodName();
			if( !method.equals("doCall") )
				sb.append( " in function '" ).append( method.substring(1) ).append( "'" );
		}
		Throwable cause = getCause();
		if( cause != null )
			sb.append( "\nCaused by: " ).append( getJavaStackTraceString(cause) );
		return sb.toString();
	}

	public static String currentSource() {
		LuanException ex = new LuanException("currentSource");
		List<StackTraceElement> st = ex.justLuan();
		return st.isEmpty() ? null : st.get(0).getFileName();
	}

}