package org.dynjs.exception; import org.dynjs.runtime.*; import org.dynjs.runtime.builtins.types.error.JavaStackGetter; import org.dynjs.runtime.builtins.types.error.StackElement; import java.util.ArrayList; public class ThrowException extends DynJSException { private static final long serialVersionUID = -5523478980527254739L; private final ExecutionContext context; private Object value; private ArrayList<StackElement> stack; public ThrowException(final ExecutionContext context, Throwable value) { super(value); this.value = value; this.context = context; setUpStackElements(context); } public ThrowException(final ExecutionContext context, Object value) { this.value = value; this.context = context; setUpStackElements(context); if (value instanceof JSObject) { JSObject object = (JSObject) value; if (!object.hasProperty(context, "stack")) { PropertyDescriptor stackDesc = new PropertyDescriptor(); stackDesc.setGetter(new JavaStackGetter(context.getGlobalContext(), this)); ((JSObject) value).defineOwnProperty(context, "stack", stackDesc, false); } } } protected void setUpStackElements(final ExecutionContext context) { this.stack = new ArrayList<StackElement>(); context.collectStackElements(this.stack); int stackSize = this.stack.size(); StackTraceElement[] javaElements = getStackTrace(); StackTraceElement[] elements = new StackTraceElement[javaElements.length + stackSize]; for (int i = 0; i < stackSize; ++i) { StackElement e = stack.get(i); String cn = "<global>"; String fn = null; int dotLoc = e.getDebugContext().indexOf("."); if (dotLoc > 0) { cn = e.getDebugContext().substring(0, dotLoc); fn = e.getDebugContext().substring(dotLoc + 1); } else { fn = e.getDebugContext(); } elements[i] = new StackTraceElement(cn, fn, e.getFileName(), e.getLineNumber()); } for (int i = 0; i < javaElements.length; ++i) { elements[i + stackSize] = javaElements[i]; } setStackTrace(elements); } public String getMessage() { if (value instanceof JSObject) { String message = ""; if (((JSObject) value).hasProperty(null, "name")) { message += ((JSObject) value).get(null, "name") + ": "; } if (((JSObject) value).hasProperty(null, "message")) { message += ((JSObject) value).get(null, "message"); } return message; } else if (value instanceof String) { return value.toString(); } return super.getMessage(); } public Object getValue() { return this.value; } @Override public synchronized Throwable getCause() { Throwable cause = super.getCause(); if (cause != null) { return cause; } if (this.value instanceof JSObject) { Object jsCause = ((JSObject) this.value).get(this.context, "cause"); if (jsCause instanceof Throwable) { return (Throwable) jsCause; } else if (jsCause != null && jsCause != Types.UNDEFINED) { return new ThrowException(this.context, jsCause); } } return null; } }