import javax.swing.* ;import java.awt.* ;import java.awt.event.* ;/** * The JExceptionDialog class provides easy-to-use, single-call methods * for displaying error dialogs based on an exception. The dialogs * will contain a "Show Details" button that shows the exception's * stack trace when clicked. <br /><br /> * * There are two variants of the dialog showing method: showDialog * and showFatalDialog. The latter should be used if your program * cannot recover from the exception and needs to shut down. <br /><br /> * * Example usage:<br /><br /> * * try {<br /> // Dangerous code here<br /> } catch (SomeException e) {<br /> JExceptionDialog.showDialog(e, null) ;<br /> }<br /><br /> * JExceptionDialog also provides a method for getting the String * that would be printed to System.err if an exception's printStackTrace method * was called as a String. * * @author Michael Davies (coolguy5678) */public class JExceptionDialog extends JDialog { private Exception baseException ; private JButton okButton ; private JButton detailsButton ; private JTextArea detailsArea ; private JScrollPane detailsScroll ; private boolean detailsIsActive ; /** * The title of any exception dialogs that are displayed * without specifying a title. You may want to set * this to the name of your application. <br /><br /> * * The default value is "Error". */ public static String defaultTitle = "Error" ; /** * The error message of any exception dialogs that are displayed * without specifying a message. <br /><br /> * * The default value is "An unexpected error has occurred.". */ public static String defaultErrorMessage = "An unexpected error has occurred." ; /** * The error message of any fatal exception dialogs that are displayed * without specifying a message. <br /><br /> * * The default value is * "An unexpected fatal error has occurred, and the program must close." */ public static String defaultFatalErrorMessage = "A fatal error has occurred, " + "and the program must close."; /** * The Icon that is used on the dialogs. <br /> <br /> * * * The default is the "error" Icon from * the look and feel. */ public static Icon errorIcon = UIManager.getLookAndFeel().getDefaults().getIcon("OptionPane.errorIcon") ; //---------- private JExceptionDialog(Exception baseException, Frame owner, String title, String error, String okTitle) { super(owner, title, true) ; this.baseException = baseException ; detailsIsActive = false ; // Set up the content pane JPanel cp = new JPanel() ; cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS)) ; // Add some padding cp.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Add the error message JLabel label = new JLabel(error, errorIcon, JLabel.CENTER) ; label.setAlignmentX(Component.CENTER_ALIGNMENT) ; cp.add(label) ; cp.add(Box.createRigidArea(new Dimension(0, 10))) ; // Set up the panel for the buttons JPanel buttonPanel = new JPanel() ; buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)) ; buttonPanel.add(Box.createHorizontalGlue()) ; // Place buttons on the right edge // Set up the OK button okButton = new JButton(okTitle) ; okButton.addActionListener(list) ; okButton.setActionCommand("ok") ; buttonPanel.add(okButton) ; buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))) ; // Set up the Details button detailsButton = new JButton("Show Details") ; detailsButton.addActionListener(list) ; detailsButton.setActionCommand("details") ; buttonPanel.add(detailsButton) ; // Add the button panel buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))) ; cp.add(buttonPanel) ; cp.add(Box.createRigidArea(new Dimension(0, 10))) ; // Set up the details text area detailsArea = new JTextArea(getExceptionStackTrace(baseException)) ; detailsArea.setEditable(false) ; detailsScroll = new JScrollPane(detailsArea) ; // Final things setContentPane(cp) ; setResizable(false) ; pack() ; // Set size of details to our width by 100 detailsScroll.setMinimumSize(new Dimension(getWidth(), 100)) ; detailsScroll.setPreferredSize(new Dimension(getWidth(), 100)) ; detailsScroll.setMaximumSize(new Dimension(getWidth(), 100)) ; } //---------- private ActionListener list = new ActionListener() { public void actionPerformed(ActionEvent e) { // Go away if OK was pressed if (e.getActionCommand().equals("ok")) { setVisible(false) ; dispose() ; } // Or toggle the details else if (e.getActionCommand().equals("details")) { detailsIsActive = !detailsIsActive ; if (detailsIsActive) { getContentPane().add(detailsScroll) ; detailsButton.setText("Hide Details") ; } else { getContentPane().remove(detailsScroll) ; detailsButton.setText("Show Details") ; } pack() ; } } } ; //---------- /** * Get the text that would be printed to System.err * if e.printStackTrace() was called, as a String. * * @param e the Throwable to get the stack trace String of * @return the String description of the stack trace */ public static String getExceptionStackTrace(Throwable e) { StringBuffer s = new StringBuffer() ; // Borrowed this code from Throwable.printStackTrace s.append(e + "\n") ; StackTraceElement[] trace = e.getStackTrace() ; for (int i = 0 ; i < trace.length ; i++) s.append("\tat " + trace[i] + "\n") ; Throwable ourCause = e.getCause() ; if (ourCause != null) appendStackTraceAsCause(ourCause, trace, s) ; return s.toString() ; } private static void appendStackTraceAsCause(Throwable e, StackTraceElement[] causedTrace, StringBuffer s) { // Borrowed this code from Throwable.printStackTraceAsCause StackTraceElement[] trace = e.getStackTrace() ; int m = trace.length - 1, n = causedTrace.length - 1 ; while (m >= 0 && n >= 0 && trace[m].equals(causedTrace[n])) { m-- ; n-- ; } int framesInCommon = trace.length - 1 - m ; s.append("Caused by: " + e + "\n") ; for (int i = 0 ; i <= m ; i++) s.append("\tat " + trace[i] + "\n") ; if (framesInCommon != 0) s.append("\t... " + framesInCommon + " more\n") ; Throwable ourCause = e.getCause() ; if (ourCause != null) appendStackTraceAsCause(ourCause, trace, s) ; } /** * Display an error dialog. * * @param baseException the exception on which to base the dialog * @param owner the owner of the exception dialog (can be null) * @param title the title of the dialog * @param errorMessage the error message to display on the dialog * @throws NullPointerException if either baseException, title or errorMessage is null */ public static void showDialog(Exception baseException, Frame owner, String title, String errorMessage) { if (baseException == null || title == null || errorMessage == null) { throw new NullPointerException() ; } new JExceptionDialog(baseException, owner, title, errorMessage, "OK").setVisible(true) ; } /** * Display an error dialog, using the default title and error message. * * @param baseException the exception on which to base the dialog * @param owner the owner of the exception dialog (can be null) * @throws NullPointerException if either argument is null */ public static void showDialog(Exception baseException, Frame owner) { showDialog(baseException, owner, defaultTitle, defaultErrorMessage) ; } /** * Display an error dialog for a fatal error, and exit. * * @param baseException the exception on which to base the dialog * @param owner the owner of the exception dialog (can be null) * @param title the title of the dialog * @param errorMessage the error message to display on the dialog * @param errorCode the error code to exit with * @throws NullPointerException if either baseException, title or errorMessage is null */ public static void showFatalDialog(Exception baseException, Frame owner, String title, String errorMessage, int errorCode) { if (baseException == null || title == null || errorMessage == null) { throw new NullPointerException() ; } new JExceptionDialog(baseException, owner, title, errorMessage, "Exit").setVisible(true) ; System.exit(errorCode) ; } /** * Display an error dialog for a fatal error, and exit, using the default title, error message, * and an error code of -1. * * @param baseException the exception on which to base the dialog * @param owner the owner of the exception dialog (can be null) * @throws NullPointerException if either argument is null */ public static void showFatalDialog(Exception baseException, Frame owner) { showFatalDialog(baseException, owner, defaultTitle, defaultFatalErrorMessage, -1) ; }}