/**
*
* This file is a part of ZOOLA - an extensible BeanShell implementation.
* Zoola is based on original BeanShell code created by Pat Niemeyer.
*
* Original BeanShell code is Copyright (C) 2000 Pat Niemeyer <pat@pat.net>.
*
* New portions are Copyright 2012 Rafal Lewczuk <rafal.lewczuk@jitlogic.com>
*
* This is free software. You can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ZOOLA. If not, see <http://www.gnu.org/licenses/>.
*
*/
package bsh;
import bsh.ast.SimpleNode;
/**
EvalError indicates that we cannot continue evaluating the script
or the script has thrown an exception.
EvalError may be thrown for a script syntax error, an evaluation
error such as referring to an undefined variable, an internal error.
<p>
@see TargetError
*/
public class EvalError extends Error
{
private SimpleNode node;
// Note: no way to mutate the Throwable message, must maintain our own
private String message;
private final CallStack callstack;
public EvalError( String s, SimpleNode node, CallStack callstack, Throwable cause ) {
this(s,node,callstack);
initCause(cause);
}
public EvalError( String s, SimpleNode node, CallStack callstack ) {
this.message = s;
this.node = node;
// freeze the callstack for the stack trace.
this.callstack = callstack==null ? null : callstack.copy();
}
/**
Print the error with line number and stack trace.
*/
public String getMessage()
{
String trace;
if ( node != null )
trace = " : at Line: "+ node.getLineNumber()
+ " : in file: "+ node.getSourceFile()
+ " : "+node.getText();
else
// Users should not normally see this.
trace = ": <at unknown location>";
if ( callstack != null )
trace = trace +"\n" + getScriptStackTrace();
return getRawMessage() + trace;
}
/**
Re-throw the error, prepending the specified message.
*/
public void reThrow( String msg )
throws EvalError
{
prependMessage( msg );
throw this;
}
/**
The error has trace info associated with it.
i.e. It has an AST node that can print its location and source text.
*/
SimpleNode getNode() {
return node;
}
void setNode( SimpleNode node ) {
this.node = node;
}
public String getErrorText() {
if ( node != null )
return node.getText() ;
else
return "<unknown error>";
}
public int getErrorLineNumber() {
if ( node != null )
return node.getLineNumber() ;
else
return -1;
}
public String getErrorSourceFile() {
if ( node != null )
return node.getSourceFile() ;
else
return "<unknown file>";
}
public String getScriptStackTrace()
{
if ( callstack == null )
return "<Unknown>";
String trace = "";
CallStack stack = callstack.copy();
while ( stack.depth() > 0 )
{
NameSpace ns = stack.pop();
SimpleNode node = ns.getNode();
if ( ns.isMethod )
{
trace = trace + "\nCalled from method: " + ns.getName();
if ( node != null )
trace += " : at Line: "+ node.getLineNumber()
+ " : in file: "+ node.getSourceFile()
+ " : "+node.getText();
}
}
return trace;
}
public String getRawMessage() { return message; }
/**
Prepend the message if it is non-null.
*/
private void prependMessage( String s )
{
if ( s == null )
return;
if ( message == null )
message = s;
else
message = s + " : "+ message;
}
}