1 35 package org.jruby.exceptions; 36 37 import java.io.ByteArrayOutputStream ; 38 import java.io.PrintStream ; 39 import java.io.PrintWriter ; 40 import java.io.StringWriter ; 41 42 import org.jruby.*; 43 import org.jruby.runtime.Block; 44 import org.jruby.runtime.ThreadContext; 45 import org.jruby.runtime.builtin.IRubyObject; 46 47 public class RaiseException extends JumpException { 48 private static final long serialVersionUID = -7612079169559973951L; 49 50 private RubyException exception; 51 52 public RaiseException(RubyException actException) { 53 this(actException, false); 54 } 55 56 public RaiseException(Ruby runtime, RubyClass excptnClass, String msg, boolean nativeException) { 57 super(msg, JumpType.RaiseJump); 58 if (msg == null) { 59 msg = "No message available"; 60 } 61 setException((RubyException) excptnClass.callMethod(runtime.getCurrentContext(), "new", new IRubyObject[] {excptnClass.getRuntime().newString(msg)}, Block.NULL_BLOCK), nativeException); 62 } 63 64 public RaiseException(RubyException exception, boolean isNativeException) { 65 super(JumpType.RaiseJump); 66 setException(exception, isNativeException); 67 } 68 69 public static RaiseException createNativeRaiseException(Ruby runtime, Throwable cause) { 70 NativeException nativeException = new NativeException(runtime, runtime.getClass(NativeException.CLASS_NAME), cause); 71 return new RaiseException(cause, nativeException); 72 } 73 74 private static String buildMessage(Throwable exception) { 75 StringBuffer sb = new StringBuffer (); 76 StringWriter stackTrace = new StringWriter (); 77 exception.printStackTrace(new PrintWriter (stackTrace)); 78 79 sb.append("Native Exception: '").append(exception.getClass()).append("'; "); 80 sb.append("Message: ").append(exception.getMessage()).append("; "); 81 sb.append("StackTrace: ").append(stackTrace.getBuffer().toString()); 82 83 return sb.toString(); 84 } 85 86 public RaiseException(Throwable cause, NativeException nativeException) { 87 super(buildMessage(cause), cause, JumpType.RaiseJump); 88 setException(nativeException, false); 89 } 90 91 95 public RubyException getException() { 96 return exception; 97 } 98 99 103 protected void setException(RubyException newException, boolean nativeException) { 104 Ruby runtime = newException.getRuntime(); 105 ThreadContext context = runtime.getCurrentContext(); 106 107 if (!context.isWithinDefined()) { 108 runtime.getGlobalVariables().set("$!", newException); 109 } 110 111 if (runtime.getTraceFunction() != null) { 112 runtime.callTraceFunction(context, "return", context.getPosition(), 113 context.getFrameSelf(), context.getFrameName(), context.getFrameKlazz()); 114 } 115 116 this.exception = newException; 117 118 if (runtime.getStackTraces() > 5) { 119 return; 120 } 121 122 runtime.setStackTraces(runtime.getStackTraces() + 1); 123 124 if (newException.callMethod(context, "backtrace").isNil() && context.getSourceFile() != null) { 125 IRubyObject backtrace = context.createBacktrace(0, nativeException); 126 newException.callMethod(context, "set_backtrace", backtrace); 127 } 128 129 runtime.setStackTraces(runtime.getStackTraces() - 1); 130 } 131 132 public Throwable fillInStackTrace() { 133 return originalFillInStackTrace(); 134 } 135 136 public void printStackTrace() { 137 printStackTrace(System.err); 138 } 139 140 public void printStackTrace(PrintStream ps) { 141 StackTraceElement [] trace = getStackTrace(); 142 int externalIndex = 0; 143 for (int i = trace.length - 1; i > 0; i--) { 144 if (trace[i].getClassName().indexOf("org.jruby.evaluator") >= 0) { 145 break; 146 } 147 externalIndex = i; 148 } 149 IRubyObject backtrace = exception.backtrace(); 150 Ruby runtime = backtrace.getRuntime(); 151 if (runtime.getNil() != backtrace) { 152 String firstLine = backtrace.callMethod(runtime.getCurrentContext(), "first").callMethod(runtime.getCurrentContext(), "to_s").toString(); 153 ps.print(firstLine + ": "); 154 } 155 ps.println(exception.message + " (" + exception.getMetaClass().toString() + ")"); 156 exception.printBacktrace(ps); 157 ps.println("\t...internal jruby stack elided..."); 158 for (int i = externalIndex; i < trace.length; i++) { 159 ps.println("\tfrom " + trace[i].toString()); 160 } 161 } 162 163 public void printStackTrace(PrintWriter pw) { 164 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 165 printStackTrace(new PrintStream (baos)); 166 pw.print(baos.toString()); 167 } 168 } 169 | Popular Tags |