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 }