/** * Copyright (C) 2015 Valkyrie RCP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.valkyriercp.application.exceptionhandling; import org.jdesktop.swingx.JXErrorPane; import org.jdesktop.swingx.error.ErrorInfo; import org.jdesktop.swingx.error.ErrorReporter; import javax.swing.*; import java.util.logging.Level; /** * Error handler based on the {@link org.jdesktop.swingx.JXErrorPane} found in the swingx project. * * @author Jan Hoskens */ public class JXErrorDialogExceptionHandler<SELF extends JXErrorDialogExceptionHandler<SELF>> extends MessagesDialogExceptionHandler<SELF> { private ErrorReporter errorReporter; /** * No shutDownPolicy can be used in conjunction with the {@link org.jdesktop.swingx.JXErrorPane}. */ public void setShutdownPolicy(ShutdownPolicy shutdownPolicy) { throw new UnsupportedOperationException( "JXErrorDialogExceptionHandler does not support setting of ShutdownPolicy"); } /** * Add an {@link ErrorReporter} to the {@link org.jdesktop.swingx.JXErrorPane}. * * @param errorReporter error reporter to add. */ public void setErrorReporter(ErrorReporter errorReporter) { this.errorReporter = errorReporter; } public SELF reportingTo(ErrorReporter errorReporter) { setErrorReporter(errorReporter); return self(); } /** * Shows the {@link org.jdesktop.swingx.JXErrorPane} to the user. */ public void notifyUserAboutException(Thread thread, final Throwable throwable) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { final ErrorInfo errorInfo = new ErrorInfo( resolveExceptionCaption(throwable), (String) createExceptionContent(throwable), getDetailsAsHTML(throwable.getMessage(), throwable), null, throwable, Level.SEVERE, null); JXErrorPane pane = new JXErrorPane(); pane.setErrorInfo(errorInfo); if (errorReporter != null) { pane.setErrorReporter(errorReporter); } JXErrorPane.showDialog(resolveParentFrame(), pane); } }); } /** * Converts the incoming string to an escaped output string. This method is * far from perfect, only escaping <, > and & characters */ private static String escapeXml(String input) { return input == null ? "" : input.replace("&", "&").replace("<", "<").replace(">", ">"); } /** * Creates and returns HTML representing the details of this incident info. * This method is only called if the details needs to be generated: ie: the * detailed error message property of the incident info is null. */ private static String getDetailsAsHTML(String title, Throwable e) { if (e != null) { // convert the stacktrace into a more pleasent bit of HTML StringBuilder html = new StringBuilder("<html>"); html.append("<h2>").append(escapeXml(title)).append("</h2>"); html.append("<HR size='1' noshade>"); html.append("<div></div>"); html.append("<b>Message:</b>"); html.append("<pre>"); html.append(" ").append(escapeXml(e.toString())); html.append("</pre>"); html.append("<b>Stack trace:</b>"); html.append("<pre>"); for (StackTraceElement el : e.getStackTrace()) { html.append(" ").append(el.toString().replace("<init>", "<init>")).append("\n"); } if (e.getCause() != null) { html.append("</pre>"); html.append("<b>Cause:</b>"); html.append("<pre>"); html.append(e.getCause().getMessage()); html.append("</pre><pre>"); for (StackTraceElement el : e.getCause().getStackTrace()) { html.append(" ").append(el.toString().replace("<init>", "<init>")).append("\n"); } } html.append("</pre></html>"); return html.toString(); } else { return null; } } }