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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
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>", "&lt;init&gt;") + "\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>", "&lt;init&gt;") + "\n");
115                                    }
116                            }
117                            html.append("</pre></html>");
118                            return html.toString();
119                    }
120                    else {
121                            return null;
122                    }
123            }
124    }