001 package org.springframework.richclient.exceptionhandling; 002 003 import java.util.logging.Level; 004 005 import javax.swing.JOptionPane; 006 007 import org.jdesktop.swingx.JXErrorPane; 008 import org.jdesktop.swingx.error.ErrorInfo; 009 import org.jdesktop.swingx.error.ErrorReporter; 010 011 /** 012 * Error handler based on the {@link JXErrorPane} found in the swingx project. 013 * 014 * @author Jan Hoskens 015 * 016 */ 017 public class JXErrorDialogExceptionHandler extends MessagesDialogExceptionHandler { 018 019 private ErrorReporter errorReporter; 020 021 /** 022 * No shutDownPolicy can be used in conjunction with the {@link JXErrorPane}. 023 */ 024 public void setShutdownPolicy(ShutdownPolicy shutdownPolicy) { 025 throw new UnsupportedOperationException( 026 "JXErrorDialogExceptionHandler does not support setting of ShutdownPolicy"); 027 } 028 029 /** 030 * Add an {@link ErrorReporter} to the {@link JXErrorPane}. 031 * 032 * @param errorReporter error reporter to add. 033 */ 034 public void setErrorReporter(ErrorReporter errorReporter) { 035 this.errorReporter = errorReporter; 036 } 037 038 /** 039 * Shows the {@link JXErrorPane} to the user. 040 */ 041 public void notifyUserAboutException(Thread thread, Throwable throwable) { 042 ErrorInfo errorInfo = new ErrorInfo(resolveExceptionCaption(throwable), 043 (String) createExceptionContent(throwable), getDetailsAsHTML(throwable.getMessage(), resolveMessageType(), 044 throwable), null, throwable, resolveMessageType(), null); 045 JXErrorPane pane = new JXErrorPane(); 046 pane.setErrorInfo(errorInfo); 047 if (errorReporter != null) { 048 pane.setErrorReporter(errorReporter); 049 } 050 051 JXErrorPane.showDialog(resolveParentFrame(), pane); 052 } 053 054 /** 055 * Resolve the Spring logLevel to java Level. 056 */ 057 private Level resolveMessageType() { 058 switch (logLevel) { 059 case TRACE: 060 return Level.FINEST; 061 case DEBUG: 062 return Level.FINER; 063 case INFO: 064 return Level.INFO; 065 case WARN: 066 return Level.WARNING; 067 case ERROR: 068 case FATAL: 069 default: 070 return Level.SEVERE; 071 } 072 } 073 074 /** 075 * Converts the incoming string to an escaped output string. This method is 076 * far from perfect, only escaping <, > and & characters 077 */ 078 private static String escapeXml(String input) { 079 return input == null ? "" : input.replace("&", "&").replace("<", "<").replace(">", ">"); 080 } 081 082 /** 083 * Creates and returns HTML representing the details of this incident info. 084 * This method is only called if the details needs to be generated: ie: the 085 * detailed error message property of the incident info is null. 086 */ 087 private static String getDetailsAsHTML(String title, Level level, Throwable e) { 088 if (e != null) { 089 // convert the stacktrace into a more pleasent bit of HTML 090 StringBuffer html = new StringBuffer("<html>"); 091 html.append("<h2>" + escapeXml(title) + "</h2>"); 092 html.append("<HR size='1' noshade>"); 093 html.append("<div></div>"); 094 html.append("<b>Message:</b>"); 095 html.append("<pre>"); 096 html.append(" " + escapeXml(e.toString())); 097 html.append("</pre>"); 098 html.append("<b>Level:</b>"); 099 html.append("<pre>"); 100 html.append(" " + level); 101 html.append("</pre>"); 102 html.append("<b>Stack Trace:</b>"); 103 html.append("<pre>"); 104 for (StackTraceElement el : e.getStackTrace()) { 105 html.append(" " + el.toString().replace("<init>", "<init>") + "\n"); 106 } 107 if (e.getCause() != null) { 108 html.append("</pre>"); 109 html.append("<b>Cause:</b>"); 110 html.append("<pre>"); 111 html.append(e.getCause().getMessage()); 112 html.append("</pre><pre>"); 113 for (StackTraceElement el : e.getCause().getStackTrace()) { 114 html.append(" " + el.toString().replace("<init>", "<init>") + "\n"); 115 } 116 } 117 html.append("</pre></html>"); 118 return html.toString(); 119 } 120 else { 121 return null; 122 } 123 } 124 }