net.rim.ejde.internal.ui.views.profiler.ProfilerView.java Source code

Java tutorial

Introduction

Here is the source code for net.rim.ejde.internal.ui.views.profiler.ProfilerView.java

Source

/*
* Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License, Version 1.0,
* which accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package net.rim.ejde.internal.ui.views.profiler;

import java.awt.Desktop;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;

import net.rim.ejde.internal.core.ContextManager;
import net.rim.ejde.internal.core.RimIDEUtil;
import net.rim.ejde.internal.ui.preferences.PreferenceConstants;
import net.rim.ejde.internal.ui.views.BasicDebugView;
import net.rim.ejde.internal.util.DebugUtils;
import net.rim.ejde.internal.util.Messages;
import net.rim.ejde.internal.util.ProjectUtils;
import net.rim.ide.RIA;
import net.rim.ide.RIA.ProfileType;
import net.rim.ide.core.IDEError;
import net.rim.ide.core.ProfileData;
import net.rim.ide.core.ProfileData.SourceResolver;
import net.rim.ide.core.ProfileItem;
import net.rim.ide.core.ProfileItemSource;
import net.rim.ide.core.ProfileLine;
import net.rim.ide.core.ProfileMethod;
import net.rim.ide.core.ProfileSourceLine;
import net.rim.ide.core.Util;
import net.rim.tools.compiler.debug.DebugMethod;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;

/**
 * View to display profile data.
 */
public class ProfilerView extends BasicDebugView implements SourceResolver {

    public static final String PROFILER_VIEW_ID = "net.rim.ejde.ui.viewers.ProfilerView";

    // Indexes of profile tabs
    final static public int INDEX_OF_TAB_SUMMARY = 0;

    final static public int INDEX_OF_TAB_METHOD = 1;

    final static public int INDEX_OF_TAB_SOURCE = 2;

    private static final Logger log = Logger.getLogger(ProfilerView.class);

    private TabFolder _tabFolder;

    private int _whatToProfile = 0;

    private boolean _methodTimeType;

    private ProfileTab[] _profileTabs;

    private ProfileData _pd;

    boolean _isInitialized = false;

    private static final String BLACKBERRY_PROFILEVISDESKTOP_TMP_FILE_PREFIX = "bbprof.prefix.";
    private static final String BLACKBERRY_PROFILEVISDESKTOP_TMP_FILE_SUFFIX = ".bbprof";

    /**
     * Constructs a ProfilerView instance.
     *
     * @throws CoreException
     *
     */
    public ProfilerView() throws CoreException {
        super(FORWARD_BUTTON | BACKWARD_BUTTON | REFRESH_BUTTON | CLEAR_BUTTON | OPTIONS_BUTTON | SAVE_BUTTON
                | SAVE_TO_XML | SAVE_RAW_TO_XML);
        RIA ria = RIA.getCurrentDebugger();
        if (ria != null && !_isInitialized) {
            initProfileParameters(ria);
        }
    }

    /**
     * Initializes all parameters related to profile.
     *
     * @throws CoreException
     *
     */
    private void initProfileParameters(RIA ria) {
        if (ria != null) {
            if (!DebugUtils.isRIMDebuggerRunning()) {
                return;
            }
            if (!ria.getProfileEnabled()) {
                ria.setProfileEnabled(true);
            }
            cleanMessage();
            try {
                // get profile options from preference store
                IPreferenceStore ps = ContextManager.PLUGIN.getPreferenceStore();
                _whatToProfile = ps.getInt(PreferenceConstants.NET_RIM_EJDE_UI_VIEWS_WHATTOPROFILE);
                ProfileType[] types;
                // MKS 2486071
                String debugAttachedTo = ria.getDebugAttachTo();
                if (debugAttachedTo == null || debugAttachedTo.isEmpty()) {
                    return;
                } else {
                    types = ProfilingViewOptionsDialog.getProfileTypes(ria);
                }

                if (!isValidProfileId(types, _whatToProfile)) {
                    _whatToProfile = types[0].getId();
                }
                _methodTimeType = ps.getBoolean(PreferenceConstants.NET_RIM_EJDE_UI_VIEWS_METHOD_TIME_TYPE);
                log.debug("Profile option - type:" + _whatToProfile + ", method: "
                        + (_methodTimeType ? "Cumulative" : "In method only"));
                ria.profileSetType(_whatToProfile);
                updateTypeColumeTitle();
                _isInitialized = true;
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }

    protected void handleRIMDebugEvent(DebugEvent event) {
        if (event.getKind() == DebugEvent.CREATE && !_isInitialized) {
            initProfileParameters(RIA.getCurrentDebugger());
        }
    }

    public void createTableViewPart(Composite parent) {
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 1;
        parent.setLayout(gridLayout);
        // create a TabFolder component on the view
        _tabFolder = new TabFolder(parent, SWT.BOTTOM);
        _tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
        _profileTabs = new ProfileTab[3];
        _profileTabs[INDEX_OF_TAB_SUMMARY] = new SummaryProfileTab(this);
        _profileTabs[INDEX_OF_TAB_METHOD] = new MethodProfileTab(this);
        _profileTabs[INDEX_OF_TAB_SOURCE] = new SourceProfileTab(this);
        //
        if (!DebugUtils.isRIMDebuggerRunning()) {
            setMessage(Messages.ProcessView_NO_BB_DEBUG_SESSION_MSG, true);
        }
    }

    /**
     * Set focus to a certain UI component.
     */
    public void setFocus() {
        // nothing to do
    }

    /**
     * Gets the profile type that need to be displayed.
     *
     * @return Profile type.
     */
    public int getWhatToProfile() {
        return _whatToProfile;
    }

    /**
     * Gets method time type.
     *
     * @return <code>true</code> method time will be cumulated, <code>false</code> otherwise.
     */
    public boolean getMethodTimeType() {
        return _methodTimeType;
    }

    /**
     * Set the tab at the given zero-relative index in the tabfolder as selected.
     *
     * @param index
     *            the index of the item to select.
     */
    public void setActiveTab(int index) {
        _tabFolder.setSelection(index);
    }

    protected TabFolder getTabFolder() {
        return _tabFolder;
    }

    /**
     * Updates the title of the type column (what to profile) of each tab.
     */
    void updateTypeColumeTitle() {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                // the _profileTabs could be null if this is called during the view creation
                if (_profileTabs == null) {
                    return;
                }
                for (int i = 0; i < _profileTabs.length; i++) {
                    _profileTabs[i].updateTypeColumeTitle();
                }
            }

        });
    }

    /**
     * Display profile data.
     */
    public void displayProfileData(ProfileTab[] tabs) {
        if (tabs == null || tabs.length == 0)
            return;
        if (_pd != null) {
            for (int i = 0; i < tabs.length; i++)
                tabs[i].displayData(_pd);
        }
    }

    /**
     * Display source code information of <code>pi</code>.
     *
     * @param pi
     *            An instance of ProfileItem.
     */
    protected void displaySourceData(ProfileItem pi) {
        SourceProfileTab sourceTab = (SourceProfileTab) _profileTabs[INDEX_OF_TAB_SOURCE];
        sourceTab.setTotal(_pd.getTotalExecutionTicks());
        sourceTab.setHistory(pi);
        sourceTab.clearExpansion();
        sourceTab.displayData(pi);
        setActiveTab(INDEX_OF_TAB_SOURCE);
    }

    /**
     * Clears the view (all tabs).
     *
     * @param clearPreferences
     *            <code>true</code> record or the last operation on this tab will be cleaned; <code>false</code> record or the
     *            last operation on this tab will not be cleaned.
     */
    public void clearVeiwer(boolean clearPreferences) {

        if (_pd != null)
            // clear display on each tab
            for (int i = 0; i < _profileTabs.length; i++)
                _profileTabs[i].clearTab(clearPreferences);
    }

    /**
     * Save profile data to a csv file.
     */
    private void saveProfile() {
        if (_pd == null)
            return;
        try {
            // save profile data to the file
            saveContents(RimIDEUtil.openCSVFileForSave(getSite().getShell()));
        } catch (IDEError e) {
            log.error("", e);
        }
    }

    /**
     * Writes the profile data to <code>file</code>.
     *
     * @param file
     *            Destination file.
     * @throws IDEError
     */
    private void saveContents(File file) throws IDEError {
        if (file == null) {
            return;
        }
        RIA ria = RIA.getCurrentDebugger();
        if (ria == null) {
            return;
        }
        String debugAttachedTo = ria.getDebugAttachTo();
        if (debugAttachedTo == null || debugAttachedTo.isEmpty()) {
            return;
        }

        PrintStream out = null;
        try {
            out = new PrintStream(new FileOutputStream(file));
            out.print(RIA.getString("ProfileCSVFileHeader1")); //$NON-NLS-1$
            out.print(ria.profileGetTypes()[_whatToProfile].getDescription());
            out.print(RIA.getString("ProfileCSVFileHeader2")); //$NON-NLS-1$
            out.println();

            ProfileItem[] modules = sortedElements(_pd, null);
            for (int i = 0; i < modules.length; i++) {
                ProfileItem module = modules[i];
                Object moduleName = module;

                ProfileItem[] methods = sortedElements(module, null);
                for (int j = 0; j < methods.length; j++) {
                    ProfileItem method = methods[j];

                    out.print(moduleName);
                    out.print(", "); //$NON-NLS-1$
                    String methodStr = method.toString();
                    Object handle = method.getMethodHandle();
                    if (handle != null && handle instanceof DebugMethod) {
                        methodStr = ((DebugMethod) handle).getFullName();
                    }
                    out.print(Util.replace(methodStr, ",", "")); //$NON-NLS-1$ //$NON-NLS-2$
                    out.print(", "); //$NON-NLS-1$
                    out.print(method.getTicks());
                    out.print(", "); //$NON-NLS-1$
                    out.print(method.getCount());
                    out.println();
                }
            }
            out.close();
        } catch (IOException e) {
            log.error("", e);
        }
    }

    /**
     * Sorts children ProfileItems of <code>source</code>.
     *
     * @param source
     *            ProfileItemSource instance.
     * @param comparator
     *            Comparator instance used to sort children items of <code>source</code>.
     * @return Array of sorted children ProfileItems of <code>source</code>.
     */
    protected static ProfileItem[] sortedElements(ProfileItemSource source, Comparator comparator) {
        ProfileItem profileItems[] = getUnsortedElements(source);
        if (profileItems.length == 0)
            return profileItems;
        if ((source instanceof ProfileMethod) || (source instanceof ProfileLine))
            // source lines are sorted use ProfileMethod's default comparator
            Arrays.sort(profileItems, source.getComparator());
        else
            Arrays.sort(profileItems, comparator == null ? source.getComparator() : comparator);
        return profileItems;
    }

    /**
     * Gets unsorted children of given <code>source</code>.
     *
     * @param source
     * @return
     */
    protected static ProfileItem[] getUnsortedElements(ProfileItemSource source) {
        Enumeration enumeration = source.getChildrenKeys();
        if (enumeration == null)
            return new ProfileItem[0];
        ProfileItem profileItems[] = new ProfileItem[source.getChildCount()];
        int i = 0;
        while (enumeration.hasMoreElements()) {
            ProfileItem pi = source.getChild(enumeration.nextElement());
            profileItems[i++] = pi;
        }
        return profileItems;
    }

    private void refresh(boolean clearPreferences) throws CoreException {
        RefreshProfilerViewJob job = new RefreshProfilerViewJob();
        try {
            PlatformUI.getWorkbench().getProgressService().run(false, true, job);
        } catch (InvocationTargetException e) {
            log.error("", e);
        } catch (InterruptedException e) {
            log.error("", e);
        }
    }

    class RefreshProfilerViewJob implements IRunnableWithProgress {

        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            monitor.beginTask(Messages.ProfilerView_Refresh, 100);
            RIA ria = RIA.getCurrentDebugger();
            if (ria == null) {
                return;
            }
            clearVeiwer(true);
            monitor.worked(10);
            try {
                ria.profileRefreshData();
                monitor.worked(20);
                _pd = ria.profileGetData();
                monitor.worked(30);
                if (_pd == null)
                    return;
                ProfileItem.setTickMode(_methodTimeType);
                monitor.worked(40);
                displayProfileData(new ProfileTab[] { _profileTabs[INDEX_OF_TAB_SUMMARY],
                        _profileTabs[INDEX_OF_TAB_METHOD], _profileTabs[INDEX_OF_TAB_SOURCE] });
                monitor.worked(50);
                setHasData(true);
                monitor.worked(60);
                updateToolbar();
            } catch (IDEError e) {
                log.error("", e);
            }
            monitor.done();
        }
    }

    // ------ Methods in BasicDebugView to be overridden ------
    /**
     * RIM Debug session is terminated.
     *
     * @see BasicDebugView#RIMDebugTerminated().
     */
    public void RIMDebugTerminated(ILaunch[] launches) {
        setMessage(Messages.ProcessView_NO_BB_DEBUG_SESSION_MSG, true);
        _isInitialized = false;
        this.getSite().getShell().getDisplay().syncExec(new Runnable() {

            @Override
            public void run() {
                clear();
            }

        });
        // this.getSite().getShell().getDisplay().asyncExec( new CloseViewJob( this ) );
    }

    /**
     * Gets new profile data, erases the current profile data, and display the new profile data.
     *
     * @throws CoreException
     * @see BasicDebugView#refresh().
     *
     */
    public void refresh() throws CoreException {
        refresh(true);
    }

    public void forward() {
        if (!(_tabFolder.getSelectionIndex() == INDEX_OF_TAB_SOURCE))
            return;
        _profileTabs[INDEX_OF_TAB_SOURCE].forward();
    }

    public void backward() {
        if (!(_tabFolder.getSelectionIndex() == INDEX_OF_TAB_SOURCE))
            return;
        _profileTabs[INDEX_OF_TAB_SOURCE].backward();
    }

    /**
     * (non-Javadoc)
     *
     * @see BasicDebugView#clear().
     */
    public void clear() {
        // clear the debugger
        RIA ria = RIA.getCurrentDebugger();
        if (ria == null) {
            return;
        }
        try {
            ria.profileClearData();
        } catch (IDEError e) {
            log.error(e);
            return;
        }
        // clear the display data
        clearVeiwer(true);
        _pd = null;
        setHasData(false);
        updateToolbar();
        updateTypeColumeTitle();
    }

    /**
     * Gets the ProfileData instance represented by this view.
     *
     * @return a ProfileData instance.
     */
    public ProfileData getProfileData() {
        return _pd;
    }

    /**
     * (non-Javadoc)
     *
     * @see BasicDebugView#save().
     */
    public void save() {
        saveProfile();
    }

    public void dispose() {
        super.dispose();
        if (RIA.getCurrentDebugger() != null) {
            RIA.getCurrentDebugger().setProfileEnabled(false);
        }
        _pd = null;
        _profileTabs = null;
    }

    private static boolean isValidProfileId(ProfileType[] types, int id) {
        for (int i = 0; i < types.length; i++) {
            if (types[i].getId() == id) {
                return true;
            }
        }
        return false;
    }

    /**
     * Opens an option dialog. Options related to profiler can be set on the dialog and will be saved as references when "OK"
     * button is pressed.
     *
     * @see BasicDebugView#setOptions().
     */
    public void setOptions() {
        // create an ImplicitBuildRuleEditDialog instance
        ProfilingViewOptionsDialog optionsDialog = new ProfilingViewOptionsDialog(getSite().getShell());
        // show the dialog
        optionsDialog.open();
        if (optionsDialog.isOkButtonClicked()) {
            try {
                IPreferenceStore ps = ContextManager.PLUGIN.getPreferenceStore();
                int whatToProfile = ps.getInt(PreferenceConstants.NET_RIM_EJDE_UI_VIEWS_WHATTOPROFILE);
                if (whatToProfile != _whatToProfile) {
                    initProfileParameters(RIA.getCurrentDebugger());
                    clear();
                    enableActions(REFRESH_BUTTON, false);
                } else {
                    initProfileParameters(RIA.getCurrentDebugger());
                    refresh(false);
                }
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }

    /**
     * Save view content to a XML file.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void saveXML() {
        File xmlFile = chooseDataFile();
        if (xmlFile == null) {
            return;
        }
        if (!xmlFile.exists()) {
            xmlFile = ProjectUtils.createFile(xmlFile);
            if (xmlFile == null || !xmlFile.exists()) {
                return;
            }
        }
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(ContextManager.getActiveWorkbenchShell());
        SaveDataRunnale runnable = new SaveDataRunnale(xmlFile, this);
        try {
            dialog.run(false, true, runnable);
        } catch (InvocationTargetException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), e.getMessage(),
                    Messages.ErrorHandler_DIALOG_TITLE);
        } catch (InterruptedException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), e.getMessage(),
                    Messages.ErrorHandler_DIALOG_TITLE);
        }
    }

    /**
     * Save raw data of the view content to a XML file.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void saveRawToXML() {
        File xmlFile = chooseRawDataFile();
        if (xmlFile == null) {
            return;
        }
        if (!xmlFile.exists()) {
            xmlFile = ProjectUtils.createFile(xmlFile);
            if (xmlFile == null || !xmlFile.exists()) {
                return;
            }
        }
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(ContextManager.getActiveWorkbenchShell());
        SaveRawDataRunnale runnable = new SaveRawDataRunnale(xmlFile, this);
        try {
            dialog.run(false, true, runnable);
        } catch (InvocationTargetException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), e.getMessage(),
                    Messages.ErrorHandler_DIALOG_TITLE);
        } catch (InterruptedException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), e.getMessage(),
                    Messages.ErrorHandler_DIALOG_TITLE);
        }
    }

    private void saveRawData(File xmlFile) {
        RIA ria = RIA.getCurrentDebugger();
        if (ria == null) {
            return;
        }
        if (xmlFile == null) {
            return;
        }
        if (!xmlFile.exists()) {
            xmlFile = ProjectUtils.createFile(xmlFile);
            if (xmlFile == null || !xmlFile.exists()) {
                return;
            }
        }
        PrintStream out = null;
        try {
            out = new PrintStream(new FileOutputStream(xmlFile));
            ria.profileDumpRawXML(out);
        } catch (Exception e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), Messages.ErrorHandler_DIALOG_TITLE,
                    e.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    private File chooseDataFile() {
        return chooseXMLFile(new String[] { "*.xml" }, new String[] { "XML File (*.xml)" });
    }

    private File chooseRawDataFile() {
        return chooseXMLFile(new String[] { "*.xml", "*.bbprof" },
                new String[] { "XML File (*.xml)", "BlackBerry ProfileVisDesktop File (*.bbprof)" });
    }

    private File chooseXMLFile(String[] filterExtensions, String[] filterNamesExtensions) {
        FileDialog dialog = new FileDialog(this.getSite().getShell(), SWT.SAVE);
        dialog.setFilterExtensions(filterExtensions);
        dialog.setFilterNames(filterNamesExtensions);
        String xmlFile = dialog.open();
        if (!StringUtils.isBlank(xmlFile)) {
            return new File(xmlFile);
        }
        return null;
    }

    @Override
    public String resolveSourceLine(ProfileItem item) {
        RIA ria = RIA.getCurrentDebugger();
        if (ria == null) {
            return Messages.SourceProfileTab_NO_SOURCE_MESSAGE;
        }
        ProfileSourceLine psl = item.getLineHandle();
        if (psl == null)
            return Messages.SourceProfileTab_NO_SOURCE_MESSAGE;
        Object line = psl.getLine();
        if (line == null) {
            return Messages.SourceProfileTab_NO_SOURCE_MESSAGE;
        }
        return line.toString();
    }

    public void openProfileVis() {
        File tmpFile = getTmpFile();
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(ContextManager.getActiveWorkbenchShell());
        SaveRawDataRunnale runnable = new SaveRawDataRunnale(tmpFile, this);
        try {
            dialog.run(false, true, runnable);
        } catch (InvocationTargetException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), e.getMessage(),
                    Messages.ErrorHandler_DIALOG_TITLE);
            return;
        } catch (InterruptedException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), e.getMessage(),
                    Messages.ErrorHandler_DIALOG_TITLE);
            return;
        }
        try {
            Desktop.getDesktop().open(tmpFile);
        } catch (IOException e) {
            log.error(e);
            MessageDialog.openError(ContextManager.getActiveWorkbenchShell(), Messages.ErrorHandler_DIALOG_TITLE,
                    Messages.BBProfileVis_Not_Installed_ErrMsg);
        }
    }

    private static synchronized File getTmpFile() {
        String tmpDir = System.getProperty("java.io.tmpdir");
        if (tmpDir == null) {
            // Shouldn't happen
            tmpDir = ".";
        }
        File file = null;
        for (int retry = 0; retry < 10; retry++) {
            file = new File(tmpDir, BLACKBERRY_PROFILEVISDESKTOP_TMP_FILE_PREFIX + System.currentTimeMillis()
                    + BLACKBERRY_PROFILEVISDESKTOP_TMP_FILE_SUFFIX);
            if (!file.exists()) {
                return file;
            }
        }
        throw new RuntimeException("unable to create temporary file");
    }

    // ----- Inner Classes ------
    class CloseViewJob implements Runnable {
        ProfilerView _view;

        CloseViewJob(ProfilerView view) {
            _view = view;
        }

        public void run() {
            IViewSite viewSite = _view.getViewSite();
            if (viewSite == null) {
                return;
            }
            IWorkbenchPage workbenchPage = viewSite.getPage();
            if (workbenchPage == null) {
                return;
            }
            workbenchPage.hideView(_view);
        }

    }

    class SaveRawDataRunnale implements IRunnableWithProgress {
        File destFile;
        SourceResolver sourceResolver;

        public SaveRawDataRunnale(File destFile, SourceResolver sourceResolver) {
            this.sourceResolver = sourceResolver;
            this.destFile = destFile;
        }

        @Override
        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            try {
                monitor.beginTask("Saving profiling raw data...", 10);
                log.trace("Save raw to XML");
                monitor.worked(1);
                saveRawData(destFile);
            } finally {
                monitor.done();
            }

        }

    }

    class SaveDataRunnale implements IRunnableWithProgress {
        File destFile;
        SourceResolver sourceResolver;

        public SaveDataRunnale(File destFile, SourceResolver sourceResolver) {
            this.sourceResolver = sourceResolver;
            this.destFile = destFile;
        }

        @Override
        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            try {
                monitor.beginTask("Saving profiling data...", 10);
                log.trace("Save XML");
                RIA ria = RIA.getCurrentDebugger();
                if (ria == null) {
                    return;
                }
                monitor.worked(1);
                ProfileData profileData = getProfileData();
                if (profileData == null) {
                    return;
                }
                monitor.worked(1);
                try {
                    profileData.saveContentsInXml(destFile,
                            ria.profileGetTypes()[getWhatToProfile()].getDescription(), this.sourceResolver);
                } catch (IDEError e) {
                    log.error(e);
                    MessageDialog.openError(ContextManager.getActiveWorkbenchShell(),
                            Messages.ErrorHandler_DIALOG_TITLE, e.getMessage());
                }
            } finally {
                monitor.done();
            }

        }

    }
}