public Integer handleError(ESXX esxx, Context cx, Throwable ex) { String title = "ESXX Server Error"; int code = 500; if (ex instanceof ESXXException) { code = ((ESXXException) ex).getStatus(); } StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); out.println(esxx.getHTMLHeader()); out.println("<h2>" + title + "</h2>"); out.println("<h3>Unhandled exception: " + ex.getClass().getSimpleName() + "</h3>"); if (ex instanceof ESXXException || ex instanceof javax.xml.stream.XMLStreamException || ex instanceof javax.xml.transform.TransformerException) { out.println("<p><tt>" + encodeXMLContent(ex.getMessage()) + "</tt></p>"); } else if (ex instanceof RhinoException) { out.println("<pre>"); out.println(ex.getClass().getSimpleName() + ": " + encodeXMLContent(ex.getMessage())); out.println(((RhinoException) ex).getScriptStackTrace(new ESXX.JSFilenameFilter())); out.println("</pre>"); } else { out.println("<pre>"); ex.printStackTrace(out); out.println("</pre>"); } out.println(esxx.getHTMLFooter()); out.close(); try { return handleResponse( esxx, cx, new Response(code, "text/html; charset=UTF-8", sw.toString(), null)); } catch (Exception ex2) { // Hmm return 20; } }
/** Interrupts script execution. */ private void interrupted(Context cx, final StackFrame frame, Throwable scriptException) { ContextData contextData = frame.contextData(); boolean eventThreadFlag = callback.isGuiEventThread(); contextData.eventThreadFlag = eventThreadFlag; boolean recursiveEventThreadCall = false; interruptedCheck: synchronized (eventThreadMonitor) { if (eventThreadFlag) { if (interruptedContextData != null) { recursiveEventThreadCall = true; break interruptedCheck; } } else { while (interruptedContextData != null) { try { eventThreadMonitor.wait(); } catch (InterruptedException exc) { return; } } } interruptedContextData = contextData; } if (recursiveEventThreadCall) { // XXX: For now the following is commented out as on Linux // too deep recursion of dispatchNextGuiEvent causes GUI lockout. // Note: it can make GUI unresponsive if long-running script // will be called on GUI thread while processing another interrupt if (false) { // Run event dispatch until gui sets a flag to exit the initial // call to interrupted. while (this.returnValue == -1) { try { callback.dispatchNextGuiEvent(); } catch (InterruptedException exc) { } } } return; } if (interruptedContextData == null) Kit.codeBug(); try { do { int frameCount = contextData.frameCount(); this.frameIndex = frameCount - 1; final String threadTitle = Thread.currentThread().toString(); final String alertMessage; if (scriptException == null) { alertMessage = null; } else { alertMessage = scriptException.toString(); } int returnValue = -1; if (!eventThreadFlag) { synchronized (monitor) { if (insideInterruptLoop) Kit.codeBug(); this.insideInterruptLoop = true; this.evalRequest = null; this.returnValue = -1; callback.enterInterrupt(frame, threadTitle, alertMessage); try { for (; ; ) { try { monitor.wait(); } catch (InterruptedException exc) { Thread.currentThread().interrupt(); break; } if (evalRequest != null) { this.evalResult = null; try { evalResult = do_eval(cx, evalFrame, evalRequest); } finally { evalRequest = null; evalFrame = null; monitor.notify(); } continue; } if (this.returnValue != -1) { returnValue = this.returnValue; break; } } } finally { insideInterruptLoop = false; } } } else { this.returnValue = -1; callback.enterInterrupt(frame, threadTitle, alertMessage); while (this.returnValue == -1) { try { callback.dispatchNextGuiEvent(); } catch (InterruptedException exc) { } } returnValue = this.returnValue; } switch (returnValue) { case STEP_OVER: contextData.breakNextLine = true; contextData.stopAtFrameDepth = contextData.frameCount(); break; case STEP_INTO: contextData.breakNextLine = true; contextData.stopAtFrameDepth = -1; break; case STEP_OUT: if (contextData.frameCount() > 1) { contextData.breakNextLine = true; contextData.stopAtFrameDepth = contextData.frameCount() - 1; } break; } } while (false); } finally { synchronized (eventThreadMonitor) { interruptedContextData = null; eventThreadMonitor.notifyAll(); } } }