001: /*****************************************************************************
002: * *
003: * This file is part of the BeanShell Java Scripting distribution. *
004: * Documentation and updates may be found at http://www.beanshell.org/ *
005: * *
006: * Sun Public License Notice: *
007: * *
008: * The contents of this file are subject to the Sun Public License Version *
009: * 1.0 (the "License"); you may not use this file except in compliance with *
010: * the License. A copy of the License is available at http://www.sun.com *
011: * *
012: * The Original Code is BeanShell. The Initial Developer of the Original *
013: * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
014: * (C) 2000. All Rights Reserved. *
015: * *
016: * GNU Public License Notice: *
017: * *
018: * Alternatively, the contents of this file may be used under the terms of *
019: * the GNU Lesser General Public License (the "LGPL"), in which case the *
020: * provisions of LGPL are applicable instead of those above. If you wish to *
021: * allow use of your version of this file only under the terms of the LGPL *
022: * and not to allow others to use your version of this file under the SPL, *
023: * indicate your decision by deleting the provisions above and replace *
024: * them with the notice and other provisions required by the LGPL. If you *
025: * do not delete the provisions above, a recipient may use your version of *
026: * this file under either the SPL or the LGPL. *
027: * *
028: * Patrick Niemeyer (pat@pat.net) *
029: * Author of Learning Java, O'Reilly & Associates *
030: * http://www.pat.net/~pat/ *
031: * *
032: *****************************************************************************/package bsh;
033:
034: import java.lang.reflect.InvocationTargetException;
035:
036: import java.io.PrintStream;
037:
038: /**
039: TargetError is an EvalError that wraps an exception thrown by the script
040: (or by code called from the script). TargetErrors indicate exceptions
041: which can be caught within the script itself, whereas a general EvalError
042: indicates that the script cannot be evaluated further for some reason.
043:
044: If the exception is caught within the script it is automatically unwrapped,
045: so the code looks like normal Java code. If the TargetError is thrown
046: from the eval() or interpreter.eval() method it may be caught and unwrapped
047: to determine what exception was thrown.
048: */
049: public class TargetError extends EvalError {
050: Throwable target;
051: boolean inNativeCode;
052:
053: public TargetError(String msg, Throwable t, SimpleNode node,
054: CallStack callstack, boolean inNativeCode) {
055: super (msg, node, callstack);
056: target = t;
057: this .inNativeCode = inNativeCode;
058: }
059:
060: public TargetError(Throwable t, SimpleNode node, CallStack callstack) {
061: this ("TargetError", t, node, callstack, false);
062: }
063:
064: public Throwable getTarget() {
065: // check for easy mistake
066: if (target instanceof InvocationTargetException)
067: return ((InvocationTargetException) target)
068: .getTargetException();
069: else
070: return target;
071: }
072:
073: public String toString() {
074: return super .toString() + "\nTarget exception: "
075: + printTargetError(target);
076: }
077:
078: public void printStackTrace() {
079: printStackTrace(false, System.err);
080: }
081:
082: public void printStackTrace(PrintStream out) {
083: printStackTrace(false, out);
084: }
085:
086: public void printStackTrace(boolean debug, PrintStream out) {
087: if (debug) {
088: super .printStackTrace(out);
089: out.println("--- Target Stack Trace ---");
090: }
091: target.printStackTrace(out);
092: }
093:
094: /**
095: Generate a printable string showing the wrapped target exception.
096: If the proxy mechanism is available, allow the extended print to
097: check for UndeclaredThrowableException and print that embedded error.
098: */
099: public String printTargetError(Throwable t) {
100: String s = target.toString();
101:
102: if (Capabilities.canGenerateInterfaces())
103: s += "\n" + xPrintTargetError(t);
104:
105: return s;
106: }
107:
108: /**
109: Extended form of print target error.
110: This indirection is used to print UndeclaredThrowableExceptions
111: which are possible when the proxy mechanism is available.
112:
113: We are shielded from compile problems by using a bsh script.
114: This is acceptable here because we're not in a critical path...
115: Otherwise we'd need yet another dynamically loaded module just for this.
116: */
117: public String xPrintTargetError(Throwable t) {
118: String getTarget = "import java.lang.reflect.UndeclaredThrowableException;"
119: + "String result=\"\";"
120: + "while ( target instanceof UndeclaredThrowableException ) {"
121: + " target=target.getUndeclaredThrowable(); "
122: + " result+=\"Nested: \"+target.toString();"
123: + "}"
124: + "return result;";
125: Interpreter i = new Interpreter();
126: try {
127: i.set("target", t);
128: return (String) i.eval(getTarget);
129: } catch (EvalError e) {
130: throw new InterpreterError("xprintarget: " + e.toString());
131: }
132: }
133:
134: /**
135: Return true if the TargetError was generated from native code.
136: e.g. if the script called into a compiled java class which threw
137: the excpetion. We distinguish so that we can print the stack trace
138: for the native code case... the stack trace would not be useful if
139: the exception was generated by the script. e.g. if the script
140: explicitly threw an exception... (the stack trace would simply point
141: to the bsh internals which generated the exception).
142: */
143: public boolean inNativeCode() {
144: return inNativeCode;
145: }
146: }
|