com.windowtester.eclipse.ui.dialogs.ExceptionDetailsDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.windowtester.eclipse.ui.dialogs.ExceptionDetailsDialog.java

Source

/*******************************************************************************
 *  Copyright (c) 2012 Google, Inc.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *  
 *  Contributors:
 *  Google, Inc. - initial API and implementation
 *******************************************************************************/
package com.windowtester.eclipse.ui.dialogs;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.windowtester.eclipse.ui.image.DialogImage;

/**
 * A dialog to display an error message, 
 * product and provider information,
 * plus the details of the exception itself.
 * A details button shows or hides an error details viewer.
 */
public class ExceptionDetailsDialog extends AbstractDetailsDialog {

    /**
     * The details to be shown
     * ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     */
    private final Object details;

    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructors
    //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Creates a dialog showing the specified message and exception.
     * Note that the dialog will have no visual representation (no widgets)
     * until it is told to open.
     * 
     * @param parentShell the shell under which to create this dialog
     * @param title the title to use for this dialog,
     *      or <code>null</code> to indicate that the default title should be used
     * @param message the dialog message (not null)
     * @param details the details to be displayed.
     *       ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     */
    public ExceptionDetailsDialog(Shell parentShell, String title, String message, Object details) {
        this(parentShell, title, getDialogImage(details), message, details);
    }

    /**
     * Creates a dialog showing the specified message and exception.
     * Note that the dialog will have no visual representation (no widgets)
     * until it is told to open.
     * 
     * @param parentShell the shell under which to create this dialog
     * @param title the title to use for this dialog,
     *      or <code>null</code> to indicate that the default title should be used
     * @param image the image to appear to the left of the dialog
     *       or <code>null</code> for no image
     * @param message the dialog message (not null)
     * @param details the details to be displayed
     *       ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     */
    public ExceptionDetailsDialog(Shell parentShell, String title, DialogImage image, String message,
            Object details) {
        this(parentShell, title, image != null ? image.getImage() : null, message, details);
    }

    /**
     * Creates a dialog showing the specified message and exception.
     * Note that the dialog will have no visual representation (no widgets)
     * until it is told to open.
     * 
     * @param parentShell the shell under which to create this dialog
     * @param title the title to use for this dialog,
     *      or <code>null</code> to indicate that the default title should be used
     * @param image the image to appear to the left of the dialog
     *       or <code>null</code> for no image
     * @param message the dialog message
     * @param details the details to be displayed
     *       ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     */
    public ExceptionDetailsDialog(Shell parentShell, String title, Image image, String message, Object details) {
        super(parentShell, getTitle(title, details), image, getMessage(message, details));
        this.details = details;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // UI creation and event handling
    //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Create the details area with content.
     * 
     * @param parent the parent of the details area
     * @return the details area
     * 
     */
    protected Control createDetailsArea(Composite parent) {

        // create the details area
        Composite panel = new Composite(parent, SWT.NONE);
        panel.setLayoutData(new GridData(GridData.FILL_BOTH));
        GridLayout layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        panel.setLayout(layout);

        // create the details content
        createProductInfoArea(panel);
        createDetailsViewer(panel);

        return panel;
    }

    /**
     * Create the product information area
     * 
     * @param parent the parent of the product information area
     * @return the product information area
     */
    protected Composite createProductInfoArea(Composite parent) {
        Composite composite = new Composite(parent, SWT.NULL);
        composite.setLayoutData(new GridData());
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        composite.setLayout(layout);

        new Label(composite, SWT.NONE).setText("Provider:");
        new Label(composite, SWT.NONE).setText("Google, Inc.");
        new Label(composite, SWT.NONE).setText("Plug-in Name:");
        new Label(composite, SWT.NONE).setText("WindowTester-Pro");
        //      new Label(composite, SWT.NONE).setText("Plug-in ID:");
        //      new Label(composite, SWT.NONE).setText(product.getPluginId());
        //      new Label(composite, SWT.NONE).setText("Version:");
        //      new Label(composite, SWT.NONE).setText(product.getVersion().toString());

        return composite;
    }

    /**
     * Create the details viewer with content.
     * 
     * @param parent the parent of the details viewer
     * @return the details viewer or <code>null</code> if none created
     */
    protected Control createDetailsViewer(Composite parent) {
        if (details == null)
            return null;

        Text text = new Text(parent, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        text.setLayoutData(new GridData(GridData.FILL_BOTH));

        // Create the content
        StringWriter writer = new StringWriter(1000);
        if (details instanceof Throwable)
            appendException(new PrintWriter(writer), (Throwable) details);
        else if (details instanceof IStatus)
            appendStatus(new PrintWriter(writer), (IStatus) details, 0);
        text.setText(writer.toString());

        return text;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Utility
    //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Answer the title.
     * 
     * @param title the title or <code>null</code>
     * @param details the details to be displayed
     *       ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     * @return the title (not <code>null</code>)
     */
    public static String getTitle(String title, Object details) {
        if (title != null)
            return title;
        if (details instanceof Throwable) {
            Throwable e = (Throwable) details;
            while (e instanceof InvocationTargetException)
                e = ((InvocationTargetException) e).getTargetException();
            String name = e.getClass().getName();
            return name.substring(name.lastIndexOf('.') + 1);
        }
        return "Exception";
    }

    /**
     * Answer the image for the specified level of detail.
     * 
     * @param details the details to be displayed.
     *       ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     * @return the dialog image
     */
    public static DialogImage getDialogImage(Object details) {
        if (details instanceof IStatus) {
            switch (((IStatus) details).getSeverity()) {
            case IStatus.ERROR:
                return DialogImage.ERROR;
            case IStatus.WARNING:
                return DialogImage.WARNING;
            case IStatus.INFO:
                return DialogImage.INFO;
            case IStatus.OK:
                return null;
            }
        }
        return DialogImage.ERROR;
    }

    /**
     * Answer the message.
     * 
     * @param message the message or <code>null</code>
     * @param details the details to be displayed
     *       ({@link Exception}, {@link IStatus}, or <code>null</code> if no details)
     * @return the message (not <code>null</code>)
     */
    public static String getMessage(String message, Object details) {
        if (details instanceof Throwable) {
            Throwable e = (Throwable) details;
            while (e instanceof InvocationTargetException)
                e = ((InvocationTargetException) e).getTargetException();
            if (message == null)
                return e.toString();
            return MessageFormat.format(message, new Object[] { e.toString() });
        }
        if (details instanceof IStatus) {
            String statusMessage = ((IStatus) details).getMessage();
            if (message == null)
                return statusMessage;
            return MessageFormat.format(message, new Object[] { statusMessage });
        }
        if (message != null)
            return message;
        return "An Exception occurred.";
    }

    /**
     * Append the exception information to the writer.
     * 
     * @param writer the writer to contain the stack trace
     * @param ex the exception
     */
    public static void appendException(PrintWriter writer, Throwable ex) {
        if (ex instanceof CoreException) {
            appendStatus(writer, ((CoreException) ex).getStatus(), 0);
            writer.println();
        }
        appendStackTrace(writer, ex);
        if (ex instanceof InvocationTargetException)
            appendException(writer, ((InvocationTargetException) ex).getTargetException());
    }

    /**
     * Append the status information to the writer.
     * 
     * @param writer the writer to contain the stack trace
     * @param status the status object
     * @param nesting the indent level
     */
    public static void appendStatus(PrintWriter writer, IStatus status, int nesting) {
        for (int i = 0; i < nesting; i++)
            writer.print("  "); //$NON-NLS-1$
        writer.println(status.getMessage());
        IStatus[] children = status.getChildren();
        for (int i = 0; i < children.length; i++)
            appendStatus(writer, children[i], nesting + 1);
    }

    /**
     * Append the stack trace for the specified exception to the writer.
     * 
     * @param writer the writer to contain the stack trace
     * @param ex the exception
     */
    public static void appendStackTrace(PrintWriter writer, Throwable ex) {
        ex.printStackTrace(writer);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Testing
    //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Test this dialog
     */
    public static void test() {
        new ExceptionDetailsDialog(null, "Test without exception", DialogImage.ERROR, //$NON-NLS-1$
                "Test this dialog with a null exception", null).open(); //$NON-NLS-1$
        new ExceptionDetailsDialog(null, null, (Image) null, null, null).open();
        try {
            throw new RuntimeException("Test " + ExceptionDetailsDialog.class.getName()); //$NON-NLS-1$
        } catch (Exception e) {
            new ExceptionDetailsDialog(null, "Test with exception", DialogImage.ERROR, //$NON-NLS-1$
                    "Test this dialog with an exception.  The exception is {0}", e).open(); //$NON-NLS-1$
            new ExceptionDetailsDialog(null, null, DialogImage.ERROR, null, e).open();
            try {
                throw new InvocationTargetException(e);
            } catch (Exception e2) {
                new ExceptionDetailsDialog(null, null, DialogImage.ERROR, null, e2).open();
            }
        }
    }

    /**
     * Answer an action to test this dialog.
     * 
     * @return the test action
     */
    public static IAction getTestAction() {
        return new Action("Test " + ExceptionDetailsDialog.class.getName()) {
            public void run() {
                test();
            }

        };
    }
}