org.jboss.tools.common.model.ui.reporting.ReportProblemWizard.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.common.model.ui.reporting.ReportProblemWizard.java

Source

/*******************************************************************************
 * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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:
 *     Exadel, Inc. and Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.common.model.ui.reporting;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.Collator;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.about.ISystemSummarySection;
import org.eclipse.ui.internal.IWorkbenchConstants;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.jboss.tools.common.CommonPlugin;
import org.jboss.tools.common.meta.action.XActionInvoker;
import org.jboss.tools.common.meta.action.XEntityData;
import org.jboss.tools.common.meta.action.impl.XEntityDataImpl;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.options.PreferenceModelUtilities;
import org.jboss.tools.common.model.ui.ModelUIImages;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
import org.jboss.tools.common.model.ui.attribute.XAttributeSupport;
import org.jboss.tools.common.model.ui.attribute.adapter.IModelPropertyEditorAdapter;
import org.jboss.tools.common.model.ui.messages.UIMessages;
import org.jboss.tools.common.model.ui.widgets.ReferenceListener;
import org.jboss.tools.common.model.ui.widgets.TextAndReferenceComponent;
import org.jboss.tools.common.model.ui.wizards.query.AbstractQueryWizard;
import org.jboss.tools.common.model.ui.wizards.query.AbstractQueryWizardView;
import org.jboss.tools.common.reporting.ProblemReportingHelper;

public class ReportProblemWizard extends AbstractQueryWizard {

    public ReportProblemWizard() {
        setView(new ReportProblemWizardView());
        getView().setMessage(UIMessages.REPORT_PROBLEM_DESCRIPTION);
    }

}

/**
 * @author yukhovich
 *
 */
class ReportProblemWizardView extends AbstractQueryWizardView {
    /** LOG_DATE_FORMAT */
    final private static SimpleDateFormat LOG_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); //$NON-NLS-1$

    final private static SimpleDateFormat CURENT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$

    final private static SimpleDateFormat SESSION_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); //$NON-NLS-1$

    final private static long TWENTY_FOUR_HOURS = 86400000;

    /** log file name */
    private Text logFileName;

    /** Browse button */
    private Button browseButton;

    /** LINE_LIMIT */
    final private static int LINE_LIMIT = 70;

    int stackTracesCount;
    Text problemDescription;
    XAttributeSupport sendSupport;
    XAttributeSupport infoSupport;

    XModelObject reportOptions = PreferenceModelUtilities.getPreferenceModel()
            .getByPath(ReportPreference.OPTIONS_REPORT_PROBLEM_PATH);

    XModelObject exceptionsObject = PreferenceModelUtilities.getPreferenceModel()
            .createModelObject("ProblemBufferEditor", null); //$NON-NLS-1$

    XEntityData sendData = XEntityDataImpl.create(new String[][] { { "SharableReportProblem" }, //$NON-NLS-1$
            { ReportPreference.ATT_ATTACH_REDHAT_LOG, "no" }, //$NON-NLS-1$
            // {ReportPreference.ATT_ATTACH_ECLIPSE_LOG, "no"}
    });
    XEntityData sendData2 = XEntityDataImpl.create(new String[][] { { "SharableReportProblem" }, //$NON-NLS-1$
            // {ReportPreference.ATT_ATTACH_ECLIPSE_LOG, "no"}
    });
    XEntityData infoData = XEntityDataImpl
            .create(new String[][] { { "SharableReportProblem" }, { ReportPreference.ATT_E_MAIL, "no" }, //$NON-NLS-1$ //$NON-NLS-2$
                    { ReportPreference.ATT_OTHER, "no" } }); //$NON-NLS-1$

    class PixelConverter {

        private FontMetrics fFontMetrics;

        public PixelConverter(Control control) {
            GC gc = new GC(control);
            gc.setFont(control.getFont());
            fFontMetrics = gc.getFontMetrics();
            gc.dispose();
        }

        /**
         * @see DialogPage#convertHorizontalDLUsToPixels
         */
        public int convertHorizontalDLUsToPixels(int dlus) {
            return Dialog.convertHorizontalDLUsToPixels(fFontMetrics, dlus);
        }

        /**
         * @see DialogPage#convertWidthInCharsToPixels
         */
        public int convertWidthInCharsToPixels(int chars) {
            return Dialog.convertWidthInCharsToPixels(fFontMetrics, chars);
        }
    }

    public ReportProblemWizardView() {
        //folderLogFileName = Platform.getLocation().toOSString() + SEPARATOR;
        setTitleImage(ModelUIImages.getImage(ModelUIImages.REPORT_PROBLEM_IMAGE));
    }

    public Control createControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        Layout layout = new GridLayout();
        composite.setLayout(layout);
        createFilenameLogControl(composite);
        createStackTracesControl(composite);
        createProblemControl(composite);
        createContactInfoControl(composite);

        initializeData();

        return composite;
    }

    /* (non-Javadoc)
     * @see org.jboss.tools.common.model.ui.wizards.query.AbstractQueryWizardView#updateBar()
     */
    public void updateBar() {
        getCommandBar().setEnabled(OK, !isMessageEmpty());
    }

    void validate() {
        if (problemDescription == null || problemDescription.isDisposed())
            return;
        String text = problemDescription.getText();
        if (text == null || text.trim().length() == 0) {
            setErrorMessage(UIMessages.REPORT_PROBLEM_NO_DESCRIPTION);
        } else {
            setErrorMessage(null);
            setMessage(UIMessages.REPORT_PROBLEM_DESCRIPTION);
        }
    }

    /* (non-Javadoc)
     * @see org.jboss.tools.common.model.ui.wizards.query.AbstractQueryWizardView#getPreferredSize()
     */
    public Point getPreferredSize() {
        return new Point(750, 500);
    }

    /* (non-Javadoc)
     * @see org.jboss.tools.common.model.ui.wizards.query.AbstractQueryWizardView#getCommands()
     */
    public String[] getCommands() {
        return new String[] { OK, CANCEL };
    }

    /* (non-Javadoc)
     * @see org.jboss.tools.common.model.ui.wizards.query.AbstractQueryWizardView#action(java.lang.String)
     */
    public void action(String command) {
        if (command.equals(OK)) {
            submitProblems();
            super.action(OK);
        } else {
            super.action(command);
        }
    }

    /**
     * 
     */
    private void initializeData() {
        File defaultLocation = new File(Platform.getLocation().toFile(), getDefaultZipFilename());
        logFileName.setText(defaultLocation.toString());
    }

    /**
     * @return
     */
    private byte[] getEclipseLogContent() {
        StringBuilder sb = new StringBuilder();
        String location = Platform.getLogFileLocation().toOSString();
        File f = new File(location);
        if (!f.isFile())
            return sb.toString().getBytes();

        InputStreamReader in = null;
        try {
            in = new FileReader(location);

            char[] tempBuffer = new char[512];
            int len = 0;
            while ((len = in.read(tempBuffer)) != -1) {
                sb.append(tempBuffer);
            }

        } catch (IOException e) {
            ModelUIPlugin.getPluginLog().logError(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception ignore) {
                    //Ignore
                }
            }
        }

        return getLogByCurentDate(sb.toString()).getBytes();
    };

    private String getLogByCurentDate(String log) {
        String lastOldSession = ""; //$NON-NLS-1$
        boolean isAccept = false;
        Date today = new Date();

        StringBuffer sb = new StringBuffer();
        StringTokenizer st = new StringTokenizer(log, "\n", true); //$NON-NLS-1$
        while (st.hasMoreTokens()) {
            String t = st.nextToken();
            if (t.startsWith("!SESSION")) { //$NON-NLS-1$
                String dateString = t.substring(9, 25);
                try {
                    Date date = SESSION_DATE_FORMAT.parse(dateString);
                    long delta = today.getTime() - date.getTime();
                    if (delta < TWENTY_FOUR_HOURS) {
                        if (!isAccept)
                            sb.append(lastOldSession + "\n"); //$NON-NLS-1$
                        sb.append(t);
                        isAccept = true;
                    } else {
                        lastOldSession = new String(t);
                        isAccept = false;
                    }
                } catch (ParseException ex) {
                    //ModelUIPlugin.getPluginLog().logError(ex);
                    sb.append(t);
                    isAccept = true;
                }
            } else {
                if (isAccept) {
                    sb.append(t);
                }
            }
        }
        return sb.toString();
    }

    /**
     * @return
     */
    private byte[] getUserCommentContent() {
        StringBuffer sb = new StringBuffer();

        sb = sb.append("email : ").append( //$NON-NLS-1$
                ReportPreference.E_MAIL_OPTION.getValue()).append("\n"); //$NON-NLS-1$
        sb = sb.append("description : ").append(problemDescription.getText()) //$NON-NLS-1$
                .append("\n"); //$NON-NLS-1$
        sb.append("other : ").append(ReportPreference.OTHER_OPTION.getValue()) //$NON-NLS-1$
                .append("\n"); //$NON-NLS-1$

        return sb.toString().getBytes();
    }

    /**
     * @return
     */
    private byte[] getEclipsePropertiesContent() {
        StringWriter out = new StringWriter();
        PrintWriter writer = new PrintWriter(out);
        writer.println(NLS.bind(WorkbenchMessages.SystemSummary_timeStamp,
                DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date())));

        appendExtensions(writer);
        writer.close();
        return out.toString().getBytes();
    }

    /**
     * create a ZIP file contain following files: 
     */
    private void createZipFile() throws IOException {

        File zipFilename = new File(logFileName.getText());

        ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipFilename));
        try {
            addFileToZip(getEclipseLogContent(), "eclipse.log", zout); //$NON-NLS-1$
            addFileToZip(getUserCommentContent(), "usercomment.txt", zout); //$NON-NLS-1$
            addFileToZip(getEclipsePropertiesContent(), "eclipse.properties", zout); //$NON-NLS-1$

            ModelUIPlugin.getDefault().logInfo("Wrote diagnostic info to " + zipFilename); //$NON-NLS-1$
        } finally {
            zout.close();
        }
    }

    /**
     * Add bytes form tempBuffer in zipOutputStream with name from fileName
     * @param tempBuffer tempolary-buffer
     * @param fileName
     * @param zout
     * @throws IOException
     */
    private void addFileToZip(byte[] tempBuffer, String fileName, ZipOutputStream zout) throws IOException {

        ZipEntry e = new ZipEntry(fileName);
        zout.putNextEntry(e);
        zout.write(tempBuffer, 0, tempBuffer.length);
        zout.closeEntry();
    }

    /**
     * Get a filename for zip-file
     * 
     * @return filename for zip-file
     */
    private String getDefaultZipFilename() {
        String currentDate;
        Date today = new Date();

        currentDate = LOG_DATE_FORMAT.format(today);
        return "jbosstools-diagnostics-" + currentDate.toString() + ".zip"; //$NON-NLS-1$ //$NON-NLS-2$
    }

    private void createStackTracesControl(Composite parent) {
        stackTracesCount = ProblemReportingHelper.buffer.getSize();
        exceptionsObject.setAttributeValue("exceptions", //$NON-NLS-1$
                formatContent(ProblemReportingHelper.buffer.getContent()));
        XEntityData data = (stackTracesCount > 0) ? sendData : sendData2;
        boolean isSeparatorNeeded = false;
        if (stackTracesCount > 0) {
            createStackTracesLabelControl(parent);
            isSeparatorNeeded = true;
        }
        if (data.getAttributeData().length > 0) {
            sendSupport = new XAttributeSupport(reportOptions, data, true);
            sendSupport.setAutoStore(false);
            GridLayout layout = getDefaultSupportLayout();
            layout.marginWidth = 10;
            sendSupport.setLayout(layout);
            sendSupport.createControl(parent);
            sendSupport.addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent evt) {
                    updateBar();
                }
            });
            isSeparatorNeeded = true;
        } else {
            sendSupport = null;
        }
        if (isSeparatorNeeded) {
            Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
            separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        }
    }

    /**
     * 
     * @param parent
     *            a parent Composite object
     */
    private void createFilenameLogControl(final Composite parent) {
        Group g = new Group(parent, SWT.SHADOW_ETCHED_IN);
        g.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));

        GridLayout layout = new GridLayout(3, false);
        g.setLayout(layout);

        createLabel(g, "Log file name", 1);
        logFileName = createSingleText(g, 1);
        browseButton = createPushButton(g, "&Browse...", null);

        browseButton.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
                widgetSelected(e);
            }

            public void widgetSelected(SelectionEvent e) {
                FileDialog fileDialog = new FileDialog(parent.getShell(), SWT.SAVE);
                fileDialog.setText("Save");

                File fileName = new File(logFileName.getText());

                fileDialog.setFilterPath(fileName.getParent());
                fileDialog.setFileName(fileName.getName());

                String[] filterExt = { "*.zip" }; //$NON-NLS-1$
                fileDialog.setFilterExtensions(filterExt);
                String selected = fileDialog.open();

                if (selected != null) {
                    logFileName.setText(selected);
                }
            };

        });
    }

    private void createProblemControl(Composite parent) {
        Group g = new Group(parent, SWT.SHADOW_ETCHED_IN);
        g.setText("Problem Description");
        g.setLayoutData(new GridData(GridData.FILL_BOTH));
        g.setLayout(new GridLayout());
        problemDescription = new Text(g, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        problemDescription.setLayoutData(new GridData(GridData.FILL_BOTH));
        problemDescription.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                validate();
                updateBar();
            }
        });
    }

    private void createContactInfoControl(Composite parent) {
        Group g = new Group(parent, SWT.SHADOW_ETCHED_IN);
        g.setText("Contact Information (optional)");
        g.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        g.setLayout(new GridLayout());
        infoSupport = new XAttributeSupport(reportOptions, infoData, true);
        infoSupport.setAutoStore(false);
        infoSupport.setLayout(getDefaultSupportLayout());
        Control c = infoSupport.createControl(g);
        c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        infoSupport.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                validate();
            }
        });
    }

    private void createStackTracesLabelControl(Composite parent) {
        Composite panel = new Composite(parent, SWT.NONE);
        GridLayout layout = getDefaultSupportLayout();
        layout.marginWidth = 10;
        panel.setLayout(layout);
        Label image = new Label(panel, SWT.NONE);
        image.setImage(ModelUIImages.getImage("warning.gif")); //$NON-NLS-1$
        GridData d = new GridData();
        d.widthHint = 16;
        image.setLayoutData(d);
        image.setLayoutData(new GridData());
        TextAndReferenceComponent t2 = new TextAndReferenceComponent(panel, SWT.NONE);
        d = new GridData(GridData.FILL_HORIZONTAL);
        d.horizontalIndent = 5;
        t2.setLayoutData(d);
        String text = "You have " + stackTracesCount + " stack traces to send (<a>see details</a>).";
        t2.setText(text, 300);
        t2.addReferenceListener(new ReferenceListener() {
            public void referenceSelected(String reference) {
                XActionInvoker.invoke("EditActions.Edit", exceptionsObject, //$NON-NLS-1$
                        null);
            }
        });
    }

    private void submitProblems() {
        if (sendSupport != null)
            sendSupport.store();
        if (infoSupport != null)
            infoSupport.store();
        String text = CommonPlugin.getEnvironment() + "\n" //$NON-NLS-1$
                + problemDescription.getText();
        boolean addRedHatLog = "yes" //$NON-NLS-1$
                .equals(ReportPreference.ATTACH_REDHAT_LOG_OPTION.getValue());
        if (addRedHatLog && stackTracesCount > 0) {
            String log = exceptionsObject.getAttributeValue("exceptions"); //$NON-NLS-1$
            text += "\n----------Red Hat Log-----------\n" + log + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
        }
        boolean addEclipseLog = "yes" //$NON-NLS-1$
                .equals(ReportPreference.ATTACH_ECLIPSE_LOG_OPTION.getValue());
        if (addEclipseLog) {
            String eclipseLog = ProblemReportingHelper.buffer.getEclipseLogContent();
            text += "\n----------Eclipse Log----------\n" + eclipseLog + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
        }
        /*
        String email = ReportPreference.E_MAIL_OPTION.getValue();
        String other = ReportPreference.OTHER_OPTION.getValue();
        */
        try {
            createZipFile();
            // Submit.getInstance().submit(reportText, addRedHatLog);
            // ProblemReportingHelper.buffer.report(text, email, other,
            // addRedHatLog);
            showConfirmDialog();
        } catch (IOException e) {
            ModelUIPlugin.getPluginLog().logError(e);
        }

        if (addRedHatLog) {
            // clean is to be done after report,
            // which is executed as background job.
            // ProblemReportingHelper.buffer.clean();
        }
    }

    private void showConfirmDialog() {
        final String filename = logFileName.getText();
        String message = NLS.bind(UIMessages.REPORT_PROBLEM_RESULT, filename);

        MessageDialog dialog = new MessageDialog(problemDescription.getShell(), "Info", null, message,
                MessageDialog.INFORMATION, new String[] { UIMessages.REPORT_PROBLEM_COPY_BUTTON, "Close" }, 1) {
            protected void buttonPressed(int buttonId) {
                if (buttonId == 0) {
                    Clipboard clipboard = new Clipboard(problemDescription.getShell().getDisplay());
                    try {
                        clipboard.setContents(new String[] { filename },
                                new Transfer[] { TextTransfer.getInstance() });
                    } finally {
                        clipboard.dispose();
                    }
                }
                super.buttonPressed(buttonId);
            }
        };
        dialog.open();
    }

    private String formatContent(String content) {
        StringBuffer sb = new StringBuffer();
        StringTokenizer st = new StringTokenizer(content, "\n", true); //$NON-NLS-1$
        while (st.hasMoreTokens()) {
            String t = st.nextToken();
            if ("\n".equals(t)) { //$NON-NLS-1$
                sb.append(t);
            } else {
                while (t.length() > LINE_LIMIT) {
                    String t1 = t.substring(0, LINE_LIMIT);
                    int i = t1.lastIndexOf(' ');
                    if (i > 40)
                        t1 = t1.substring(0, i);
                    t = t.substring(t1.length());
                    sb.append(t1).append("\n"); //$NON-NLS-1$
                }
                sb.append(t);
            }
        }
        return sb.toString();
    }

    /**
     * 
     * @return
     */
    private boolean isMessageEmpty() {
        if (sendSupport != null) {
            IModelPropertyEditorAdapter a = sendSupport
                    .getPropertyEditorAdapterByName(ReportPreference.ATT_ATTACH_REDHAT_LOG);
            if (a != null && "yes".equals(a.getValue())) //$NON-NLS-1$
                return false;
            a = sendSupport.getPropertyEditorAdapterByName(ReportPreference.ATT_ATTACH_ECLIPSE_LOG);
            if (a != null && "yes".equals(a.getValue())) //$NON-NLS-1$
                return false;
        }
        String text = problemDescription.getText();
        if (text == null || text.trim().length() == 0)
            return true;
        return false;
    }

    /**
     * Creates a new label widget
     * 
     * @param parent
     *            the parent composite to add this label widget to
     * @param text
     *            the text for the label
     * @param hspan
     *            the horizontal span to take up in the parent composite
     * @return the new label
     */
    private Label createLabel(Composite parent, String text, int hspan) {
        Label l = new Label(parent, SWT.NONE);
        l.setFont(parent.getFont());
        l.setText(text);
        GridData gd = new GridData();
        gd.horizontalSpan = hspan;
        l.setLayoutData(gd);
        return l;
    }

    /**
     * Creates a new text widget
     * 
     * @param parent
     *            the parent composite to add this text widget to
     * @param hspan
     *            the horizontal span to take up on the parent composite
     * @return the new text widget
     */
    private Text createSingleText(Composite parent, int hspan) {
        Text t = new Text(parent, SWT.SINGLE | SWT.BORDER);
        t.setFont(parent.getFont());
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = hspan;
        gd.widthHint = 100;
        t.setLayoutData(gd);
        return t;
    }

    /**
     * Returns a width hint for a button control.
     */
    private int getButtonWidthHint(Button button) {
        button.setFont(JFaceResources.getDialogFont());
        PixelConverter converter = new PixelConverter(button);
        int widthHint = converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
    }

    /**
     * Sets width and height hint for the button control. <b>Note:</b> This is
     * a NOP if the button's layout data is not an instance of
     * <code>GridData</code>.
     * 
     * @param the
     *            button for which to set the dimension hint
     */
    private void setButtonDimensionHint(Button button) {
        Object gd = button.getLayoutData();
        if (gd instanceof GridData) {
            ((GridData) gd).widthHint = getButtonWidthHint(button);
            ((GridData) gd).horizontalAlignment = GridData.FILL;
        }
    }

    /**
     * Creates and returns a new push button with the given label and/or image.
     * 
     * @param parent
     *            parent control
     * @param label
     *            button label or <code>null</code>
     * @param image
     *            image or <code>null</code>
     * 
     * @return a new push button
     */
    private Button createPushButton(Composite parent, String label, Image image) {
        Button button = new Button(parent, SWT.PUSH);
        button.setFont(parent.getFont());
        if (image != null) {
            button.setImage(image);
        }
        if (label != null) {
            button.setText(label);
        }
        GridData gd = new GridData();
        button.setLayoutData(gd);
        setButtonDimensionHint(button);
        return button;
    }

    private IConfigurationElement[] getSortedExtensions() {
        IConfigurationElement[] configElements = Platform.getExtensionRegistry().getConfigurationElementsFor(
                PlatformUI.PLUGIN_ID, IWorkbenchRegistryConstants.PL_SYSTEM_SUMMARY_SECTIONS);

        Arrays.sort(configElements, new Comparator() {
            Collator collator = Collator.getInstance(Locale.getDefault());

            public int compare(Object a, Object b) {
                IConfigurationElement element1 = (IConfigurationElement) a;
                IConfigurationElement element2 = (IConfigurationElement) b;

                String id1 = element1.getAttribute("id"); //$NON-NLS-1$
                String id2 = element2.getAttribute("id"); //$NON-NLS-1$

                if (id1 != null && id2 != null && !id1.equals(id2)) {
                    return collator.compare(id1, id2);
                }

                String title1 = element1.getAttribute("sectionTitle"); //$NON-NLS-1$ 
                String title2 = element2.getAttribute("sectionTitle"); //$NON-NLS-1$

                if (title1 == null) {
                    title1 = ""; //$NON-NLS-1$
                }
                if (title2 == null) {
                    title2 = ""; //$NON-NLS-1$
                }

                return collator.compare(title1, title2);
            }
        });

        return configElements;
    }

    /*
     * Appends the contents of all extensions to the configurationLogSections
     * extension point.
     */
    private void appendExtensions(PrintWriter writer) {
        IConfigurationElement[] configElements = getSortedExtensions();
        for (int i = 0; i < configElements.length; ++i) {
            IConfigurationElement element = configElements[i];

            Object obj = null;
            try {
                obj = WorkbenchPlugin.createExtension(element, IWorkbenchConstants.TAG_CLASS);
            } catch (CoreException e) {
                WorkbenchPlugin.log("could not create class attribute for extension", //$NON-NLS-1$
                        e.getStatus());
            }

            writer.println();
            writer.println(
                    NLS.bind(WorkbenchMessages.SystemSummary_sectionTitle, element.getAttribute("sectionTitle"))); //$NON-NLS-1$

            if (obj instanceof ISystemSummarySection) {
                ISystemSummarySection logSection = (ISystemSummarySection) obj;
                logSection.write(writer);
            } else {
                writer.println(WorkbenchMessages.SystemSummary_sectionError);
            }
        }
    }

    protected GridLayout getDefaultSupportLayout() {
        GridLayout gridLayout = new GridLayout(2, false);
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        gridLayout.horizontalSpacing = 0;
        gridLayout.verticalSpacing = 5;
        return gridLayout;
    }

}