org.talend.designer.runtime.visualization.views.RuntimeGraphcsComposite.java Source code

Java tutorial

Introduction

Here is the source code for org.talend.designer.runtime.visualization.views.RuntimeGraphcsComposite.java

Source

// ============================================================================
//
// Copyright (C) 2006-2015 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.designer.runtime.visualization.views;

import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.talend.designer.runtime.visualization.Activator;
import org.talend.designer.runtime.visualization.IActiveJvm;
import org.talend.designer.runtime.visualization.JvmCoreException;
import org.talend.designer.runtime.visualization.JvmModel;
import org.talend.designer.runtime.visualization.JvmModelEvent;
import org.talend.designer.runtime.visualization.JvmModelEvent.State;
import org.talend.designer.runtime.visualization.ReportMessage;
import org.talend.designer.runtime.visualization.ReportMessageManager;
import org.talend.designer.runtime.visualization.MBean.IMBeanServer;
import org.talend.designer.runtime.visualization.MBean.IMBeanServerChangeListener;
import org.talend.designer.runtime.visualization.MBean.IMonitoredMXBeanAttribute;
import org.talend.designer.runtime.visualization.MBean.IMonitoredMXBeanGroup;
import org.talend.designer.runtime.visualization.MBean.IMonitoredMXBeanGroup.AxisUnit;
import org.talend.designer.runtime.visualization.MBean.MBeanServerEvent;
import org.talend.designer.runtime.visualization.internal.ui.IHelpContextIds;
import org.talend.designer.runtime.visualization.internal.ui.RefreshJob;
import org.talend.designer.runtime.visualization.internal.ui.properties.memory.GarbageAction;
import org.talend.designer.runtime.visualization.internal.ui.properties.timeline.LoadChartAction;
import org.talend.designer.runtime.visualization.internal.ui.properties.timeline.Messages;
import org.talend.designer.runtime.visualization.internal.ui.properties.timeline.MonitorAttributeName;
import org.talend.designer.runtime.visualization.internal.ui.properties.timeline.TimelineChart;

/**
 * created by ldong on Apr 7, 2015 Detailled comment
 *
 */
public class RuntimeGraphcsComposite extends AbstractRuntimeGraphcsComposite {

    /** The charts. */
    private List<TimelineChart> charts;

    /** The action to load chart set. */
    private LoadChartAction loadChartSetAction;

    /** The action to run garbage collector. */
    private GarbageAction garbageCollectorAction;

    /** The MBean server change listener. */
    private IMBeanServerChangeListener mBeanServerChangeListener;

    /** The charts page. */
    private Composite chartsPage;

    /** The message page. */
    private Composite messagePage;

    /** The report text filed. */
    private StyledText reportField;

    /** The information text filed. */
    private Text infoField;

    /** The report field. */
    private Composite reportComposite;

    /** The chart composite. */
    private Composite chartComposite;

    /** The information composite. */
    private Composite infoComposite;

    private static volatile RuntimeGraphcsComposite lastInstance;

    private ReportMessageManager messageManager;

    private static long lastAddTime = System.currentTimeMillis();

    public RuntimeGraphcsComposite(Composite parent, ISelection selection, int style) {
        super(parent, selection, style);
        charts = new ArrayList<TimelineChart>();
        loadChartSetAction = new LoadChartAction(this);
        garbageCollectorAction = new GarbageAction(this);
        setInput(selection);
        this.messageManager = ReportMessageManager.getInstance();
        synchronized (this) {
            if (lastInstance != null) {
                //didn't work. cause the instance's hashCode changed in the CopyOnWriteArrayList,check later.
                // System.out.println("from comp:" + lastInstance.hashCode());
                JvmModel.getInstance().removeJvmModelChangeListener(lastInstance);
            } else {
                lastInstance = this;
            }
        }
    }

    @Override
    protected void refresh() {
        refreshConnectionIndicator();
        refreshReportField();

        IActiveJvm jvm = getJvm();
        if (jvm == null || !jvm.isConnected() || isRefreshSuspended() || chartsPage.isDisposed()) {
            return;
        }

        for (TimelineChart chart : charts) {
            if (!chart.isDisposed() && chart.isVisible()) {
                chart.refresh();
            }
        }
    }

    private void refreshReportField() {
        long newAddTime = System.currentTimeMillis();
        if (newAddTime - lastAddTime < 10 * 1000) {
            return;
        }
        lastAddTime = newAddTime;
        IActiveJvm jvm = getJvm();
        List<IMonitoredMXBeanGroup> groups = jvm.getMBeanServer().getMonitoredAttributeGroups();

        for (IMonitoredMXBeanGroup group : groups) {
            if (group.getName().equals(MonitorAttributeName.HEAP_MEMORY)) {
                Number useHeapSize = 0;
                Number maxHeapSize = 0;
                Date lastDate = null;
                for (IMonitoredMXBeanAttribute attribute : group.getAttributes()) {
                    if (attribute.getAttributeName().equals(MonitorAttributeName.HEAP_MEMORY_USE)) {
                        List<Number> values = attribute.getValues();
                        List<Date> dates = attribute.getDates();
                        if (values.size() > 1) {
                            useHeapSize = values.get(values.size() - 1);
                            lastDate = dates.get(dates.size() - 1);
                        }
                    } else if (attribute.getAttributeName().equals(MonitorAttributeName.HEAP_MEMORY_SIZE)) {
                        List<Number> values = attribute.getValues();
                        List<Date> dates = attribute.getDates();
                        if (values.size() > 1) {
                            maxHeapSize = values.get(values.size() - 1);
                            lastDate = dates.get(dates.size() - 1);
                        }
                    }
                }
                if (lastDate != null) {
                    if (isRightPercentage(maxHeapSize, useHeapSize)) {
                        //                       setNormalReport(lastDate);
                    } else {
                        setWarningReport(lastDate);
                    }
                }
            }
        }
    }

    private boolean isRightPercentage(Number max, Number use) {
        double fixedPercent = 0.8;
        boolean isRightMemmory = false;
        if (max instanceof Integer) {
            isRightMemmory = (Integer) max * fixedPercent > (Integer) use;
        } else if (max instanceof Long) {
            isRightMemmory = (Long) max * fixedPercent > (Long) use;
        } else if (max instanceof Double) {
            isRightMemmory = (Double) max * fixedPercent > (Double) use;
        }
        return isRightMemmory;
    }

    private synchronized void setWarningReport(Date lastDate) {
        if (messageManager != null) {
            StringBuilder finalContent = new StringBuilder();
            finalContent.append(Messages.memoryWarningMsg);
            finalContent.append(" "); //$NON-NLS-1$
            finalContent.append(new SimpleDateFormat("hh:mm:ss a MM/dd/yyyy").format(lastDate)); //$NON-NLS-1$
            finalContent.append(System.getProperty("line.seperator")); //$NON-NLS-1$
            messageManager.setWarningMessage(finalContent.toString(), getDisplay().getSystemColor(SWT.COLOR_RED),
                    getDisplay().getSystemColor(SWT.COLOR_WHITE));
        }
        displayReportField();
    }

    public void displayReportField() {
        if (reportField != null && !reportField.isDisposed()) {
            if (messageManager == null) {
                return;
            }
            UnboundedFifoBuffer messages = messageManager.getMessages();
            Iterator iterator = messages.iterator();
            StringBuilder content = new StringBuilder();
            StyleRange[] styleRanges = new StyleRange[messages.size()];
            int i = 0;
            while (iterator.hasNext()) {
                ReportMessage message = (ReportMessage) iterator.next();
                content.append(message.getContent());
                styleRanges[i++] = message.getType();
            }
            reportField.setText(content.toString());
            reportField.setStyleRanges(styleRanges);
            //            reportField.setForeground(new Color(Display.getDefault(), 255, 0, 0));
            reportField.setTopIndex(Integer.MAX_VALUE);
        }
    }

    private void setNormalReport(Date lastDate) {
        if (reportField != null && !reportField.isDisposed()) {
            StringBuilder finalContent = new StringBuilder();
            finalContent.append(reportField.getText());
            finalContent.append(System.getProperty("line.seperator")); //$NON-NLS-1$
            finalContent.append(Messages.memoryNormalMsg);
            finalContent.append(" "); //$NON-NLS-1$
            finalContent.append(lastDate.toString());
            reportField.setText(finalContent.toString());
            reportField.setForeground(new Color(Display.getDefault(), 0, 0, 0));
            reportField.setTopIndex(Integer.MAX_VALUE);
        }
    }

    @Override
    public void jvmModelChanged(JvmModelEvent event) {
        super.jvmModelChanged(event);

        if (event.state == State.JvmConnected && !chartsPage.isDisposed()) {
            final IActiveJvm newJvm = (IActiveJvm) event.jvm;
            Display.getDefault().asyncExec(new Runnable() {

                @Override
                public void run() {
                    reconstructCharts(newJvm, true);
                }
            });
            newJvm.getMBeanServer().addServerChangeListener(mBeanServerChangeListener);
        }
    }

    @Override
    protected void setInput(ISelection selection, IActiveJvm newJvm, IActiveJvm oldJvm) {
        if (newJvm == null || newJvm.equals(oldJvm)) {
            return;
        }

        reconstructCharts(newJvm, false);

        if (oldJvm != null && mBeanServerChangeListener != null) {
            IMBeanServer server = oldJvm.getMBeanServer();
            if (server != null) {
                server.removeServerChangeListener(mBeanServerChangeListener);
            }
        }

        newJvm.getMBeanServer().addServerChangeListener(mBeanServerChangeListener);
    }

    void reconstructCharts(IActiveJvm activeJvm, boolean connected) {
        if (chartsPage.isDisposed()) {
            return;
        }
        if (connected) {
            try {
                loadOverviewChartSet(activeJvm);
            } catch (JvmCoreException e) {
                Activator.log(Messages.configureMonitoredAttributesFailedMsg, e);
            }
        }

        List<IMonitoredMXBeanGroup> groups = activeJvm.getMBeanServer().getMonitoredAttributeGroups();

        if (groups.size() == 0) {
            return;
        }

        for (TimelineChart chart : charts) {
            chart.dispose();
        }
        charts.clear();

        if (chartComposite != null && !chartComposite.isDisposed()) {
            chartComposite.dispose();
        }

        chartComposite = new Composite(chartsPage, SWT.NONE);
        FormLayout chartLayout = new FormLayout();
        chartLayout.marginHeight = 0;
        chartLayout.marginWidth = 0;
        chartComposite.setLayout(chartLayout);
        FormData chartComData = new FormData();
        chartComData.top = new FormAttachment(0, 0);
        chartComData.bottom = new FormAttachment(100, 0);
        chartComData.left = new FormAttachment(0, 0);
        chartComData.right = new FormAttachment(100, 0);
        chartComposite.setLayoutData(chartComData);

        for (IMonitoredMXBeanGroup group : groups) {
            createSection(chartComposite, group);
        }

        createReportField(chartComposite);
        //      createInfoField(chartComposite);
        chartsPage.layout();
        chartsPage.setVisible(true);
        refresh();
    }

    private void loadOverviewChartSet(IActiveJvm activeJvm) throws JvmCoreException {
        final int[] blue = new int[] { 0, 255, 255 };
        final int[] red = new int[] { 255, 0, 0 };
        final int[] green = new int[] { 0, 255, 0 };
        final int[] lightgeen = new int[] { 128, 255, 0 };

        final int[] darkRed = new int[] { 255, 0, 128 };

        final int[] orange = new int[] { 255, 255, 0 };
        IMBeanServer server = activeJvm.getMBeanServer();
        server.getMonitoredAttributeGroups().clear();

        IMonitoredMXBeanGroup group = server.addMonitoredAttributeGroup(MonitorAttributeName.HEAP_MEMORY,
                AxisUnit.MBytes);

        group.addAttribute(ManagementFactory.MEMORY_MXBEAN_NAME, MonitorAttributeName.HEAP_MEMORY_USE, green);

        group.addAttribute(ManagementFactory.MEMORY_MXBEAN_NAME, MonitorAttributeName.HEAP_MEMORY_SIZE, darkRed);

        group.addAttribute(ManagementFactory.MEMORY_MXBEAN_NAME, MonitorAttributeName.HEAP_MEMORY_NINTY, blue);

        group.addAttribute(ManagementFactory.MEMORY_MXBEAN_NAME, MonitorAttributeName.HEAP_MEMORY_THREE_QUARTER,
                orange);

        group = server.addMonitoredAttributeGroup(MonitorAttributeName.CPU_USE, AxisUnit.Percent);
        group.addAttribute(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, MonitorAttributeName.CPU_TIME,
                lightgeen);
    }

    private void createSection(Composite parent, IMonitoredMXBeanGroup group) {
        if (parent.isDisposed()) {
            return;
        }
        FormToolkit tookit = new FormToolkit(Display.getDefault());

        ExpandableComposite section = tookit.createSection(parent, ExpandableComposite.NO_TITLE);
        section.setText(group.getName());
        FormLayout sectionLayout = new FormLayout();
        sectionLayout.marginWidth = 0;
        sectionLayout.marginHeight = 0;
        section.setLayout(sectionLayout);
        FormData sectionData = new FormData();
        if (group.getName().equals(MonitorAttributeName.HEAP_MEMORY)) {
            sectionData.left = new FormAttachment(0, 0);
            sectionData.right = new FormAttachment(65, 0);
            sectionData.top = new FormAttachment(0, 6);
            sectionData.bottom = new FormAttachment(53, -5);
        } else if (group.getName().equals(MonitorAttributeName.THREAD_COUNT)) {
            sectionData.left = new FormAttachment(50, 5);
            sectionData.right = new FormAttachment(100, -5);
            sectionData.top = new FormAttachment(50, 2);
            sectionData.bottom = new FormAttachment(100, 0);
        } else if (group.getName().equals(MonitorAttributeName.CPU_USE)) {
            sectionData.left = new FormAttachment(0, 0);
            sectionData.right = new FormAttachment(65, 0);
            sectionData.top = new FormAttachment(53, 0);
            sectionData.bottom = new FormAttachment(100, -6);
        }
        section.setLayoutData(sectionData);

        Composite flatFormComposite = createFlatFormComposite(section, tookit);
        FormLayout formLayout = new FormLayout();
        formLayout.marginHeight = 0;
        formLayout.marginWidth = 0;
        flatFormComposite.setLayout(formLayout);
        TimelineChart chart = new TimelineChart(flatFormComposite, section, group, SWT.NONE,
                toString() + getJvm().getPid());
        charts.add(chart);

        FormData data;
        data = new FormData();
        data.left = new FormAttachment(0, 0);
        data.right = new FormAttachment(100, 0);
        data.top = new FormAttachment(0, 0);
        data.bottom = new FormAttachment(100, 0);
        chart.setLayoutData(data);
        section.setClient(flatFormComposite);

        ArrayList<Action> list = new ArrayList<Action>();
        list.add(garbageCollectorAction);
        if (group.getName().equals(MonitorAttributeName.HEAP_MEMORY)) {
            addSectionActions(section, list);
        }
    }

    private Composite createFlatFormComposite(Composite section, FormToolkit tookit) {
        Composite flatFormComposite = createComposite(section, tookit);
        FormLayout layout = new FormLayout();
        layout.marginWidth = ITabbedPropertyConstants.HSPACE + 2;
        layout.marginHeight = ITabbedPropertyConstants.VSPACE;
        layout.spacing = ITabbedPropertyConstants.VMARGIN + 1;
        flatFormComposite.setLayout(layout);
        return flatFormComposite;
    }

    public Composite createComposite(Composite parent, FormToolkit tookit) {
        Composite c = tookit.createComposite(parent, SWT.NONE);
        tookit.paintBordersFor(c);
        return c;
    }

    @Override
    protected void createControls(Composite parent) {

        chartsPage = new Composite(parent, SWT.NULL);
        parent.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
        chartsPage.setBackground(parent.getBackground());
        FormLayout formLayout = new FormLayout();
        formLayout.marginWidth = 0;
        formLayout.marginHeight = 0;
        chartsPage.setLayout(formLayout);

        FormData pageData = new FormData();
        pageData.top = new FormAttachment(0, 0);
        pageData.bottom = new FormAttachment(100, 0);
        pageData.left = new FormAttachment(0, 0);
        pageData.right = new FormAttachment(100, 0);

        chartsPage.setLayoutData(pageData);
        mBeanServerChangeListener = new IMBeanServerChangeListener() {

            @Override
            public void serverChanged(MBeanServerEvent event) {
                new RefreshJob(Messages.reconstructChartJobLabel, toString()) {

                    @Override
                    protected void refreshUI() {
                        IActiveJvm jvm = getJvm();
                        if (jvm != null) {
                            reconstructCharts(jvm, false);
                        }
                    }
                }.schedule();
            }
        };

        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IHelpContextIds.TIMELINE_PAGE);
    }

    private Composite createMessagePage(Composite parent) {
        messagePage = new Composite(parent, SWT.NONE);
        FormLayout messageLayout = new FormLayout();
        messageLayout.marginHeight = 0;
        messageLayout.marginWidth = 0;
        messagePage.setLayout(messageLayout);
        messagePage.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

        FormToolkit toolkit = new FormToolkit(Display.getDefault());
        Hyperlink hyperlink = toolkit.createHyperlink(messagePage, Messages.loadDefaultChartSetLabel, SWT.NONE);
        hyperlink.addHyperlinkListener(new HyperlinkAdapter() {

            @Override
            public void linkActivated(HyperlinkEvent event) {
                try {
                    new LoadChartAction(RuntimeGraphcsComposite.this).loadDefaultChartSet();
                } catch (JvmCoreException e) {
                    Activator.log(Messages.loadChartSetFailedMsg, e);
                }
            }
        });
        return messagePage;
    }

    /*  private void createInfoField(Composite parent) {
        
    infoComposite = createFlatFormComposite(parent, new FormToolkit(Display.getDefault()));
    FormLayout reportLayout = new FormLayout();
    reportLayout.marginWidth = 0;
    reportLayout.marginHeight = 0;
    infoComposite.setLayout(reportLayout);
    FormData reportData = new FormData();
    reportData.left = new FormAttachment(65, 5);
    reportData.right = new FormAttachment(100, -5);
    reportData.top = new FormAttachment(50, 0);
    reportData.bottom = new FormAttachment(100, -5);
    infoComposite.setLayoutData(reportData);
        
    Group group = new Group(infoComposite, SWT.NULL);
    FormLayout groupLayout = new FormLayout();
    groupLayout.marginWidth = 0;
    groupLayout.marginHeight = 0;
    group.setLayout(groupLayout);
    FormData groupData = new FormData();
    groupData.left = new FormAttachment(0, 0);
    groupData.right = new FormAttachment(100, 0);
    groupData.top = new FormAttachment(0, 0);
    groupData.bottom = new FormAttachment(100, 0);
    group.setLayoutData(groupData);
    group.setText("Run job Informations");
        
    infoField = new Text(group, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY);
    infoField.setEditable(false);
    infoField.setBackground(group.getBackground());
        
    FormData data;
    data = new FormData();
    data.left = new FormAttachment(0, 0);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(0, 0);
    data.bottom = new FormAttachment(100, 0);
    infoField.setLayoutData(data);
      }*/

    private void createReportField(Composite parent) {
        reportComposite = createFlatFormComposite(parent, new FormToolkit(Display.getDefault()));
        FormLayout reportLayout = new FormLayout();
        reportComposite.setLayout(reportLayout);
        FormData reportData = new FormData();
        reportData.left = new FormAttachment(65, 5);
        reportData.right = new FormAttachment(100, -5);
        reportData.top = new FormAttachment(0, 0);
        reportData.bottom = new FormAttachment(100, -5);
        reportComposite.setLayoutData(reportData);

        Group group = new Group(reportComposite, SWT.NULL);
        FormLayout groupLayout = new FormLayout();
        group.setLayout(groupLayout);
        FormData groupData = new FormData();
        groupData.left = new FormAttachment(0, 0);
        groupData.right = new FormAttachment(100, 0);
        groupData.top = new FormAttachment(0, 0);
        groupData.bottom = new FormAttachment(100, 0);
        group.setLayoutData(groupData);
        group.setText("Job execution information"); //$NON-NLS-1$

        reportField = new StyledText(group, SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY);
        //may be CoreUIPlugin.setCSSClass can do this globally ,check later
        reportField.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));

        FormData data;
        data = new FormData();
        data.left = new FormAttachment(0, 0);
        data.right = new FormAttachment(100, 0);
        data.top = new FormAttachment(0, 0);
        data.bottom = new FormAttachment(93, 0);
        reportField.setLayoutData(data);
        displayReportField();

        //export button
        Button exportButton = new Button(group, SWT.PUSH);
        exportButton.setText("Export"); //$NON-NLS-1$
        FormData exportData = new FormData();
        exportData.left = new FormAttachment(100, -70);
        exportData.right = new FormAttachment(100, 0);
        exportData.bottom = new FormAttachment(100, -1);
        exportButton.setLayoutData(exportData);
        exportButton.setEnabled(true);
        exportButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {

                if (messageManager == null || messageManager.getMessages().size() < 1) {
                    MessageDialog.openWarning(getShell(), "Warning", "No log to export."); //$NON-NLS-1$ //$NON-NLS-2$
                    return;
                }

                UnboundedFifoBuffer messages = messageManager.getMessages();
                Iterator iterator = messages.iterator();
                StringBuilder content = new StringBuilder();
                while (iterator.hasNext()) {
                    ReportMessage message = (ReportMessage) iterator.next();
                    content.append(message.getContent());
                }
                if (isMonitoring) {
                    MessageDialog.openWarning(getShell(), "Warning", "Waiting for job done."); //$NON-NLS-1$ //$NON-NLS-2$
                    return;
                }

                FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
                dialog.setFilterPath("."); //$NON-NLS-1$
                String fileName = dialog.open();
                if (fileName != null) {
                    FileWriter writer = null;
                    try {
                        writer = new FileWriter(fileName);
                        writer.write(content.toString());
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    } finally {
                        try {
                            if (writer != null) {
                                writer.close();
                            }
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    }
                }

            }
        });
    }

    private void refreshConnectionIndicator() {
        IActiveJvm jvm = getJvm();
        boolean isConnected = jvm != null && jvm.isConnected();
        refreshBackground(chartsPage, isConnected);
        for (TimelineChart chart : charts) {
            refreshBackground(chart, isConnected);
            refreshBackground(chart.getPlotArea(), isConnected);
            refreshBackground(chart.getSection(), isConnected);
        }
    }

    private static void addSectionActions(ExpandableComposite expandableComposite, List<Action> actions) {
        ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
        ToolBar toolbar = toolBarManager.createControl(expandableComposite);
        Button button = new Button(expandableComposite, SWT.PUSH);
        button.setText("Trigger GC"); //$NON-NLS-1$
        button.setVisible(false);
        // set cursor
        final Cursor cursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
        toolbar.setCursor(cursor);
        toolbar.addDisposeListener(new DisposeListener() {

            @Override
            public void widgetDisposed(DisposeEvent e) {
                if (!cursor.isDisposed()) {
                    cursor.dispose();
                }
            }
        });

        // add menus
        for (Action action : actions) {
            if (action instanceof GarbageAction) {
                toolBarManager.add(action);
            }
        }
        toolBarManager.update(true);

        expandableComposite.setTextClient(button);
    }

}