Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project')
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/Messages.java38
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/SelectSupplementaryResourcesDialog.java324
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/messages.properties16
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/Messages.java67
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java578
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/messages.properties24
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/BatchImportTraceHandler.java59
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java122
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyExperimentHandler.java54
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyTraceHandler.java54
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteExperimentHandler.java113
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceFolderElementHandler.java349
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceSupplementaryFilesHandler.java192
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DropAdapterAssistant.java669
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ImportTraceHandler.java64
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/Messages.java85
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewExperimentHandler.java74
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewFolderHandler.java63
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OffsetTraceHandler.java136
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAction.java94
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java114
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java89
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenExperimentHandler.java99
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenTraceHandler.java104
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RefreshHandler.java87
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameExperimentHandler.java96
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameFolderHandler.java164
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameTraceHandler.java177
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectElementTypeContributionItem.java269
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTraceTypeHandler.java203
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTracesHandler.java107
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SynchronizeTracesHandler.java280
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TmfActionProvider.java81
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TracePropertyTester.java114
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/messages.properties70
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfEditorLinkHelper.java129
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfImportHelper.java76
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/operations/TmfWorkspaceModifyOperation.java114
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/AbstractImportTraceWizardPage.java153
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java695
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileAndName.java175
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipEntry.java100
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFile.java135
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipLeveledStructureProvider.java111
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConfirmation.java69
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConflictHandler.java205
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceContentProvider.java182
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceLabelProvider.java40
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizard.java85
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java2365
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPageOptions.java111
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardScanPage.java565
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectDirectoriesPage.java260
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectTraceTypePage.java183
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/Messages.java216
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceTypeContentProvider.java100
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/messages.properties81
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageOperation.java369
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageWizardPage.java570
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/ITracePackageConstants.java76
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/Messages.java84
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageBookmarkElement.java66
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageContentProvider.java58
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageElement.java223
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageFilesElement.java116
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageLabelProvider.java69
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFileElement.java89
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFilesElement.java47
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageTraceElement.java167
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageHandler.java105
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageSelectTraceWizardPage.java218
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizard.java84
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizardPage.java450
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageHandler.java53
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizard.java63
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizardPage.java417
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ManifestReader.java191
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/Messages.java239
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExportOperation.java302
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExtractManifestOperation.java142
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java493
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/messages.properties53
-rw-r--r--tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/messages.properties22
83 files changed, 16145 insertions, 0 deletions
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/Messages.java
new file mode 100644
index 0000000000..c980279d28
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/Messages.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Marc-Andre Laperle - Add select/deselect all
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.dialogs;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Message bundle for dialog messages.
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.messages"; //$NON-NLS-1$
+
+ public static String SelectSpplementaryResources_DialogTitle;
+ public static String SelectSpplementaryResources_ResourcesGroupTitle;
+ public static String Dialog_SelectAll;
+ public static String Dialog_DeselectAll;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/SelectSupplementaryResourcesDialog.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/SelectSupplementaryResourcesDialog.java
new file mode 100644
index 0000000000..f63145aeaa
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/SelectSupplementaryResourcesDialog.java
@@ -0,0 +1,324 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Copied and adapted from NewFolderDialog
+ * Marc-Andre Laperle - Add select/deselect all
+ * Patrick Tasse - Add support for folder elements
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.dialogs;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+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.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * SelectSupplementaryResourcesDialog
+ */
+public class SelectSupplementaryResourcesDialog extends Dialog {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+ private static final Image EXPERIMENT_IMAGE = Activator.getDefault().getImageFromPath("icons/elcl16/experiment.gif"); //$NON-NLS-1$
+ private static final Image TRACE_IMAGE = Activator.getDefault().getImageFromPath("icons/elcl16/trace.gif"); //$NON-NLS-1$
+ private static final Image RESOURCE_IMAGE = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+
+ // ------------------------------------------------------------------------
+ // Members
+ // ------------------------------------------------------------------------
+ private CheckboxTreeViewer fTreeViewer;
+ private final Multimap<TmfCommonProjectElement, IResource> fResourceMap;
+ private IResource[] fReturnedResources;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param shell
+ * Parent shell of this dialog
+ * @param resourceMap
+ * Map of element to supplementary resources
+ */
+ public SelectSupplementaryResourcesDialog(Shell shell, Multimap<TmfCommonProjectElement, IResource> resourceMap) {
+ super(shell);
+ fResourceMap = resourceMap;
+ setShellStyle(SWT.RESIZE | getShellStyle());
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters/Setters
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return A copy of the selected resources
+ */
+ public IResource[] getResources() {
+ return Arrays.copyOf(fReturnedResources, fReturnedResources.length);
+ }
+
+ // ------------------------------------------------------------------------
+ // Dialog
+ // ------------------------------------------------------------------------
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(Messages.SelectSpplementaryResources_DialogTitle);
+ newShell.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ETOOL_DELETE));
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Group contextGroup = new Group(composite, SWT.SHADOW_NONE);
+ contextGroup.setText(Messages.SelectSpplementaryResources_ResourcesGroupTitle);
+ contextGroup.setLayout(new GridLayout(2, false));
+ contextGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ fTreeViewer = new CheckboxTreeViewer(contextGroup, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ Tree tree = fTreeViewer.getTree();
+ tree.setLayoutData(data);
+ fTreeViewer.setContentProvider(new ITreeContentProvider() {
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ return element instanceof TmfCommonProjectElement;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element instanceof IResource) {
+ getParentElement((IResource) element);
+ }
+ return null;
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof Object[]) {
+ return (Object[]) inputElement;
+ }
+ return null;
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof TmfCommonProjectElement) {
+ return fResourceMap.get((TmfCommonProjectElement) parentElement).toArray();
+ }
+ return null;
+ }
+ });
+
+ fTreeViewer.setLabelProvider(new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element instanceof IResource) {
+ IResource resource = (IResource) element;
+ TmfCommonProjectElement projectElement = getParentElement(resource);
+ // remove .tracing/<supplementary folder> segments
+ IPath suppFolderPath = projectElement.getTraceSupplementaryFolder(projectElement.getElementPath()).getFullPath();
+ return resource.getFullPath().removeFirstSegments(suppFolderPath.segmentCount()).toString();
+ } else if (element instanceof TmfCommonProjectElement) {
+ TmfCommonProjectElement projectElement = (TmfCommonProjectElement) element;
+ return projectElement.getElementPath();
+ }
+ return super.getText(element);
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof IResource) {
+ return RESOURCE_IMAGE;
+ } else if (element instanceof TmfTraceElement) {
+ return TRACE_IMAGE;
+ } else if (element instanceof TmfExperimentElement) {
+ return EXPERIMENT_IMAGE;
+ }
+ return null;
+ }
+
+ });
+
+ fTreeViewer.setInput(fResourceMap.keySet().toArray());
+
+ fTreeViewer.expandAll();
+ setAllChecked(true);
+
+ fTreeViewer.addCheckStateListener(new ICheckStateListener() {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ if (event.getElement() instanceof TmfCommonProjectElement) {
+ fTreeViewer.setSubtreeChecked(event.getElement(), event.getChecked());
+ fTreeViewer.setGrayed(event.getElement(), false);
+ } else if (event.getElement() instanceof IResource) {
+ TmfCommonProjectElement projectElement = getParentElement((IResource) event.getElement());
+ int checkedCount = 0;
+ Collection<IResource> resources = fResourceMap.get(projectElement);
+ for (IResource resource : resources) {
+ if (fTreeViewer.getChecked(resource)) {
+ checkedCount++;
+ }
+ }
+ if (checkedCount == resources.size()) {
+ fTreeViewer.setChecked(projectElement, true);
+ fTreeViewer.setGrayed(projectElement, false);
+ } else if (checkedCount > 0) {
+ fTreeViewer.setGrayChecked(projectElement, true);
+ } else {
+ fTreeViewer.setGrayChecked(projectElement, false);
+ }
+ }
+ }
+ });
+
+ fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateOKButtonEnablement();
+ }
+ });
+
+ Composite btComp = new Composite(contextGroup, SWT.NONE);
+ FillLayout layout = new FillLayout(SWT.VERTICAL);
+ layout.spacing = 4;
+ btComp.setLayout(layout);
+
+ GridData gd = new GridData();
+ gd.verticalAlignment = SWT.CENTER;
+ btComp.setLayoutData(gd);
+
+ final Button selectAll = new Button(btComp, SWT.PUSH);
+ selectAll.setText(Messages.Dialog_SelectAll);
+ selectAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setAllChecked(true);
+
+ updateOKButtonEnablement();
+ }
+ });
+
+ final Button deselectAll = new Button(btComp, SWT.PUSH);
+ deselectAll.setText(Messages.Dialog_DeselectAll);
+ deselectAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setAllChecked(false);
+
+ updateOKButtonEnablement();
+ }
+ });
+
+ getShell().setMinimumSize(new Point(300, 150));
+
+ return composite;
+ }
+
+ private TmfCommonProjectElement getParentElement(IResource resource) {
+ for (Entry<TmfCommonProjectElement, IResource> entry : fResourceMap.entries()) {
+ if (entry.getValue().equals(resource)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ private void setAllChecked(boolean state) {
+ for (Object element : fResourceMap.keySet()) {
+ fTreeViewer.setSubtreeChecked(element, state);
+ fTreeViewer.setGrayed(element, false);
+ }
+ }
+
+ private void updateOKButtonEnablement() {
+ Object[] checked = fTreeViewer.getCheckedElements();
+ getButton(IDialogConstants.OK_ID).setEnabled(checked.length > 0);
+ }
+
+ @Override
+ protected Control createButtonBar(Composite parent) {
+ Control control = super.createButtonBar(parent);
+ updateOKButtonEnablement();
+ return control;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true);
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ }
+
+ @Override
+ protected void okPressed() {
+ Object[] checkedElements = fTreeViewer.getCheckedElements();
+ List<IResource> checkedResources = new ArrayList<>(checkedElements.length);
+ for (Object checked : checkedElements) {
+ if (checked instanceof IResource) {
+ checkedResources.add((IResource) checked);
+ }
+ }
+ fReturnedResources = checkedResources.toArray(new IResource[0]);
+ super.okPressed();
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/messages.properties
new file mode 100644
index 0000000000..e90050cfa8
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/messages.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2012, 2014 Ericsson
+#
+# 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:
+# Bernd Hufmann - initial API and implementation
+# Marc-Andre Laperle - Add select/deselect all
+###############################################################################
+SelectSpplementaryResources_DialogTitle=Delete Resources
+SelectSpplementaryResources_ResourcesGroupTitle=Select resources to delete
+Dialog_SelectAll=Select All
+Dialog_DeselectAll=Deselect All \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/Messages.java
new file mode 100644
index 0000000000..30adffd89d
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/Messages.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.offset;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages for the offset dialog
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.offset.messages"; //$NON-NLS-1$
+
+ /**
+ * Advanced mode button
+ */
+ public static String OffsetDialog_AdvancedButton;
+ /**
+ * Advanced mode dialog message
+ */
+ public static String OffsetDialog_AdvancedMessage;
+ /**
+ * Basic mode button
+ */
+ public static String OffsetDialog_BasicButton;
+ /**
+ * Basic mode dialog message
+ */
+ public static String OffsetDialog_BasicMessage;
+ /**
+ * Offset time
+ */
+ public static String OffsetDialog_OffsetTime;
+ /**
+ * Reference time
+ */
+ public static String OffsetDialog_ReferenceTime;
+ /**
+ * Target time
+ */
+ public static String OffsetDialog_TargetTime;
+ /**
+ * Dialog title
+ */
+ public static String OffsetDialog_Title;
+ /**
+ * Trace name
+ */
+ public static String OffsetDialog_TraceName;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java
new file mode 100644
index 0000000000..7246c2d37c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java
@@ -0,0 +1,578 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.offset;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.TreeViewerEditor;
+import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TreeEditor;
+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.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.tracecompass.tmf.core.signal.TmfEventSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.viewers.ArrayTreeContentProvider;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+
+/**
+ * Offset wizard dialog
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class OffsetDialog extends Dialog {
+
+ private static final int TREE_EDITOR_MIN_WIDTH = 50;
+ private static final String EDITOR_KEY = "$editor$"; //$NON-NLS-1$
+ private static final String WIDTH_KEY = "$width$"; //$NON-NLS-1$
+
+ private static final TmfTimestampFormat TIME_FORMAT = new TmfTimestampFormat("yyyy-MM-dd HH:mm:ss.SSS SSS SSS"); //$NON-NLS-1$
+ private static final TmfTimestampFormat OFFSET_FORMAT = new TmfTimestampFormat("T.SSS SSS SSS"); //$NON-NLS-1$
+
+ private final Map<TmfTraceElement, Long> fOffsetMap;
+ private final Map<TmfTraceElement, ITmfTimestamp> fRefTimeMap;
+ private final Map<TmfTraceElement, ITmfTimestamp> fTargetTimeMap;
+
+ private Label fBasicMessageLabel;
+ private Group fButtonGroup;
+ private Label fAdvancedMessageLabel;
+ private FilteredTree fViewer;
+
+ private boolean fAdvancedMode = true;
+ private TreeViewerColumn fButtonViewerColumn;
+ private TreeColumn fRefTimeColumn;
+ private TreeColumn fTargetTimeColumn;
+
+ private abstract class ColumnEditingSupport extends EditingSupport {
+ private final TextCellEditor textCellEditor;
+
+ private ColumnEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+ super(viewer);
+ this.textCellEditor = textCellEditor;
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element) {
+ return textCellEditor;
+ }
+
+ @Override
+ protected boolean canEdit(Object element) {
+ return true;
+ }
+ }
+
+ private class TimeEditingSupport extends ColumnEditingSupport {
+ private Map<TmfTraceElement, ITmfTimestamp> map;
+
+ private TimeEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor, Map<TmfTraceElement, ITmfTimestamp> map) {
+ super(viewer, textCellEditor);
+ this.map = map;
+ }
+
+ @Override
+ protected void setValue(Object element, Object value) {
+ if (value instanceof String) {
+ String string = (String) value;
+ if (string.trim().isEmpty()) {
+ map.remove(element);
+ } else {
+ try {
+ ITmfTimestamp refTime = map.get(element);
+ long ref = refTime == null ? 0 : refTime.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ Long newVal = TIME_FORMAT.parseValue(string, ref);
+ map.put((TmfTraceElement) element, new TmfNanoTimestamp(newVal));
+ } catch (ParseException e) {
+ /* Ignore and reload previous value */
+ }
+ }
+ fViewer.getViewer().update(element, null);
+ }
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ if (map.get(element) == null) {
+ return ""; //$NON-NLS-1$
+ }
+ return TIME_FORMAT.format(map.get(element).normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue());
+ }
+ }
+
+ private class RefTimeEditingSupport extends TimeEditingSupport {
+ private RefTimeEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+ super(viewer, textCellEditor, fRefTimeMap);
+ }
+ }
+
+ private class TargetTimeEditingSupport extends TimeEditingSupport {
+ private TargetTimeEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+ super(viewer, textCellEditor, fTargetTimeMap);
+ }
+ }
+
+ private class OffsetEditingSupport extends ColumnEditingSupport {
+ private OffsetEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+ super(viewer, textCellEditor);
+ }
+
+ @Override
+ protected void setValue(Object element, Object value) {
+ if (value instanceof String) {
+ String string = (String) value;
+ if (string.trim().isEmpty()) {
+ fOffsetMap.put((TmfTraceElement) element, 0L);
+ } else {
+ try {
+ Long newVal = OFFSET_FORMAT.parseValue(string);
+ fOffsetMap.put((TmfTraceElement) element, newVal);
+ } catch (ParseException e) {
+ /* Ignore and reload previous value */
+ }
+ }
+ fViewer.getViewer().update(element, null);
+ }
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ if (fOffsetMap.get(element) == 0) {
+ return ""; //$NON-NLS-1$
+ }
+ return OFFSET_FORMAT.format((long) fOffsetMap.get(element));
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param parent
+ * parent shell
+ * @param results
+ * results to put the data into
+ */
+ public OffsetDialog(Shell parent, Map<TmfTraceElement, Long> results) {
+ super(parent);
+ setShellStyle(getShellStyle() & ~SWT.APPLICATION_MODAL);
+ fOffsetMap = results;
+ fRefTimeMap = new HashMap<>();
+ fTargetTimeMap = new HashMap<>();
+ }
+
+ @Override
+ protected boolean isResizable() {
+ return true;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ getShell().setText(Messages.OffsetDialog_Title);
+ Composite area = (Composite) super.createDialogArea(parent);
+ Composite composite = new Composite(area, SWT.NONE);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout();
+ gl.marginHeight = 0;
+ gl.marginWidth = 0;
+ composite.setLayout(new GridLayout());
+ createBasicMessage(composite);
+ createButtonGroup(composite);
+ createAdvancedMessage(composite);
+ createViewer(composite);
+
+ /* set label width hint equal to tree width */
+ int widthHint = fViewer.getViewer().getTree().computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+ GridData gd = (GridData) fBasicMessageLabel.getLayoutData();
+ gd.widthHint = widthHint;
+ gd = (GridData) fAdvancedMessageLabel.getLayoutData();
+ gd.widthHint = widthHint;
+ gd = (GridData) composite.getLayoutData();
+ gd.heightHint = composite.computeSize(widthHint, SWT.DEFAULT).y;
+ setBasicMode();
+
+ TmfSignalManager.register(this);
+ composite.addDisposeListener(new DisposeListener() {
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ TmfSignalManager.deregister(this);
+ }
+ });
+ return area;
+ }
+
+ private void createBasicMessage(final Composite parent) {
+ fBasicMessageLabel = new Label(parent, SWT.WRAP);
+ fBasicMessageLabel.setText(Messages.OffsetDialog_BasicMessage);
+ GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ gd.widthHint = 0;
+ gd.heightHint = SWT.DEFAULT;
+ fBasicMessageLabel.setLayoutData(gd);
+ }
+
+ private void createButtonGroup(final Composite parent) {
+ fButtonGroup = new Group(parent, SWT.SHADOW_NONE);
+ fButtonGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ fButtonGroup.setLayout(new RowLayout(SWT.HORIZONTAL));
+
+ final Button basicButton = new Button(fButtonGroup, SWT.RADIO);
+ basicButton.setText(Messages.OffsetDialog_BasicButton);
+ basicButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (!basicButton.getSelection() || !fAdvancedMode) {
+ return;
+ }
+ setBasicMode();
+ parent.layout();
+ }
+ });
+ basicButton.setSelection(true);
+
+ final Button advancedButton = new Button(fButtonGroup, SWT.RADIO);
+ advancedButton.setText(Messages.OffsetDialog_AdvancedButton);
+ advancedButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (!advancedButton.getSelection() || fAdvancedMode) {
+ return;
+ }
+ setAdvancedMode();
+ parent.layout();
+ }
+ });
+ }
+
+ private void createAdvancedMessage(final Composite parent) {
+ fAdvancedMessageLabel = new Label(parent, SWT.WRAP);
+ fAdvancedMessageLabel.setText(Messages.OffsetDialog_AdvancedMessage);
+ GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ gd.widthHint = 0;
+ gd.heightHint = SWT.DEFAULT;
+ fAdvancedMessageLabel.setLayoutData(gd);
+ }
+
+ private void createViewer(Composite parent) {
+
+ // Define the TableViewer
+ fViewer = new FilteredTree(parent, SWT.MULTI | SWT.H_SCROLL
+ | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER, new PatternFilter() {
+ @Override
+ protected boolean isLeafMatch(Viewer viewer, Object element) {
+ return wordMatches(((TmfTraceElement) element).getElementPath());
+ }
+ }, true);
+
+ // Make lines and make header visible
+ final Tree tree = fViewer.getViewer().getTree();
+ tree.setHeaderVisible(true);
+ tree.setLinesVisible(true);
+
+ TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(fViewer.getViewer(), new FocusCellOwnerDrawHighlighter(fViewer.getViewer()));
+ ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(fViewer.getViewer());
+ TreeViewerEditor.create(fViewer.getViewer(), focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
+ | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
+ | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
+
+ final TextCellEditor textCellEditor = new TextCellEditor(fViewer.getViewer().getTree(), SWT.RIGHT);
+
+ fViewer.getViewer().setColumnProperties(new String[] { Messages.OffsetDialog_TraceName, Messages.OffsetDialog_ReferenceTime, Messages.OffsetDialog_OffsetTime });
+
+ TreeViewerColumn column = createTreeViewerColumn(Messages.OffsetDialog_TraceName, SWT.NONE);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return ((TmfTraceElement) element).getElementPath();
+ }
+ });
+
+ column = createTreeViewerColumn(Messages.OffsetDialog_OffsetTime, SWT.RIGHT);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (fOffsetMap.get(element) != 0) {
+ return super.getText(OFFSET_FORMAT.format((long) fOffsetMap.get(element)));
+ }
+ return ""; //$NON-NLS-1$
+ }
+ });
+ column.setEditingSupport(new OffsetEditingSupport(fViewer.getViewer(), textCellEditor));
+
+ column = createTreeViewerColumn("", SWT.NONE); //$NON-NLS-1$
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return ""; //$NON-NLS-1$
+ }
+ });
+ column.getColumn().setWidth(TREE_EDITOR_MIN_WIDTH);
+ column.getColumn().setResizable(false);
+ fButtonViewerColumn = column;
+
+ column = createTreeViewerColumn(Messages.OffsetDialog_ReferenceTime, SWT.RIGHT);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return super.getText(fRefTimeMap.get(element));
+ }
+ });
+ column.setEditingSupport(new RefTimeEditingSupport(fViewer.getViewer(), textCellEditor));
+ fRefTimeColumn = column.getColumn();
+
+ column = createTreeViewerColumn(Messages.OffsetDialog_TargetTime, SWT.RIGHT);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return super.getText(fTargetTimeMap.get(element));
+ }
+ });
+ column.setEditingSupport(new TargetTimeEditingSupport(fViewer.getViewer(), textCellEditor));
+ fTargetTimeColumn = column.getColumn();
+
+ List<TmfTraceElement> traces = new ArrayList<>(fOffsetMap.keySet());
+ Collections.sort(traces, new Comparator<TmfTraceElement>() {
+ @Override
+ public int compare(TmfTraceElement o1, TmfTraceElement o2) {
+ IPath folder1 = new Path(o1.getElementPath()).removeLastSegments(1);
+ IPath folder2 = new Path(o2.getElementPath()).removeLastSegments(1);
+ if (folder1.equals(folder2)) {
+ return o1.getName().compareToIgnoreCase(o2.getName());
+ }
+ if (folder1.isPrefixOf(folder2)) {
+ return 1;
+ } else if (folder2.isPrefixOf(folder1)) {
+ return -1;
+ }
+ return folder1.toString().compareToIgnoreCase(folder2.toString());
+ }
+ });
+
+ fViewer.getViewer().setContentProvider(new ArrayTreeContentProvider());
+ fViewer.getViewer().setInput(traces);
+
+ /* add button as tree editors to fourth column of every item */
+ for (TreeItem treeItem : tree.getItems()) {
+ TreeEditor treeEditor = new TreeEditor(tree);
+ Button applyButton = new Button(tree, SWT.PUSH);
+ applyButton.setText("<<"); //$NON-NLS-1$
+ applyButton.setData(treeItem.getData());
+ applyButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ TmfTraceElement traceElement = (TmfTraceElement) e.widget.getData();
+ ITmfTimestamp targetTime = fTargetTimeMap.get(traceElement);
+ ITmfTimestamp refTime = fRefTimeMap.get(traceElement);
+ if (targetTime != null && refTime != null) {
+ long offset = new TmfNanoTimestamp(targetTime).getValue() -
+ new TmfNanoTimestamp(refTime).getValue();
+ fOffsetMap.put(traceElement, offset);
+ fViewer.getViewer().update(traceElement, null);
+ }
+ }
+ });
+ treeEditor.grabHorizontal = true;
+ treeEditor.minimumWidth = TREE_EDITOR_MIN_WIDTH;
+ treeEditor.setEditor(applyButton, treeItem, 2);
+ treeItem.setData(EDITOR_KEY, applyButton);
+ }
+
+ /* put temporary values in maps to pack according to time formats */
+ fRefTimeMap.put(traces.get(0), new TmfNanoTimestamp());
+ fTargetTimeMap.put(traces.get(0), new TmfNanoTimestamp());
+ fViewer.getViewer().update(traces.get(0), null);
+ for (final TreeColumn treeColumn : tree.getColumns()) {
+ if (treeColumn.getResizable()) {
+ treeColumn.pack();
+ }
+ }
+ fRefTimeMap.clear();
+ fTargetTimeMap.clear();
+ fViewer.getViewer().update(traces.get(0), null);
+
+ for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+ for (ITmfTrace parentTrace : TmfTraceManager.getInstance().getOpenedTraces()) {
+ for (ITmfTrace trace : TmfTraceManager.getTraceSet(parentTrace)) {
+ if (traceElement.getResource().equals(trace.getResource())) {
+ fRefTimeMap.put(traceElement, trace.getStartTime());
+ fViewer.getViewer().update(traceElement, null);
+ break;
+ }
+ }
+ if (fRefTimeMap.get(traceElement) != null) {
+ break;
+ }
+ }
+ }
+
+ /* open trace when double-clicking a tree item */
+ tree.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ TmfTraceElement traceElement = (TmfTraceElement) e.item.getData();
+ TmfOpenTraceHelper.openTraceFromElement(traceElement);
+ }
+ });
+
+ tree.setFocus();
+ }
+
+ private TreeViewerColumn createTreeViewerColumn(String title, int style) {
+ final TreeViewerColumn viewerColumn = new TreeViewerColumn(fViewer.getViewer(), style);
+ final TreeColumn column = viewerColumn.getColumn();
+ column.setText(title);
+ column.setResizable(true);
+ return viewerColumn;
+ }
+
+ private void setBasicMode() {
+ fAdvancedMode = false;
+ fRefTimeColumn.setData(WIDTH_KEY, fRefTimeColumn.getWidth());
+ fTargetTimeColumn.setData(WIDTH_KEY, fTargetTimeColumn.getWidth());
+ for (TreeItem treeItem : fViewer.getViewer().getTree().getItems()) {
+ Control editor = (Control) treeItem.getData(EDITOR_KEY);
+ editor.setVisible(false);
+ }
+ fTargetTimeColumn.setWidth(0);
+ fTargetTimeColumn.setResizable(false);
+ fRefTimeColumn.setWidth(0);
+ fRefTimeColumn.setResizable(false);
+ fButtonViewerColumn.getColumn().setWidth(0);
+ fAdvancedMessageLabel.setText(""); //$NON-NLS-1$
+ }
+
+ private void setAdvancedMode() {
+ fAdvancedMode = true;
+ fButtonViewerColumn.getColumn().setWidth(TREE_EDITOR_MIN_WIDTH);
+ fRefTimeColumn.setWidth((Integer) fRefTimeColumn.getData(WIDTH_KEY));
+ fRefTimeColumn.setResizable(true);
+ fTargetTimeColumn.setWidth((Integer) fTargetTimeColumn.getData(WIDTH_KEY));
+ fTargetTimeColumn.setResizable(true);
+ for (TreeItem treeItem : fViewer.getViewer().getTree().getItems()) {
+ Control editor = (Control) treeItem.getData(EDITOR_KEY);
+ editor.setVisible(true);
+ }
+ fAdvancedMessageLabel.setText(Messages.OffsetDialog_AdvancedMessage);
+ }
+
+ /**
+ * Handler for the event selected signal
+ *
+ * @param signal
+ * the event selected signal
+ */
+ @TmfSignalHandler
+ public void eventSelected(final TmfEventSelectedSignal signal) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+ if (traceElement.getResource().equals(signal.getEvent().getTrace().getResource())) {
+ fRefTimeMap.put(traceElement, signal.getEvent().getTimestamp());
+ fViewer.getViewer().update(traceElement, null);
+ break;
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Handler for the time selected signal
+ *
+ * @param signal
+ * the event selected signal
+ */
+ @TmfSignalHandler
+ public void timeSelected(final TmfSelectionRangeUpdatedSignal signal) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+ fTargetTimeMap.put(traceElement, signal.getBeginTime());
+ fViewer.getViewer().update(traceElement, null);
+ }
+ }
+ });
+ }
+
+ /**
+ * Handler for the trace opened signal
+ *
+ * @param signal
+ * the trace opened signal
+ */
+ @TmfSignalHandler
+ public void traceOpened(final TmfTraceOpenedSignal signal) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ for (ITmfTrace trace : TmfTraceManager.getTraceSet(signal.getTrace())) {
+ for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+ if (traceElement.getResource().equals(trace.getResource())) {
+ if (fRefTimeMap.get(traceElement) == null) {
+ fRefTimeMap.put(traceElement, trace.getStartTime());
+ fViewer.getViewer().update(traceElement, null);
+ }
+ break;
+ }
+ }
+ }
+ }
+ });
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/messages.properties
new file mode 100644
index 0000000000..af1de0d719
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/dialogs/offset/messages.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2014 Ericsson
+#
+# 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:
+# Matthew Khouzam - Initial API and implementation
+# Patrick Tasse - Initial API and implementation
+###############################################################################
+
+OffsetDialog_AdvancedButton=Advanced
+OffsetDialog_AdvancedMessage=Double-click a trace to open it, and select an event to set a reference time. \
+If the reference time and target time are set, press the button to compute their offset automatically. \
+The reference time and target time can be entered in format 'yyyy-mm-dd hh:mm:ss.sss sss sss'.
+OffsetDialog_BasicButton=Basic
+OffsetDialog_BasicMessage=Set the time offset to apply to each trace.
+OffsetDialog_OffsetTime=Offset in seconds
+OffsetDialog_ReferenceTime=Reference Time
+OffsetDialog_TargetTime=Target Time
+OffsetDialog_Title=Apply time offset
+OffsetDialog_TraceName=Trace name
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/BatchImportTraceHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/BatchImportTraceHandler.java
new file mode 100644
index 0000000000..4bac901458
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/BatchImportTraceHandler.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Bernd Hufmann - Simplify selection logic
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.BatchImportTraceWizard;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Batch import handler, spawn a wizard
+ *
+ * @author Matthew Khouzam
+ */
+public class BatchImportTraceHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ BatchImportTraceWizard w = new BatchImportTraceWizard();
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+
+ if (window == null) {
+ return false;
+ }
+
+ ISelection currentSelection = HandlerUtil.getCurrentSelection(event);
+
+ IStructuredSelection sec = StructuredSelection.EMPTY;
+ if (currentSelection instanceof IStructuredSelection) {
+ sec = (IStructuredSelection) currentSelection;
+ }
+
+ w.init(PlatformUI.getWorkbench(), sec);
+ WizardDialog dialog = new WizardDialog(window.getShell(), w);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java
new file mode 100644
index 0000000000..97968fe5f2
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.tracecompass.tmf.core.synchronization.TimestampTransformFactory;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Clear Trace Offset Handler
+ *
+ * @author Patrick Tasse
+ */
+public class ClearTraceOffsetHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+
+ // Get the set of selected trace elements
+ final Set<TmfTraceElement> traceElements = new HashSet<>();
+ if (selection instanceof StructuredSelection) {
+ Iterator<Object> iterator = ((StructuredSelection) selection).iterator();
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (element instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) element;
+ traceElements.add(trace.getElementUnderTraceFolder());
+ } else if (element instanceof TmfExperimentElement) {
+ TmfExperimentElement exp = (TmfExperimentElement) element;
+ for (TmfTraceElement trace : exp.getTraces()) {
+ traceElements.add(trace.getElementUnderTraceFolder());
+ }
+ } else if (element instanceof TmfTraceFolder) {
+ TmfTraceFolder folder = (TmfTraceFolder) element;
+ traceElements.addAll(folder.getTraces());
+ }
+ }
+ }
+
+ if (traceElements.isEmpty()) {
+ return null;
+ }
+
+ Shell shell = HandlerUtil.getActiveShellChecked(event);
+ MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION | SWT.CANCEL | SWT.OK);
+ mb.setText(Messages.ClearTraceOffsetHandler_Title);
+ mb.setMessage(Messages.ClearTraceOffsetHandler_ConfirmMessage);
+ if (mb.open() != SWT.OK) {
+ return null;
+ }
+
+ TmfWorkspaceModifyOperation operation = new TmfWorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ for (final TmfTraceElement trace : traceElements) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ if (!TimestampTransformFactory.getTimestampTransform(trace.getResource()).equals(TimestampTransformFactory.getDefaultTransform())) {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ trace.closeEditors();
+ }
+ });
+ trace.deleteSupplementaryResources();
+ TimestampTransformFactory.setTimestampTransform(trace.getResource(), null);
+ trace.refreshSupplementaryFolder();
+ }
+ }
+ }
+ };
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true, operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(shell, e.toString(), e.getTargetException().toString());
+ return null;
+ }
+
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyExperimentHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyExperimentHandler.java
new file mode 100644
index 0000000000..f8d3bc93d1
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyExperimentHandler.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Remove enable check
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.CopyExperimentDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * <b><u>CopyExperimentHandler</u></b>
+ * <p>
+ */
+public class CopyExperimentHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Get selection already validated by handler in plugin.xml
+ ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
+ if (!(selection instanceof IStructuredSelection)) {
+ return null;
+ }
+ TmfExperimentElement experiment = (TmfExperimentElement) ((IStructuredSelection) selection).getFirstElement();
+
+ // Fire the Copy Experiment dialog
+ Shell shell = HandlerUtil.getActiveShellChecked(event);
+ CopyExperimentDialog dialog = new CopyExperimentDialog(shell, experiment);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyTraceHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyTraceHandler.java
new file mode 100644
index 0000000000..f3c2bc7996
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/CopyTraceHandler.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Remove enable check
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.CopyTraceDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * <b><u>CopyTraceHandler</u></b>
+ * <p>
+ */
+public class CopyTraceHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Get selection already validated by handler in plugin.xml
+ ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
+ if (!(selection instanceof IStructuredSelection)) {
+ return null;
+ }
+ TmfTraceElement trace = (TmfTraceElement) ((IStructuredSelection) selection).getFirstElement();
+
+ // Fire the Copy Trace dialog
+ Shell shell = HandlerUtil.getActiveShellChecked(event);
+ CopyTraceDialog dialog = new CopyTraceDialog(shell, trace);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteExperimentHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteExperimentHandler.java
new file mode 100644
index 0000000000..a679e0e91b
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteExperimentHandler.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Close editors to release resources
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.util.Iterator;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>DeleteExperimentHandler</u></b>
+ * <p>
+ */
+public class DeleteExperimentHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Confirm the operation
+ Shell shell = window.getShell();
+ MessageBox confirmOperation = new MessageBox(shell, SWT.ICON_QUESTION | SWT.CANCEL | SWT.OK);
+ confirmOperation.setText(Messages.DeleteDialog_Title);
+ confirmOperation.setMessage(Messages.DeleteExperimentHandler_Message);
+ if (confirmOperation.open() != SWT.OK) {
+ return null;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return Boolean.FALSE;
+ }
+ ISelection selection = part.getSite().getSelectionProvider().getSelection();
+
+ if (selection instanceof TreeSelection) {
+ TreeSelection sel = (TreeSelection) selection;
+ Iterator<Object> iterator = sel.iterator();
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (element instanceof TmfExperimentElement) {
+ final TmfExperimentElement experiment = (TmfExperimentElement) element;
+ IResource resource = experiment.getResource();
+
+ try {
+ // Close the experiment if open
+ experiment.closeEditors();
+
+ IPath path = resource.getLocation();
+ if (path != null) {
+ // Delete supplementary files
+ experiment.deleteSupplementaryFolder();
+ }
+
+ // Finally, delete the experiment
+ resource.delete(true, null);
+
+ } catch (final CoreException e) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ final MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText(Messages.DeleteTraceHandler_Error + ' ' + experiment.getName());
+ mb.setMessage(e.getMessage());
+ mb.open();
+ }
+ });
+ Activator.getDefault().logError("Error deleting experiment: " + experiment.getName(), e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceFolderElementHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceFolderElementHandler.java
new file mode 100644
index 0000000000..22a5211b1e
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceFolderElementHandler.java
@@ -0,0 +1,349 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson, École Polytechnique de Montréal
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Close editors to release resources
+ * Geneviève Bastien - Moved the delete code to element model's classes
+ * Marc-Andre Laperle - Merged DeleteTraceHandler and DeleteFolderHandler
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * An handler for deletion of both traces and trace folders. It allows mixing
+ * both types of elements.
+ */
+public class DeleteTraceFolderElementHandler extends AbstractHandler {
+
+ private TreeSelection fSelection = null;
+
+ private enum DeleteType {
+ /**
+ * Only trace folders are selected.
+ */
+ DELETE_TRACE_FOLDERS,
+ /**
+ * Only traces are selected.
+ */
+ DELETE_TRACES,
+ /**
+ * A mix of different elements are selected.
+ */
+ DELETE_GENERIC,
+ /**
+ * Only Traces (top trace folders) are selected.
+ */
+ CLEAR_TRACES_FOLDER,
+ /**
+ * Only Traces under experiments are selected.
+ */
+ REMOVE_TRACES_FROM_EXPERIMENT
+ }
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ ISelection selection = selectionProvider.getSelection();
+
+ // Make sure selection contains only traces and trace folders
+ fSelection = null;
+ if (selection instanceof TreeSelection) {
+ fSelection = (TreeSelection) selection;
+ Iterator<Object> iterator = fSelection.iterator();
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (!(element instanceof TmfTraceElement) && !(element instanceof TmfTraceFolder)) {
+ return false;
+ }
+ }
+ }
+
+ // If we get here, either nothing is selected or everything is a trace or folder
+ return !selection.isEmpty();
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ private static DeleteType getDeleteType(ISelection selection) {
+ int numTracesFolder = 0;
+ int numTraceFolder = 0;
+ int numTraces = 0;
+ int numTracesUnderExperiment = 0;
+
+ @SuppressWarnings("rawtypes")
+ Iterator iterator = ((IStructuredSelection) selection).iterator();
+ while (iterator.hasNext()) {
+ Object next = iterator.next();
+ if ((next instanceof TmfTracesFolder)) {
+ numTracesFolder++;
+ } else if (next instanceof TmfTraceFolder) {
+ numTraceFolder++;
+ } else if (next instanceof TmfTraceElement) {
+ TmfTraceElement traceElement = (TmfTraceElement) next;
+ if (traceElement.getParent() instanceof TmfExperimentElement) {
+ numTracesUnderExperiment++;
+ } else {
+ numTraces++;
+ }
+ }
+ }
+
+ int total = numTraceFolder + numTracesFolder + numTracesUnderExperiment + numTraces;
+
+ if (numTracesFolder == total) {
+ return DeleteType.CLEAR_TRACES_FOLDER;
+ }
+
+ if (numTraceFolder == total) {
+ return DeleteType.DELETE_TRACE_FOLDERS;
+ }
+
+ if (numTraces == total) {
+ return DeleteType.DELETE_TRACES;
+ }
+
+ if (numTracesUnderExperiment == total) {
+ return DeleteType.REMOVE_TRACES_FROM_EXPERIMENT;
+ }
+
+ return DeleteType.DELETE_GENERIC;
+ }
+
+ private static String getTitle(final DeleteType deleteType) {
+ switch (deleteType)
+ {
+ case DELETE_GENERIC:
+ case DELETE_TRACES:
+ case DELETE_TRACE_FOLDERS:
+ return Messages.DeleteDialog_Title;
+ case CLEAR_TRACES_FOLDER:
+ return Messages.ClearDialog_Title;
+ case REMOVE_TRACES_FROM_EXPERIMENT:
+ return Messages.RemoveDialog_Title;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private static String getMessage(DeleteType deleteType) {
+ switch (deleteType)
+ {
+ case DELETE_GENERIC:
+ return Messages.DeleteTraceHandlerGeneric_Message;
+ case DELETE_TRACES:
+ return Messages.DeleteTraceHandler_Message;
+ case CLEAR_TRACES_FOLDER:
+ return Messages.DeleteFolderHandlerClear_Message;
+ case DELETE_TRACE_FOLDERS:
+ return Messages.DeleteFolderHandler_Message;
+ case REMOVE_TRACES_FROM_EXPERIMENT:
+ return Messages.RemoveTraceFromExperimentHandler_Message;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private static String getTraceErrorMessage(DeleteType deleteType) {
+ return deleteType == DeleteType.REMOVE_TRACES_FROM_EXPERIMENT ? Messages.RemoveTraceFromExperimentHandler_Error : Messages.DeleteFolderHandler_Error;
+ }
+
+ private static String getFolderErrorMessage(DeleteType deleteType) {
+ return deleteType == DeleteType.CLEAR_TRACES_FOLDER ? Messages.DeleteFolderHandlerClear_Error : Messages.DeleteFolderHandler_Error;
+ }
+
+ private static String getTraceTaskName(DeleteType deleteType) {
+ return deleteType == DeleteType.REMOVE_TRACES_FROM_EXPERIMENT ? Messages.RemoveTraceFromExperimentHandler_TaskName : Messages.DeleteFolderHandler_TaskName;
+ }
+
+ private static String getTraceFolderTaskName(DeleteType deleteType) {
+ return deleteType == DeleteType.CLEAR_TRACES_FOLDER ? Messages.DeleteFolderHandlerClear_TaskName : Messages.DeleteFolderHandler_TaskName;
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Get the selection
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (!(selection instanceof IStructuredSelection)) {
+ return null;
+ }
+ final DeleteType deleteType = getDeleteType(selection);
+
+ // Confirm the operation
+ Shell shell = window.getShell();
+ MessageBox confirmOperation = new MessageBox(shell, SWT.ICON_QUESTION | SWT.CANCEL | SWT.OK);
+ confirmOperation.setText(getTitle(deleteType));
+ confirmOperation.setMessage(getMessage(deleteType));
+ if (confirmOperation.open() != SWT.OK) {
+ return null;
+ }
+
+ final Iterator<Object> iterator = fSelection.iterator();
+ final int nbElements = fSelection.size();
+
+ TmfWorkspaceModifyOperation operation = new TmfWorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ SubMonitor subMonitor = SubMonitor.convert(monitor, nbElements);
+
+ while (iterator.hasNext()) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ Object element = iterator.next();
+ SubProgressMonitor elementSubMonitor = new SubProgressMonitor(subMonitor, 1);
+ if (element instanceof TmfTraceElement) {
+ final TmfTraceElement trace = (TmfTraceElement) element;
+ if (!trace.getResource().exists()) {
+ continue;
+ }
+ subMonitor.setTaskName(getTraceTaskName(deleteType) + " " + trace.getElementPath()); //$NON-NLS-1$
+ try {
+ SubMonitor deleteSubMonitor = SubMonitor.convert(elementSubMonitor, 1);
+ trace.delete(deleteSubMonitor);
+ } catch (final CoreException e) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ final MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText(getTraceErrorMessage(deleteType) + ' ' + trace.getName());
+ mb.setMessage(e.getMessage());
+ mb.open();
+ }
+ });
+ Activator.getDefault().logError(getTraceErrorMessage(deleteType) + trace.getName(), e);
+ }
+ } else if (element instanceof TmfTraceFolder) {
+ final TmfTraceFolder folder = (TmfTraceFolder) element;
+ final IResource resource = folder.getResource();
+ if (!resource.exists()) {
+ continue;
+ }
+
+ subMonitor.setTaskName(getTraceFolderTaskName(deleteType) + " " + folder.getPath()); //$NON-NLS-1$
+
+ try {
+ // delete all traces under this folder
+ SubMonitor childrenSubMonitor = SubMonitor.convert(elementSubMonitor, folder.getTraces().size() + 1);
+ for (TmfTraceElement traceElement : folder.getTraces()) {
+ SubProgressMonitor deleteSubMonitor = new SubProgressMonitor(childrenSubMonitor, 1);
+ traceElement.delete(deleteSubMonitor);
+ }
+
+ // Finally, delete the folder. For the Traces
+ // folder, we only delete the children since the
+ // folder should always be there.
+ final SubProgressMonitor deleteSubMonitor = new SubProgressMonitor(subMonitor, 1);
+ if (folder instanceof TmfTracesFolder) {
+ resource.accept(new IResourceVisitor() {
+ @Override
+ public boolean visit(IResource visitedResource) throws CoreException {
+ if (visitedResource != resource) {
+ visitedResource.delete(true, deleteSubMonitor);
+ }
+ return true;
+ }
+ }, IResource.DEPTH_ONE, 0);
+ } else {
+ resource.delete(true, deleteSubMonitor);
+ }
+ childrenSubMonitor.done();
+ } catch (final CoreException e) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ final MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText(getFolderErrorMessage(deleteType) + ' ' + folder.getName());
+ mb.setMessage(e.getMessage());
+ mb.open();
+ }
+ });
+ Activator.getDefault().logError(getFolderErrorMessage(deleteType) + folder.getName(), e);
+ }
+ }
+ subMonitor.setTaskName(""); //$NON-NLS-1$
+ elementSubMonitor.done();
+ }
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true, operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(window.getShell(), e.toString(), e.getTargetException().toString());
+ return null;
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceSupplementaryFilesHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceSupplementaryFilesHandler.java
new file mode 100644
index 0000000000..982849a2e8
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DeleteTraceSupplementaryFilesHandler.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Ericsson
+ *
+ * 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:
+ * Bernd Hufmann - Initial API and implementation
+ * Patrick Tasse - Close editors to release resources
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.SelectSupplementaryResourcesDialog;
+import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.TreeMultimap;
+
+/**
+ * Handler for Delete Supplementary Files command on trace
+ */
+public class DeleteTraceSupplementaryFilesHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Inner classes
+ // ------------------------------------------------------------------------
+
+ private class ElementComparator implements Comparator<TmfCommonProjectElement> {
+ @Override
+ public int compare(TmfCommonProjectElement e1, TmfCommonProjectElement e2) {
+ return e1.getPath().toString().compareTo(e2.getPath().toString());
+ }
+ }
+
+ private class ResourceComparator implements Comparator<IResource> {
+ @Override
+ public int compare(IResource r1, IResource r2) {
+ return r1.getFullPath().toString().compareTo(r2.getFullPath().toString());
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Get the selection
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (!(selection instanceof IStructuredSelection)) {
+ return null;
+ }
+ final Multimap<TmfCommonProjectElement, IResource> resourceMap =
+ TreeMultimap.create(new ElementComparator(), new ResourceComparator());
+ final Iterator<Object> iterator = ((IStructuredSelection) selection).iterator();
+
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (element instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) element;
+ // If trace is under an experiment, use the original trace from the traces folder
+ trace = trace.getElementUnderTraceFolder();
+ for (IResource resource : trace.getSupplementaryResources()) {
+ resourceMap.put(trace, resource);
+ }
+
+ } else if (element instanceof TmfExperimentElement) {
+ TmfExperimentElement experiment = (TmfExperimentElement) element;
+ for (IResource resource : experiment.getSupplementaryResources()) {
+ resourceMap.put(experiment, resource);
+ }
+ for (TmfTraceElement trace : experiment.getTraces()) {
+ // If trace is under an experiment, use the original trace from the traces folder
+ trace = trace.getElementUnderTraceFolder();
+ for (IResource resource : trace.getSupplementaryResources()) {
+ resourceMap.put(trace, resource);
+ }
+ }
+ }
+ }
+
+ final SelectSupplementaryResourcesDialog dialog =
+ new SelectSupplementaryResourcesDialog(window.getShell(), resourceMap);
+ if (dialog.open() != Window.OK) {
+ return null;
+ }
+
+ TmfWorkspaceModifyOperation operation = new TmfWorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+
+ Set<IProject> projectsToRefresh = new HashSet<>();
+
+ // Delete the resources that were selected
+ List<IResource> allResourcesToDelete = Arrays.asList(dialog.getResources());
+
+ SubMonitor subMonitor = SubMonitor.convert(monitor, allResourcesToDelete.size());
+
+ for (final TmfCommonProjectElement element : resourceMap.keySet()) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ List<IResource> traceResourcesToDelete = new ArrayList<>(resourceMap.get(element));
+ traceResourcesToDelete.retainAll(allResourcesToDelete);
+ if (!traceResourcesToDelete.isEmpty()) {
+ subMonitor.setTaskName(NLS.bind(Messages.DeleteSupplementaryFiles_DeletionTask, element.getElementPath()));
+ // Delete the selected resources
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ element.closeEditors();
+ }
+ });
+ element.deleteSupplementaryResources(traceResourcesToDelete.toArray(new IResource[0]));
+ projectsToRefresh.add(element.getProject().getResource());
+ }
+ subMonitor.worked(traceResourcesToDelete.size());
+ }
+
+ subMonitor = SubMonitor.convert(monitor, projectsToRefresh.size());
+
+ // Refresh projects
+ Iterator<IProject> projectIterator = projectsToRefresh.iterator();
+ while (projectIterator.hasNext()) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ IProject project = projectIterator.next();
+ subMonitor.setTaskName(NLS.bind(Messages.DeleteSupplementaryFiles_ProjectRefreshTask, project.getName()));
+ try {
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ } catch (CoreException e) {
+ Activator.getDefault().logError("Error refreshing project " + project, e); //$NON-NLS-1$
+ }
+ subMonitor.worked(1);
+ }
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true, operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(window.getShell(), e.toString(), e.getTargetException().toString());
+ return null;
+ }
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DropAdapterAssistant.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DropAdapterAssistant.java
new file mode 100644
index 0000000000..c8089b9409
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/DropAdapterAssistant.java
@@ -0,0 +1,669 @@
+/*******************************************************************************
+* Copyright (c) 2012, 2014 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ * Patrick Tasse - Add support for DROP_LINK and rename prompt on name clash
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.editors.ITmfEventsEditorConstants;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.tracecompass.tmf.ui.project.model.ITmfProjectModelElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.navigator.CommonDropAdapter;
+import org.eclipse.ui.navigator.CommonDropAdapterAssistant;
+import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+
+/**
+ * Drop adapter assistant for project explorer
+ */
+public class DropAdapterAssistant extends CommonDropAdapterAssistant {
+
+ /**
+ * Default constructor
+ */
+ public DropAdapterAssistant() {
+ }
+
+ @Override
+ public boolean isSupportedType(TransferData aTransferType) {
+ return super.isSupportedType(aTransferType) || FileTransfer.getInstance().isSupportedType(aTransferType);
+ }
+
+ @Override
+ public IStatus validateDrop(Object target, int operation, TransferData transferType) {
+ if (target instanceof TmfTraceFolder) {
+ return Status.OK_STATUS;
+ }
+ if (target instanceof TmfExperimentElement) {
+ return Status.OK_STATUS;
+ }
+ if (target instanceof TmfTraceElement) {
+ ITmfProjectModelElement parent = ((TmfTraceElement) target).getParent();
+ if (parent instanceof TmfTraceFolder) {
+ return Status.OK_STATUS;
+ }
+ if (parent instanceof TmfExperimentElement) {
+ return Status.OK_STATUS;
+ }
+ }
+ if (target instanceof IProject) {
+ return Status.OK_STATUS;
+ }
+ return Status.CANCEL_STATUS;
+ }
+
+ @Override
+ public IStatus handleDrop(CommonDropAdapter aDropAdapter, DropTargetEvent aDropTargetEvent, Object aTarget) {
+ boolean ok = false;
+
+ // Use local variable to avoid parameter assignment
+ Object targetToUse = aTarget;
+
+ int operation = aDropTargetEvent.detail;
+ if (operation != DND.DROP_LINK) {
+ operation = DND.DROP_COPY;
+ }
+
+ // If target is a trace, use its parent (either trace folder or experiment)
+ if (targetToUse instanceof TmfTraceElement) {
+ targetToUse = ((TmfTraceElement) targetToUse).getParent();
+ }
+
+ // If target is a project, use its trace folder
+ if (targetToUse instanceof IProject) {
+ TmfProjectElement projectElement = TmfProjectRegistry.getProject((IProject) targetToUse, true);
+ if (projectElement != null) {
+ targetToUse = projectElement.getTracesFolder();
+ }
+ }
+
+ if (aDropTargetEvent.data instanceof IStructuredSelection) {
+ IStructuredSelection selection = (IStructuredSelection) aDropTargetEvent.data;
+ for (Object source : selection.toArray()) {
+ if (source instanceof IResource) {
+ // If source resource is a trace, use the trace element
+ IResource sourceResource = (IResource) source;
+ TmfProjectElement projectElement = TmfProjectRegistry.getProject(sourceResource.getProject());
+ if (projectElement != null && projectElement.getTracesFolder() != null) {
+ for (TmfTraceElement trace : projectElement.getTracesFolder().getTraces()) {
+ if (trace.getResource().equals(sourceResource)) {
+ source = trace;
+ break;
+ }
+ }
+ }
+ }
+ if (source instanceof TmfTraceElement) {
+ TmfTraceElement sourceTrace = (TmfTraceElement) source;
+ // If source trace is under an experiment, use the original trace from the traces folder
+ sourceTrace = sourceTrace.getElementUnderTraceFolder();
+ if (targetToUse instanceof TmfExperimentElement) {
+ TmfExperimentElement targetExperiment = (TmfExperimentElement) targetToUse;
+ ok |= drop(sourceTrace, targetExperiment, operation);
+ } else if (targetToUse instanceof TmfTraceFolder) {
+ TmfTraceFolder traceFolder = (TmfTraceFolder) targetToUse;
+ ok |= drop(sourceTrace, traceFolder, operation);
+ }
+ } else if (source instanceof IResource) {
+ IResource sourceResource = (IResource) source;
+ if (sourceResource.getType() != IResource.FILE && sourceResource.getType() != IResource.FOLDER) {
+ continue;
+ }
+ if (targetToUse instanceof TmfExperimentElement) {
+ TmfExperimentElement targetExperiment = (TmfExperimentElement) targetToUse;
+ ok |= (drop(sourceResource, targetExperiment, operation) != null);
+ } else if (targetToUse instanceof TmfTraceFolder) {
+ TmfTraceFolder traceFolder = (TmfTraceFolder) targetToUse;
+ ok |= (drop(sourceResource, traceFolder, operation) != null);
+ }
+ }
+ }
+ } else if (aDropTargetEvent.data instanceof String[]) {
+ String[] sources = (String[]) aDropTargetEvent.data;
+ for (String source : sources) {
+ Path path = new Path(source);
+ if (targetToUse instanceof TmfExperimentElement) {
+ TmfExperimentElement targetExperiment = (TmfExperimentElement) targetToUse;
+ ok |= drop(path, targetExperiment, operation);
+ } else if (targetToUse instanceof TmfTraceFolder) {
+ TmfTraceFolder traceFolder = (TmfTraceFolder) targetToUse;
+ ok |= drop(path, traceFolder, operation);
+ }
+ }
+ }
+ return (ok ? Status.OK_STATUS : Status.CANCEL_STATUS);
+ }
+
+
+ /**
+ * Drop a trace by copying/linking a trace element in a target experiment
+ *
+ * @param sourceTrace the source trace element to copy
+ * @param targetExperiment the target experiment
+ * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
+ * @return true if successful
+ */
+ private static boolean drop(TmfTraceElement sourceTrace,
+ TmfExperimentElement targetExperiment,
+ int operation) {
+
+ IResource sourceResource = sourceTrace.getResource();
+ IResource targetResource = drop(sourceResource, targetExperiment, operation);
+
+ if (targetResource != null) {
+ if (! sourceTrace.getProject().equals(targetExperiment.getProject())) {
+ IFolder destinationSupplementaryFolder = targetExperiment.getTraceSupplementaryFolder(targetResource.getName());
+ sourceTrace.copySupplementaryFolder(destinationSupplementaryFolder);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Drop a trace by copying/linking a resource in a target experiment
+ *
+ * @param sourceResource the source resource
+ * @param targetExperiment the target experiment
+ * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
+ * @return the target resource or null if unsuccessful
+ */
+ private static IResource drop(IResource sourceResource,
+ TmfExperimentElement targetExperiment,
+ int operation) {
+
+ IResource traceResource = sourceResource;
+
+ IPath tracesFolderPath = targetExperiment.getProject().getTracesFolder().getPath();
+ if (tracesFolderPath.isPrefixOf(sourceResource.getFullPath())) {
+ String elementPath = sourceResource.getFullPath().makeRelativeTo(tracesFolderPath).toString();
+ for (TmfTraceElement trace : targetExperiment.getTraces()) {
+ if (trace.getElementPath().equals(elementPath)) {
+ return null;
+ }
+ }
+ } else {
+ String targetName = sourceResource.getName();
+ for (ITmfProjectModelElement element : targetExperiment.getProject().getTracesFolder().getChildren()) {
+ if (element.getName().equals(targetName)) {
+ targetName = promptRename(element);
+ if (targetName == null) {
+ return null;
+ }
+ break;
+ }
+ }
+ try {
+ if (operation == DND.DROP_COPY && !sourceResource.isLinked()) {
+ IPath destination = targetExperiment.getProject().getTracesFolder().getResource().getFullPath().addTrailingSeparator().append(targetName);
+ sourceResource.copy(destination, false, null);
+ cleanupBookmarks(destination);
+ } else {
+ createLink(targetExperiment.getProject().getTracesFolder().getResource(), sourceResource, targetName);
+ }
+ // use the copied resource for the experiment
+ if (sourceResource.getType() == IResource.FILE) {
+ traceResource = targetExperiment.getProject().getTracesFolder().getResource().getFile(targetName);
+ } else if (sourceResource.getType() == IResource.FOLDER) {
+ traceResource = targetExperiment.getProject().getTracesFolder().getResource().getFolder(targetName);
+ }
+ String sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION);
+ if (sourceLocation == null) {
+ sourceLocation = URIUtil.toUnencodedString(new File(sourceResource.getLocationURI()).toURI());
+ }
+ traceResource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ } catch (CoreException e) {
+ displayException(e);
+ return null;
+ }
+ }
+ if (traceResource != null && traceResource.exists()) {
+ setTraceType(traceResource);
+ for (TmfTraceElement trace : targetExperiment.getProject().getTracesFolder().getTraces()) {
+ if (trace.getResource().equals(traceResource)) {
+ targetExperiment.addTrace(trace);
+ targetExperiment.closeEditors();
+ targetExperiment.deleteSupplementaryResources();
+ break;
+ }
+ }
+ return traceResource;
+ }
+ return null;
+ }
+
+ /**
+ * Drop a trace by copying/linking a trace element in a trace folder
+ *
+ * @param sourceTrace the source trace
+ * @param traceFolder the target trace folder
+ * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
+ * @return true if successful
+ */
+ private static boolean drop(TmfTraceElement sourceTrace,
+ TmfTraceFolder traceFolder,
+ int operation) {
+
+ IResource sourceResource = sourceTrace.getResource();
+ IResource targetResource = drop(sourceResource, traceFolder, operation);
+
+ if (targetResource != null) {
+ String elementPath = targetResource.getFullPath().makeRelativeTo(traceFolder.getProject().getTracesFolder().getPath()).toString();
+ IFolder destinationSupplementaryFolder = traceFolder.getTraceSupplementaryFolder(elementPath);
+ sourceTrace.copySupplementaryFolder(destinationSupplementaryFolder);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Drop a trace by copying/linking a resource in a trace folder
+ *
+ * @param sourceResource the source resource
+ * @param traceFolder the target trace folder
+ * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
+ * @return the target resource or null if unsuccessful
+ */
+ private static IResource drop(IResource sourceResource,
+ TmfTraceFolder traceFolder,
+ int operation) {
+
+ if (sourceResource.getParent().equals(traceFolder.getResource())) {
+ return null;
+ }
+ String targetName = sourceResource.getName();
+ for (ITmfProjectModelElement element : traceFolder.getChildren()) {
+ if (element.getName().equals(targetName)) {
+ targetName = promptRename(element);
+ if (targetName == null) {
+ return null;
+ }
+ break;
+ }
+ }
+ try {
+ if (operation == DND.DROP_COPY && !sourceResource.isLinked()) {
+ IPath destination = traceFolder.getResource().getFullPath().addTrailingSeparator().append(targetName);
+ sourceResource.copy(destination, false, null);
+ cleanupBookmarks(destination);
+ } else {
+ createLink(traceFolder.getResource(), sourceResource, targetName);
+ }
+ IResource traceResource = traceFolder.getResource().findMember(targetName);
+ if (traceResource != null && traceResource.exists()) {
+ String sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION);
+ if (sourceLocation == null) {
+ sourceLocation = URIUtil.toUnencodedString(new File(sourceResource.getLocationURI()).toURI());
+ }
+ traceResource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ setTraceType(traceResource);
+ }
+ return traceResource;
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ return null;
+ }
+
+ /**
+ * Drop a trace by importing/linking a path in a target experiment
+ *
+ * @param path the source path
+ * @param targetExperiment the target experiment
+ * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
+ * @return true if successful
+ */
+ private static boolean drop(Path path,
+ TmfExperimentElement targetExperiment,
+ int operation) {
+
+ IPath tracesFolderPath = targetExperiment.getProject().getTracesFolder().getResource().getLocation();
+ IResource traceResource = null;
+ if (tracesFolderPath.isPrefixOf(path)) {
+ String elementPath = path.makeRelativeTo(tracesFolderPath).toString();
+ for (TmfTraceElement trace : targetExperiment.getTraces()) {
+ if (trace.getElementPath().equals(elementPath)) {
+ return false;
+ }
+ }
+ traceResource = targetExperiment.getProject().getTracesFolder().getResource().findMember(elementPath);
+ } else {
+ String targetName = path.lastSegment();
+ for (ITmfProjectModelElement element : targetExperiment.getProject().getTracesFolder().getChildren()) {
+ if (element.getName().equals(targetName)) {
+ targetName = promptRename(element);
+ if (targetName == null) {
+ return false;
+ }
+ break;
+ }
+ }
+ if (operation == DND.DROP_COPY) {
+ importTrace(targetExperiment.getProject().getTracesFolder().getResource(), path, targetName);
+ } else {
+ createLink(targetExperiment.getProject().getTracesFolder().getResource(), path, targetName);
+ }
+ // use the copied resource for the experiment
+ File file = new File(path.toString());
+ if (file.exists() && file.isFile()) {
+ traceResource = targetExperiment.getProject().getTracesFolder().getResource().getFile(targetName);
+ } else if (file.exists() && file.isDirectory()) {
+ traceResource = targetExperiment.getProject().getTracesFolder().getResource().getFolder(targetName);
+ }
+ }
+ if (traceResource != null && traceResource.exists()) {
+ try {
+ String sourceLocation = URIUtil.toUnencodedString(path.toFile().toURI());
+ traceResource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ setTraceType(traceResource);
+ for (TmfTraceElement trace : targetExperiment.getProject().getTracesFolder().getTraces()) {
+ if (trace.getResource().equals(traceResource)) {
+ targetExperiment.addTrace(trace);
+ targetExperiment.closeEditors();
+ targetExperiment.deleteSupplementaryResources();
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Drop a trace by importing/linking a path in a trace folder
+ *
+ * @param path the source path
+ * @param traceFolder the target trace folder
+ * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
+ * @return true if successful
+ */
+ private static boolean drop(Path path,
+ TmfTraceFolder traceFolder,
+ int operation) {
+
+ String targetName = path.lastSegment();
+ for (ITmfProjectModelElement element : traceFolder.getChildren()) {
+ if (element.getName().equals(targetName)) {
+ targetName = promptRename(element);
+ if (targetName == null) {
+ return false;
+ }
+ break;
+ }
+ }
+ if (operation == DND.DROP_COPY) {
+ importTrace(traceFolder.getResource(), path, targetName);
+ } else {
+ createLink(traceFolder.getResource(), path, targetName);
+ }
+ IResource traceResource = traceFolder.getResource().findMember(targetName);
+ if (traceResource != null && traceResource.exists()) {
+ try {
+ String sourceLocation = URIUtil.toUnencodedString(path.toFile().toURI());
+ traceResource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ setTraceType(traceResource);
+ }
+ return true;
+ }
+
+ /**
+ * Import a trace to the trace folder
+ *
+ * @param folder the trace folder resource
+ * @param path the path to the trace to import
+ * @param targetName the target name
+ */
+ private static void importTrace(final IFolder folder, final Path path, final String targetName) {
+ final File source = new File(path.toString());
+ if (source.isDirectory()) {
+ IPath containerPath = folder.getFullPath().addTrailingSeparator().append(targetName);
+ IOverwriteQuery overwriteImplementor = new IOverwriteQuery() {
+ @Override
+ public String queryOverwrite(String pathString) {
+ return IOverwriteQuery.NO_ALL;
+ }
+ };
+ List<File> filesToImport = Arrays.asList(source.listFiles());
+ ImportOperation operation = new ImportOperation(
+ containerPath,
+ source,
+ FileSystemStructureProvider.INSTANCE,
+ overwriteImplementor,
+ filesToImport);
+ operation.setCreateContainerStructure(false);
+ try {
+ operation.run(new NullProgressMonitor());
+ } catch (InvocationTargetException e) {
+ displayException(e);
+ } catch (InterruptedException e) {
+ displayException(e);
+ }
+ } else {
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ try (InputStream inputStream = new FileInputStream(source);) {
+ IFile targetFile = folder.getFile(targetName);
+ targetFile.create(inputStream, IResource.NONE, monitor);
+ } catch (CoreException | IOException e) {
+ displayException(e);
+ }
+ }
+ };
+ WorkspaceModifyDelegatingOperation operation = new WorkspaceModifyDelegatingOperation(runnable);
+ try {
+ operation.run(new NullProgressMonitor());
+ } catch (InvocationTargetException e) {
+ displayException(e);
+ } catch (InterruptedException e) {
+ displayException(e);
+ }
+ }
+ }
+
+ /**
+ * Create a link to the actual trace and set the trace type
+ *
+ * @param parentFolder the parent folder
+ * @param resource the resource
+ * @param targetName the target name
+ */
+ private static void createLink(IFolder parentFolder, IResource resource, String targetName) {
+ IPath location = resource.getLocation();
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ try {
+ String traceType = TmfTraceType.getTraceTypeId(resource);
+ TraceTypeHelper traceTypeHelper = TmfTraceType.getTraceType(traceType);
+
+ if (resource instanceof IFolder) {
+ IFolder folder = parentFolder.getFolder(targetName);
+ IStatus result = workspace.validateLinkLocation(folder, location);
+ if (result.isOK() || result.matches(IStatus.INFO | IStatus.WARNING)) {
+ folder.createLink(location, IResource.REPLACE, null);
+ if (traceTypeHelper != null) {
+ TmfTraceTypeUIUtils.setTraceType(folder, traceTypeHelper);
+ }
+ } else {
+ Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
+ }
+ } else {
+ IFile file = parentFolder.getFile(targetName);
+ IStatus result = workspace.validateLinkLocation(file, location);
+ if (result.isOK() || result.matches(IStatus.INFO | IStatus.WARNING)) {
+ file.createLink(location, IResource.REPLACE, null);
+ if (traceTypeHelper != null) {
+ TmfTraceTypeUIUtils.setTraceType(file, traceTypeHelper);
+ }
+ } else {
+ Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
+ }
+ }
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ }
+
+ /**
+ * Create a link to a file or folder
+ *
+ * @param parentFolder the parent folder
+ * @param source the file or folder
+ * @param targetName the target name
+ */
+ private static void createLink(IFolder parentFolder, IPath location, String targetName) {
+ File source = new File(location.toString());
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ try {
+
+ if (source.isDirectory()) {
+ IFolder folder = parentFolder.getFolder(targetName);
+ IStatus result = workspace.validateLinkLocation(folder, location);
+ if (result.isOK() || result.matches(IStatus.INFO | IStatus.WARNING)) {
+ folder.createLink(location, IResource.REPLACE, null);
+ } else {
+ Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
+ }
+ } else {
+ IFile file = parentFolder.getFile(targetName);
+ IStatus result = workspace.validateLinkLocation(file, location);
+ if (result.isOK() || result.matches(IStatus.INFO | IStatus.WARNING)) {
+ file.createLink(location, IResource.REPLACE, null);
+ } else {
+ Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
+ }
+ }
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ }
+
+ /**
+ * Prompts the user to rename a trace
+ *
+ * @param element the conflicting element
+ * @return the new name to use or null if rename is canceled
+ */
+ private static String promptRename(ITmfProjectModelElement element) {
+ MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.ICON_QUESTION | SWT.CANCEL | SWT.OK);
+ mb.setText(Messages.DropAdapterAssistant_RenameTraceTitle);
+ mb.setMessage(NLS.bind(Messages.DropAdapterAssistant_RenameTraceMessage, element.getName()));
+ if (mb.open() != SWT.OK) {
+ return null;
+ }
+ IContainer folder = element.getResource().getParent();
+ int i = 2;
+ while (true) {
+ String name = element.getName() + '(' + Integer.toString(i++) + ')';
+ IResource resource = folder.findMember(name);
+ if (resource == null) {
+ return name;
+ }
+ }
+ }
+
+ /**
+ * Cleanup bookmarks file in copied trace
+ */
+ private static void cleanupBookmarks(IPath path) {
+ IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(path);
+ if (folder.exists()) {
+ try {
+ for (IResource member : folder.members()) {
+ if (ITmfEventsEditorConstants.TRACE_INPUT_TYPE_CONSTANTS.contains(TmfTraceType.getTraceTypeId(member))) {
+ member.delete(true, null);
+ }
+ }
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ }
+ }
+
+ private static void setTraceType(IResource traceResource) {
+ try {
+ String traceType = TmfTraceType.getTraceTypeId(traceResource);
+ TraceTypeHelper traceTypeHelper = TmfTraceType.getTraceType(traceType);
+ if (traceTypeHelper == null) {
+ traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(traceResource.getLocation().toOSString(), null, null);
+ }
+ if (traceTypeHelper != null) {
+ TmfTraceTypeUIUtils.setTraceType(traceResource, traceTypeHelper);
+ }
+ } catch (TmfTraceImportException e) {
+ } catch (CoreException e) {
+ displayException(e);
+ }
+ }
+
+ /**
+ * Display an exception in a message box
+ *
+ * @param e the exception
+ */
+ private static void displayException(Exception e) {
+ MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText(e.getClass().getName());
+ mb.setMessage(e.getMessage());
+ mb.open();
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ImportTraceHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ImportTraceHandler.java
new file mode 100644
index 0000000000..ead339d9b3
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/ImportTraceHandler.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Bernd Hufmann - Update selection handling
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportTraceWizard;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * <b><u>ImportTraceHandler</u></b>
+ * <p>
+ * Starts an ImportTraceWizard that will handle the lowly details.
+ */
+public class ImportTraceHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ImportTraceWizard w = new ImportTraceWizard();
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+
+ if (window == null) {
+ return false;
+ }
+
+ ISelection currentSelection = HandlerUtil.getCurrentSelection(event);
+ // Menu Selection is only not null for context-sensitive menu
+ ISelection menuSelection = HandlerUtil.getActiveMenuSelection(event);
+
+ IStructuredSelection sec = StructuredSelection.EMPTY;
+
+ // Only use the selection if handler is called from context-sensitive menu
+ if ((menuSelection != null) && (currentSelection instanceof IStructuredSelection)) {
+ sec = (IStructuredSelection) currentSelection;
+ }
+
+ w.init(PlatformUI.getWorkbench(), sec);
+ WizardDialog dialog = new WizardDialog(window.getShell(), w);
+ dialog.open();
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/Messages.java
new file mode 100644
index 0000000000..0314b68990
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/Messages.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Added drag and drop messages
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages file
+ *
+ * @author Francois Chouinard
+ * @version 1.0
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.ui.project.handlers.messages"; //$NON-NLS-1$
+
+ public static String DeleteDialog_Title;
+ public static String DeleteTraceHandler_Message;
+ public static String DeleteTraceHandler_Error;
+ public static String DeleteTraceHandler_TaskName;
+ public static String DeleteTraceHandlerGeneric_Message;
+ public static String DeleteTraceHandlerGeneric_Error;
+ public static String DeleteExperimentHandler_Message;
+ public static String DeleteExperimentHandler_Error;
+ public static String DeleteFolderHandler_Message;
+ public static String DeleteFolderHandler_Error;
+ public static String DeleteFolderHandler_TaskName;
+
+ public static String RemoveDialog_Title;
+ public static String RemoveTraceFromExperimentHandler_Message;
+ public static String RemoveTraceFromExperimentHandler_TaskName;
+ public static String RemoveTraceFromExperimentHandler_Error;
+ public static String ClearDialog_Title;
+ public static String DeleteFolderHandlerClear_Message;
+ public static String DeleteFolderHandlerClear_Error;
+ public static String DeleteFolderHandlerClear_TaskName;
+
+ public static String SelectTraceTypeHandler_ErrorSelectingTrace;
+ public static String SelectTraceTypeHandler_Title;
+ public static String SelectTraceTypeHandler_TraceFailedValidation;
+ public static String SelectTraceTypeHandler_TracesFailedValidation;
+ public static String SelectTraceTypeHandler_InvalidTraceType;
+
+ public static String DropAdapterAssistant_RenameTraceTitle;
+ public static String DropAdapterAssistant_RenameTraceMessage;
+
+ public static String SynchronizeTracesHandler_InitError;
+ public static String SynchronizeTracesHandler_CopyProblem;
+ public static String SynchronizeTracesHandler_WrongType;
+ public static String SynchronizeTracesHandler_WrongTraceNumber;
+ public static String SynchronizeTracesHandler_Title;
+ public static String SynchronizeTracesHandler_Error;
+ public static String SynchronizeTracesHandler_ErrorSynchingExperiment;
+ public static String SynchronizeTracesHandler_ErrorSynchingForTrace;
+
+ public static String ClearTraceOffsetHandler_Title;
+ public static String ClearTraceOffsetHandler_ConfirmMessage;
+
+ public static String DeleteSupplementaryFiles_DeletionTask;
+ public static String DeleteSupplementaryFiles_ProjectRefreshTask;
+
+ public static String AnalysisModule_Help;
+
+ public static String TmfActionProvider_OpenWith;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewExperimentHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewExperimentHandler.java
new file mode 100644
index 0000000000..0548db66bc
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewExperimentHandler.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentFolder;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.NewExperimentDialog;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>NewExperimentHandler</u></b>
+ * <p>
+ */
+public class NewExperimentHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return Boolean.FALSE;
+ }
+ ISelection selection = part.getSite().getSelectionProvider().getSelection();
+ TmfExperimentFolder experimentFolder = null;
+ if (selection instanceof TreeSelection) {
+ TreeSelection sel = (TreeSelection) selection;
+ Object element = sel.getFirstElement();
+ if (element instanceof TmfExperimentFolder) {
+ experimentFolder = (TmfExperimentFolder) element;
+ }
+ }
+ if (experimentFolder == null) {
+ return null;
+ }
+
+ // Fire the New Experiment dialog
+ Shell shell = window.getShell();
+ NewExperimentDialog dialog = new NewExperimentDialog(shell, experimentFolder);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewFolderHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewFolderHandler.java
new file mode 100644
index 0000000000..c189f11b4e
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/NewFolderHandler.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.NewFolderDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for the New Folder command.
+ */
+public class NewFolderHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (!(selection instanceof IStructuredSelection)) {
+ return null;
+ }
+ final Object element = ((IStructuredSelection) selection).getFirstElement();
+ if (!(element instanceof TmfTraceFolder)) {
+ return null;
+ }
+ TmfTraceFolder parent = (TmfTraceFolder) element;
+
+ // Fire the New Folder dialog
+ Shell shell = window.getShell();
+ NewFolderDialog dialog = new NewFolderDialog(shell, parent);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OffsetTraceHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OffsetTraceHandler.java
new file mode 100644
index 0000000000..a87a2320fe
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OffsetTraceHandler.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.offset.OffsetDialog;
+import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.tracecompass.tmf.core.synchronization.ITmfTimestampTransform;
+import org.eclipse.tracecompass.tmf.core.synchronization.TimestampTransformFactory;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Offset Handler
+ *
+ * @author Matthew Khouzam
+ */
+public class OffsetTraceHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+
+ // Get the set of selected trace elements
+ final Set<TmfTraceElement> traceElements = new HashSet<>();
+ if (selection instanceof StructuredSelection) {
+ Iterator<Object> iterator = ((StructuredSelection) selection).iterator();
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (element instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) element;
+ traceElements.add(trace.getElementUnderTraceFolder());
+ } else if (element instanceof TmfExperimentElement) {
+ TmfExperimentElement exp = (TmfExperimentElement) element;
+ for (TmfTraceElement trace : exp.getTraces()) {
+ traceElements.add(trace.getElementUnderTraceFolder());
+ }
+ } else if (element instanceof TmfTraceFolder) {
+ TmfTraceFolder folder = (TmfTraceFolder) element;
+ traceElements.addAll(folder.getTraces());
+ }
+ }
+ }
+
+ if (traceElements.isEmpty()) {
+ return null;
+ }
+
+ final Map<TmfTraceElement, Long> offsets = new LinkedHashMap<>(traceElements.size());
+ for (TmfTraceElement trace : traceElements) {
+ offsets.put(trace, 0L);
+ }
+
+ Shell shell = HandlerUtil.getActiveShellChecked(event);
+ OffsetDialog dialog = new OffsetDialog(shell, offsets);
+ dialog.open();
+
+ if (dialog.getReturnCode() != Window.OK) {
+ return null;
+ }
+
+ TmfWorkspaceModifyOperation operation = new TmfWorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ for (final TmfTraceElement trace : offsets.keySet()) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ Long offset = offsets.get(trace);
+ if (offset != 0 && trace.getResource().exists()) {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ trace.closeEditors();
+ }
+ });
+ long previousOffset = TimestampTransformFactory.getTimestampTransform(trace.getResource()).transform(0);
+ ITmfTimestampTransform transform = TimestampTransformFactory.createWithOffset(previousOffset + offset);
+ trace.deleteSupplementaryResources();
+ // make sure the supplementary folder exists
+ trace.refreshSupplementaryFolder();
+ TimestampTransformFactory.setTimestampTransform(trace.getResource(), transform);
+ trace.refreshSupplementaryFolder();
+ }
+ }
+ }
+ };
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true, operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(shell, e.toString(), e.getTargetException().toString());
+ return null;
+ }
+
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAction.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAction.java
new file mode 100644
index 0000000000..f7bec56714
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAction.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+* Copyright (c) 2012, 2014 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.NotEnabledException;
+import org.eclipse.core.commands.NotHandledException;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfAnalysisOutputElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectModelElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.IHandlerService;
+
+/**
+ * <b><u>OpenAction</u></b>
+ */
+public class OpenAction extends Action {
+
+ private static final String OPEN_COMMAND_ID = "org.eclipse.ui.navigate.openResource"; //$NON-NLS-1$
+
+ private final IWorkbenchPage page;
+ private final ISelectionProvider selectionProvider;
+ private TmfProjectModelElement element;
+
+ /**
+ * Default constructor
+ * @param page the workbench page
+ * @param selectionProvider the selection provider
+ */
+ public OpenAction(IWorkbenchPage page, ISelectionProvider selectionProvider) {
+ this.page = page;
+ this.selectionProvider = selectionProvider;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ ISelection selection = selectionProvider.getSelection();
+ if (!selection.isEmpty()) {
+ IStructuredSelection sSelection = (IStructuredSelection) selection;
+ Object firstElement = sSelection.getFirstElement();
+ if ((sSelection.size() == 1) && (firstElement instanceof TmfTraceElement ||
+ firstElement instanceof TmfExperimentElement ||
+ firstElement instanceof TmfAnalysisOutputElement)) {
+ element = (TmfProjectModelElement) firstElement;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void run() {
+ try {
+ Object service = page.getActivePart().getSite().getService(IHandlerService.class);
+ IHandlerService handlerService = (IHandlerService) service;
+ boolean executeCommand = ((element instanceof TmfTraceElement) || (element instanceof TmfAnalysisOutputElement));
+
+ if (!executeCommand && element instanceof TmfExperimentElement) {
+ TmfExperimentElement experiment = (TmfExperimentElement) element;
+ executeCommand = (experiment.getTraces().size() > 0);
+ }
+
+ if (executeCommand) {
+ handlerService.executeCommand(OPEN_COMMAND_ID, null);
+ }
+ } catch (ExecutionException e) {
+ Activator.getDefault().logError("Error opening resource " + element.getName(), e); //$NON-NLS-1$
+ } catch (NotDefinedException e) {
+ Activator.getDefault().logError("Error opening resource " + element.getName(), e); //$NON-NLS-1$
+ } catch (NotEnabledException e) {
+ Activator.getDefault().logError("Error opening resource " + element.getName(), e); //$NON-NLS-1$
+ } catch (NotHandledException e) {
+ Activator.getDefault().logError("Error opening resource " + element.getName(), e); //$NON-NLS-1$
+ }
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java
new file mode 100644
index 0000000000..ae52eb4ba6
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 École Polytechnique de Montréal
+ *
+ * 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:
+ * Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfAnalysisElement;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Handler for when user wants to open the analysis help text
+ *
+ * @author Geneviève Bastien
+ */
+public class OpenAnalysisHelpHandler extends AbstractHandler {
+
+ private TmfAnalysisElement fAnalysis;
+
+ @Override
+ public boolean isEnabled() {
+ // Check if we are closing down
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ final IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ final ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ final ISelection selection = selectionProvider.getSelection();
+
+ // Make sure there is only one selection and that it is a trace
+ fAnalysis = null;
+ if (selection instanceof TreeSelection) {
+ final TreeSelection sel = (TreeSelection) selection;
+ // There should be only one item selected as per the plugin.xml
+ final Object element = sel.getFirstElement();
+ if (element instanceof TmfAnalysisElement) {
+ fAnalysis = (TmfAnalysisElement) element;
+ }
+ }
+
+ return (fAnalysis != null);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Check that the trace is valid
+ if (fAnalysis == null) {
+ return null;
+ }
+
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ displayHelpMsg(fAnalysis.getHelpMessage());
+ }
+ };
+
+ thread.start();
+
+ return null;
+ }
+
+ private static void displayHelpMsg(final String errorMsg) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ /*
+ * TODO: A message box is not the best place to show help.
+ * Something should be done with the Eclipse help
+ */
+ final MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText(Messages.AnalysisModule_Help);
+ mb.setMessage(errorMsg);
+ mb.open();
+ }
+ });
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java
new file mode 100644
index 0000000000..f4d88d2d93
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 École Polytechnique de Montréal
+ *
+ * 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:
+ * Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfAnalysisOutputElement;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Handler to programatically open a view
+ *
+ * @author Geneviève Bastien
+ */
+public class OpenAnalysisOutputHandler extends AbstractHandler {
+
+ private TmfAnalysisOutputElement fOutputElement;
+
+ @Override
+ public boolean isEnabled() {
+ /* Check if we are closing down */
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ /* Get the selection */
+ final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ final IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ final ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ final ISelection selection = selectionProvider.getSelection();
+
+ /* Make sure there is only one selection and that it is an analysis output */
+ fOutputElement = null;
+ if (selection instanceof TreeSelection) {
+ final TreeSelection sel = (TreeSelection) selection;
+ // There should be only one item selected as per the plugin.xml
+ final Object element = sel.getFirstElement();
+ if (element instanceof TmfAnalysisOutputElement) {
+ fOutputElement = (TmfAnalysisOutputElement) element;
+ }
+ }
+
+ return (fOutputElement != null);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ /* Check if we are closing down */
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ /* Check that the view is valid */
+ if (fOutputElement == null) {
+ return null;
+ }
+
+ fOutputElement.outputAnalysis();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenExperimentHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenExperimentHandler.java
new file mode 100644
index 0000000000..ba782e15a3
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenExperimentHandler.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson, École Polytechnique de Montréal
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Geneviève Bastien - Experiment instantiates with an experiment type
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>OpenExperimentHandler</u></b>
+ * <p>
+ */
+public class OpenExperimentHandler extends AbstractHandler {
+
+ private TmfExperimentElement fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ final IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ final ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ final ISelection selection = selectionProvider.getSelection();
+
+ // Make sure there is only one selection and that it is an experiment
+ fExperiment = null;
+ if (selection instanceof TreeSelection) {
+ final TreeSelection sel = (TreeSelection) selection;
+ // There should be only one item selected as per the plugin.xml
+ final Object element = sel.getFirstElement();
+ if (element instanceof TmfExperimentElement) {
+ fExperiment = (TmfExperimentElement) element;
+ }
+ }
+
+ // We only enable opening from the Traces folder for now
+ return ((fExperiment != null) && (fExperiment.getTraces().size() > 0));
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Check that the experiment is valid
+ if (fExperiment == null) {
+ return null;
+ }
+
+ TmfOpenTraceHelper.openTraceFromElement(fExperiment);
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenTraceHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenTraceHandler.java
new file mode 100644
index 0000000000..604aba59c2
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/OpenTraceHandler.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>OpenTraceHandler</u></b>
+ * <p>
+ * TODO: Add support for multiple trace selection
+ */
+public class OpenTraceHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ private TmfTraceElement fTrace = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ final IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ final ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ final ISelection selection = selectionProvider.getSelection();
+
+ // Make sure there is only one selection and that it is a trace
+ fTrace = null;
+ if (selection instanceof TreeSelection) {
+ final TreeSelection sel = (TreeSelection) selection;
+ // There should be only one item selected as per the plugin.xml
+ final Object element = sel.getFirstElement();
+ if (element instanceof TmfTraceElement) {
+ fTrace = (TmfTraceElement) element;
+ }
+ }
+
+ // We only enable opening from the Traces folder for now
+ return (fTrace != null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Check that the trace is valid
+ if (fTrace == null) {
+ return null;
+ }
+
+ // If trace is under an experiment, use the original trace from the traces folder
+ TmfOpenTraceHelper.openTraceFromElement(fTrace.getElementUnderTraceFolder());
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RefreshHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RefreshHandler.java
new file mode 100644
index 0000000000..14edcc13b7
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RefreshHandler.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>RefreshHandler</u></b>
+ * <p>
+ * TODO: Handle multiple selections
+ */
+public class RefreshHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ ISelection selection = part.getSite().getSelectionProvider().getSelection();
+ if (selection instanceof TreeSelection) {
+ TreeSelection treeSelection = (TreeSelection) selection;
+ Object element = treeSelection.getFirstElement();
+ IResource resource = null;
+ if (element instanceof TmfTraceFolder) {
+ TmfTraceFolder folder = (TmfTraceFolder) element;
+ resource = folder.getResource();
+ }
+ else if (element instanceof TmfExperimentFolder) {
+ TmfExperimentFolder folder = (TmfExperimentFolder) element;
+ resource = folder.getResource();
+ }
+ else if (element instanceof TmfExperimentElement) {
+ TmfExperimentElement folder = (TmfExperimentElement) element;
+ resource = folder.getResource();
+ }
+ try {
+ if (resource != null) {
+ resource.refreshLocal(IResource.DEPTH_INFINITE, null);
+ }
+ } catch (CoreException e) {
+ Activator.getDefault().logError("Error refreshing projects", e); //$NON-NLS-1$
+ }
+ }
+
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameExperimentHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameExperimentHandler.java
new file mode 100644
index 0000000000..b66bb31d68
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameExperimentHandler.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.RenameExperimentDialog;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>RenameExperimentHandler</u></b>
+ * <p>
+ */
+public class RenameExperimentHandler extends AbstractHandler {
+
+ private TmfExperimentElement fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // isEnabled
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ ISelection selection = selectionProvider.getSelection();
+
+ // Make sure there is only selection and that it is an experiment
+ fExperiment = null;
+ if (selection instanceof TreeSelection) {
+ TreeSelection sel = (TreeSelection) selection;
+ Object element = sel.getFirstElement();
+ if (element instanceof TmfExperimentElement) {
+ fExperiment = (TmfExperimentElement) element;
+ }
+ }
+
+ return (fExperiment != null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Fire the Rename Experiment dialog
+ Shell shell = window.getShell();
+ RenameExperimentDialog dialog = new RenameExperimentDialog(shell, fExperiment);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameFolderHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameFolderHandler.java
new file mode 100644
index 0000000000..cbbfb8546a
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameFolderHandler.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.RenameFolderDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for the Rename Folder command.
+ */
+public class RenameFolderHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ TmfTraceFolder selectedFolder = null;
+ if (selection instanceof IStructuredSelection) {
+ Object element = ((IStructuredSelection) selection).getFirstElement();
+ if (element instanceof TmfTraceFolder) {
+ selectedFolder = (TmfTraceFolder) element;
+ }
+ }
+ if (selectedFolder == null) {
+ return null;
+ }
+ final TmfTraceFolder oldFolder = selectedFolder;
+
+ // Fire the Rename Folder dialog
+ RenameFolderDialog dialog = new RenameFolderDialog(window.getShell(), oldFolder);
+ dialog.open();
+
+ if (dialog.getReturnCode() != Window.OK) {
+ return null;
+ }
+
+ final String newName = (String) dialog.getFirstResult();
+
+ IContainer parentFolder = oldFolder.getResource().getParent();
+ final TmfTraceFolder tracesFolder = oldFolder.getProject().getTracesFolder();
+ final IPath newFolderPath = parentFolder.getFullPath().append(newName);
+
+ WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ monitor.beginTask("", 1000); //$NON-NLS-1$
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+
+ for (final TmfTraceElement traceElement : oldFolder.getTraces()) {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ traceElement.closeEditors();
+ }
+ });
+
+ IPath relativePath = traceElement.getPath().makeRelativeTo(oldFolder.getPath());
+ String newElementPath = newFolderPath.makeRelativeTo(tracesFolder.getPath()).append(relativePath).toString();
+ traceElement.renameSupplementaryFolder(newElementPath);
+ }
+
+ oldFolder.getResource().move(newFolderPath, IResource.FORCE | IResource.SHALLOW, monitor);
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(window.getShell(), e.toString(), e.getTargetException().toString());
+ return null;
+ }
+
+ /* We need to split the WorkspaceModifyOperation so that the new model
+ * elements get created by the resource changed event */
+ operation = new WorkspaceModifyOperation() {
+ @Override
+ protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
+
+ IPath oldFolderElementPath = oldFolder.getPath().makeRelativeTo(tracesFolder.getPath());
+ IPath newFolderElementPath = oldFolderElementPath.removeLastSegments(1).append(newName);
+ for (TmfExperimentElement experiment : oldFolder.getProject().getExperimentsFolder().getExperiments()) {
+ for (TmfTraceElement oldTrace : experiment.getTraces()) {
+ if (oldTrace.getElementPath().startsWith(oldFolderElementPath.toString())) {
+ experiment.removeTrace(oldTrace);
+ String relativePath = oldTrace.getElementPath().substring(oldFolderElementPath.toString().length() + 1);
+ String newTraceElementPath = newFolderElementPath.append(relativePath).toString();
+ for (TmfTraceElement newTrace : tracesFolder.getTraces()) {
+ if (newTrace.getElementPath().equals(newTraceElementPath)) {
+ experiment.addTrace(newTrace);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(window.getShell(), e.toString(), e.getTargetException().toString());
+ return null;
+ }
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameTraceHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameTraceHandler.java
new file mode 100644
index 0000000000..a9066d3320
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/RenameTraceHandler.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Add support for folder elements
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.RenameTraceDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for the Rename Trace command.
+ */
+public class RenameTraceHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ TmfTraceElement selectedTrace = null;
+ if (selection instanceof IStructuredSelection) {
+ Object element = ((IStructuredSelection) selection).getFirstElement();
+ if (element instanceof TmfTraceElement) {
+ selectedTrace = (TmfTraceElement) element;
+ }
+ }
+ if (selectedTrace == null) {
+ return null;
+ }
+
+ // If trace is under an experiment, use the original trace from the traces folder
+ final TmfTraceElement oldTrace = selectedTrace.getElementUnderTraceFolder();
+
+ RenameTraceDialog dialog = new RenameTraceDialog(window.getShell(), oldTrace);
+ if (dialog.open() != Window.OK) {
+ return null;
+ }
+
+ final TmfTraceFolder traceFolder = (TmfTraceFolder) oldTrace.getParent();
+ final String newName = (String) dialog.getFirstResult();
+
+ IFolder parentFolder = (IFolder) oldTrace.getParent().getResource();
+ final TmfTraceFolder tracesFolder = oldTrace.getProject().getTracesFolder();
+ final IPath newPath = parentFolder.getFullPath().append(newName);
+
+ WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ monitor.beginTask("", 1000); //$NON-NLS-1$
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ // Close the trace if open
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ oldTrace.closeEditors();
+ }
+ });
+
+ if (oldTrace.getResource() instanceof IFolder) {
+ IFolder folder = (IFolder) oldTrace.getResource();
+ IFile bookmarksFile = oldTrace.getBookmarksFile();
+ if (bookmarksFile.exists()) {
+ IFile newBookmarksFile = folder.getFile(bookmarksFile.getName().replace(oldTrace.getName(), newName));
+ if (!newBookmarksFile.exists()) {
+ IPath newBookmarksPath = newBookmarksFile.getFullPath();
+ bookmarksFile.move(newBookmarksPath, IResource.FORCE | IResource.SHALLOW, monitor);
+ }
+ }
+ }
+
+ String newElementPath = newPath.makeRelativeTo(tracesFolder.getPath()).toString();
+ oldTrace.renameSupplementaryFolder(newElementPath);
+ oldTrace.getResource().move(newPath, IResource.FORCE | IResource.SHALLOW, monitor);
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
+ } catch (InterruptedException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(window.getShell(), e.toString(), e.getTargetException().toString());
+ return null;
+ }
+
+ /* We need to split the WorkspaceModifyOperation so that the new model
+ * elements get created by the resource changed event */
+ operation = new WorkspaceModifyOperation() {
+ @Override
+ protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
+
+ // Locate the new trace object
+ TmfTraceElement newTrace = null;
+ String newElementPath = oldTrace.getParent().getPath().append(newName).makeRelativeTo(tracesFolder.getPath()).toString();
+ for (TmfTraceElement element : traceFolder.getTraces()) {
+ if (element.getElementPath().equals(newElementPath)) {
+ newTrace = element;
+ break;
+ }
+ }
+ if (newTrace == null) {
+ return;
+ }
+
+ TmfExperimentFolder experimentFolder = newTrace.getProject().getExperimentsFolder();
+ for (final TmfExperimentElement experiment : experimentFolder.getExperiments()) {
+ for (final TmfTraceElement expTrace : experiment.getTraces()) {
+ if (expTrace.getElementPath().equals(oldTrace.getElementPath())) {
+ experiment.removeTrace(expTrace);
+ experiment.addTrace(newTrace);
+ }
+ }
+ }
+ }
+ };
+
+ try {
+ PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
+ } catch (InterruptedException e) {
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(window.getShell(), e.toString(), e.getTargetException().toString());
+ }
+
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectElementTypeContributionItem.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectElementTypeContributionItem.java
new file mode 100644
index 0000000000..2c09e8d3d5
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectElementTypeContributionItem.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson, École Polytechnique de Montréal
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ * Geneviève Bastien - Moved SelectTraceTypeContributionItem to this class
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTrace;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType.TraceElementType;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.CompoundContributionItem;
+import org.eclipse.ui.menus.CommandContributionItem;
+import org.eclipse.ui.menus.CommandContributionItemParameter;
+
+/**
+ * ContributionItem for the element type selection.
+ *
+ * @author Patrick Tassé
+ */
+public class SelectElementTypeContributionItem extends CompoundContributionItem {
+
+ private static final ImageDescriptor SELECTED_ICON = Activator.getDefault().getImageDescripterFromPath("icons/elcl16/bullet.gif"); //$NON-NLS-1$
+ private static final String BUNDLE_PARAMETER = "org.eclipse.linuxtools.tmf.ui.commandparameter.select_trace_type.bundle"; //$NON-NLS-1$
+ private static final String TYPE_PARAMETER = "org.eclipse.linuxtools.tmf.ui.commandparameter.select_trace_type.type"; //$NON-NLS-1$
+ private static final String ICON_PARAMETER = "org.eclipse.linuxtools.tmf.ui.commandparameter.select_trace_type.icon"; //$NON-NLS-1$
+ private static final String SELECT_TRACE_TYPE_COMMAND_ID = "org.eclipse.linuxtools.tmf.ui.command.select_trace_type"; //$NON-NLS-1$
+ private static final String DEFAULT_TRACE_ICON_PATH = "icons/elcl16/trace.gif"; //$NON-NLS-1$
+
+ @Override
+ protected IContributionItem[] getContributionItems() {
+
+ /*
+ * Fill the selected trace types and verify if selection applies only to
+ * either traces or experiments
+ */
+ Set<String> selectedTraceTypes = new HashSet<>();
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ ISelection selection = page.getSelection();
+ boolean forTraces = false, forExperiments = false;
+ if (selection instanceof StructuredSelection) {
+ for (Object element : ((StructuredSelection) selection).toList()) {
+ if (element instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) element;
+ selectedTraceTypes.add(trace.getTraceType());
+ forTraces = true;
+ } else if (element instanceof TmfExperimentElement) {
+ TmfExperimentElement exp = (TmfExperimentElement) element;
+ selectedTraceTypes.add(exp.getTraceType());
+ forExperiments = true;
+ }
+ }
+ }
+
+ if (forTraces && forExperiments) {
+ /* This should never happen anyways */
+ throw new RuntimeException("You must select only experiments or only traces to set the element type"); //$NON-NLS-1$
+ }
+
+ return getContributionItems(selectedTraceTypes, forExperiments);
+ }
+
+ /**
+ * Get the contribution items for traces
+ *
+ * @param selectedTraceTypes
+ * The set of selected trace types
+ * @param forExperiments
+ * <code>true</code> if the contribution items are requested for
+ * experiments, <code>false</code> for traces
+ *
+ * @return The list of contribution items
+ */
+ protected IContributionItem[] getContributionItems(Set<String> selectedTraceTypes, boolean forExperiments) {
+
+ String ceType = forExperiments ? TmfTraceType.EXPERIMENT_ELEM : TmfTraceType.TYPE_ELEM;
+ TraceElementType elementType = forExperiments ? TraceElementType.EXPERIMENT : TraceElementType.TRACE;
+
+ List<IContributionItem> list = new LinkedList<>();
+
+ Map<String, MenuManager> categoriesMap = new HashMap<>();
+ IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(
+ TmfTraceType.TMF_TRACE_TYPE_ID);
+ for (IConfigurationElement ce : config) {
+ if (ce.getName().equals(TmfTraceType.CATEGORY_ELEM)) {
+ String categoryId = ce.getAttribute(TmfTraceType.ID_ATTR);
+ ImageDescriptor icon = isSelectedCategory(categoryId, config, selectedTraceTypes) ? SELECTED_ICON : null;
+ MenuManager subMenu = new MenuManager(ce.getAttribute(TmfTraceType.NAME_ATTR), icon, null);
+ categoriesMap.put(categoryId, subMenu);
+ list.add(subMenu);
+ }
+ }
+
+ for (IConfigurationElement ce : config) {
+ if (ce.getName().equals(ceType)) {
+ String traceBundle = ce.getContributor().getName();
+ String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
+ String label = ce.getAttribute(TmfTraceType.NAME_ATTR).replaceAll("&", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
+ boolean selected = selectedTraceTypes.contains(traceTypeId);
+ MenuManager subMenu = categoriesMap.get(ce.getAttribute(TmfTraceType.CATEGORY_ATTR));
+
+ /* Get the icon from the tmftracetypeui extension, if it exists */
+ String traceIcon = null;
+ IConfigurationElement uiCE = TmfTraceTypeUIUtils.getTraceUIAttributes(traceTypeId, elementType);
+ if (uiCE != null) {
+ traceIcon = uiCE.getAttribute(TmfTraceTypeUIUtils.ICON_ATTR);
+ }
+
+ addContributionItem(list, traceBundle, traceTypeId, traceIcon, label, selected, subMenu);
+ }
+ }
+
+ Comparator<IContributionItem> comparator = new Comparator<IContributionItem>() {
+ @Override
+ public int compare(IContributionItem o1, IContributionItem o2) {
+ if (o1 instanceof MenuManager) {
+ if (o2 instanceof MenuManager) {
+ MenuManager m1 = (MenuManager) o1;
+ MenuManager m2 = (MenuManager) o2;
+ return m1.getMenuText().compareTo(m2.getMenuText());
+ }
+ return -1;
+ }
+ if (o2 instanceof MenuManager) {
+ return 1;
+ }
+ CommandContributionItem c1 = (CommandContributionItem) o1;
+ CommandContributionItem c2 = (CommandContributionItem) o2;
+ return c1.getData().label.compareTo(c2.getData().label);
+ }
+ };
+
+ if (forExperiments) {
+ Collections.sort(list, comparator);
+ return list.toArray(new IContributionItem[list.size()]);
+ }
+
+ /*
+ * Add the custom txt and xml trace type to the contribution items for
+ * traces
+ */
+ for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
+ String traceBundle = Activator.getDefault().getBundle().getSymbolicName();
+ String traceTypeId = CustomTxtTrace.buildTraceTypeId(def.categoryName, def.definitionName);
+ String traceIcon = DEFAULT_TRACE_ICON_PATH;
+ String label = def.definitionName;
+ boolean selected = selectedTraceTypes.contains(traceTypeId);
+ MenuManager subMenu = getCategorySubMenu(list, categoriesMap, def.categoryName, selected);
+
+ addContributionItem(list, traceBundle, traceTypeId, traceIcon, label, selected, subMenu);
+ }
+ for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
+ String traceBundle = Activator.getDefault().getBundle().getSymbolicName();
+ String traceTypeId = CustomXmlTrace.buildTraceTypeId(def.categoryName, def.definitionName);
+ String traceIcon = DEFAULT_TRACE_ICON_PATH;
+ String label = def.definitionName;
+ boolean selected = selectedTraceTypes.contains(traceTypeId);
+ MenuManager subMenu = getCategorySubMenu(list, categoriesMap, def.categoryName, selected);
+
+ addContributionItem(list, traceBundle, traceTypeId, traceIcon, label, selected, subMenu);
+ }
+
+ Collections.sort(list, comparator);
+ return list.toArray(new IContributionItem[list.size()]);
+ }
+
+ private static MenuManager getCategorySubMenu(List<IContributionItem> list,
+ Map<String, MenuManager> categoriesMap, String categoryName, boolean selected) {
+ for (Entry<String, MenuManager> entry : categoriesMap.entrySet()) {
+ MenuManager subMenu = entry.getValue();
+ if (subMenu.getMenuText().equals(categoryName)) {
+ if (selected) {
+ subMenu.setImageDescriptor(SELECTED_ICON);
+ }
+ return subMenu;
+ }
+ }
+ ImageDescriptor icon = selected ? SELECTED_ICON : null;
+ MenuManager subMenu = new MenuManager(categoryName, icon, null);
+ categoriesMap.put(categoryName, subMenu);
+ list.add(subMenu);
+ return subMenu;
+ }
+
+ private static void addContributionItem(List<IContributionItem> list,
+ String traceBundle, String traceTypeId, String traceIcon,
+ String label, boolean selected,
+ MenuManager subMenu) {
+ Map<String, String> params;
+
+ params = new HashMap<>();
+ params.put(BUNDLE_PARAMETER, traceBundle);
+ params.put(TYPE_PARAMETER, traceTypeId);
+ params.put(ICON_PARAMETER, traceIcon);
+
+ ImageDescriptor icon = null;
+ if (selected) {
+ icon = SELECTED_ICON;
+ }
+
+ CommandContributionItemParameter param = new CommandContributionItemParameter(
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow(), // serviceLocator
+ "my.parameterid", // id //$NON-NLS-1$
+ SELECT_TRACE_TYPE_COMMAND_ID, // commandId
+ CommandContributionItem.STYLE_PUSH // style
+ );
+ param.parameters = params;
+ param.icon = icon;
+ param.disabledIcon = icon;
+ param.hoverIcon = icon;
+ param.label = label;
+ param.visibleEnabled = true;
+
+ if (subMenu != null) {
+ subMenu.add(new CommandContributionItem(param));
+ } else {
+ list.add(new CommandContributionItem(param));
+ }
+ }
+
+ private static boolean isSelectedCategory(String categoryId, IConfigurationElement[] config, Set<String> selectedTraceTypes) {
+ for (IConfigurationElement ce : config) {
+ if (ce.getName().equals(TmfTraceType.TYPE_ELEM)) {
+ String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
+ if (selectedTraceTypes.contains(traceTypeId)) {
+ if (categoryId.equals(ce.getAttribute(TmfTraceType.CATEGORY_ATTR))) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTraceTypeHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTraceTypeHandler.java
new file mode 100644
index 0000000000..ad5b264199
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTraceTypeHandler.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson, École Polytechnique de Montréal
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Patrick Tasse - Fix propagation to experiment traces
+ * Geneviève Bastien - Add support of experiment types
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>SetTraceTypeHandler</u></b>
+ * <p>
+ */
+public class SelectTraceTypeHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final String TYPE_PARAMETER = "org.eclipse.linuxtools.tmf.ui.commandparameter.select_trace_type.type"; //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ private TreeSelection fSelection = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ ISelection selection = selectionProvider.getSelection();
+
+ // Make sure selection contains only traces
+ fSelection = null;
+ if (selection instanceof TreeSelection) {
+ fSelection = (TreeSelection) selection;
+ Iterator<Object> iterator = fSelection.iterator();
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (!(element instanceof TmfCommonProjectElement)) {
+ return false;
+ }
+ }
+ }
+
+ // If we get here, either nothing is selected or everything is a trace
+ return !selection.isEmpty();
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+ List<IStatus> statuses = new ArrayList<>();
+ Set<TmfProjectElement> projects = new HashSet<>();
+ boolean ok = true;
+ for (Object element : fSelection.toList()) {
+ TmfCommonProjectElement trace = (TmfCommonProjectElement) element;
+ if (trace instanceof TmfTraceElement) {
+ trace = ((TmfTraceElement) trace).getElementUnderTraceFolder();
+ }
+ IResource resource = trace.getResource();
+ if (resource != null) {
+ try {
+ // Set the trace type for this resource
+ String traceType = event.getParameter(TYPE_PARAMETER);
+ String previousTraceType = trace.getTraceType();
+ IStatus status = propagateProperties(trace, traceType);
+ ok &= status.isOK();
+
+ if (status.isOK()) {
+ if ((previousTraceType != null) && (!traceType.equals(previousTraceType))) {
+ // Close the trace if open
+ trace.closeEditors();
+ // Delete all supplementary resources
+ trace.deleteSupplementaryResources();
+ }
+ } else {
+ statuses.add(status);
+ }
+ projects.add(trace.getProject());
+ } catch (CoreException e) {
+ Activator.getDefault().logError(Messages.SelectTraceTypeHandler_ErrorSelectingTrace + trace.getName(), e);
+ }
+ }
+ trace.getProject();
+ }
+ for (TmfProjectElement project : projects) {
+ project.refresh();
+ }
+
+ if (!ok) {
+ final Shell shell = window.getShell();
+ MultiStatus info = new MultiStatus(Activator.PLUGIN_ID, 1, Messages.SelectTraceTypeHandler_TraceFailedValidation, null);
+ if (statuses.size() > 1)
+ {
+ info = new MultiStatus(Activator.PLUGIN_ID, 1, Messages.SelectTraceTypeHandler_TracesFailedValidation, null);
+ }
+ for (IStatus status : statuses) {
+ info.add(status);
+ }
+ ErrorDialog.openError(shell, Messages.SelectTraceTypeHandler_Title, Messages.SelectTraceTypeHandler_InvalidTraceType, info);
+ }
+ return null;
+ }
+
+ private static IStatus propagateProperties(TmfCommonProjectElement element, String traceType)
+ throws CoreException {
+
+ TraceTypeHelper traceTypeHelper = TmfTraceType.getTraceType(traceType);
+ if (traceTypeHelper == null) {
+ return Status.CANCEL_STATUS;
+ }
+ final IStatus validateTraceType = traceTypeHelper.validate(element.getResource().getLocation().toOSString());
+ if (!validateTraceType.isOK()) {
+ return validateTraceType;
+ }
+
+ IResource resource = element.getResource();
+ TmfTraceTypeUIUtils.setTraceType(resource, traceTypeHelper);
+
+ TmfExperimentFolder experimentFolder = element.getProject().getExperimentsFolder();
+ for (final TmfExperimentElement experiment : experimentFolder.getExperiments()) {
+ for (final TmfTraceElement child : experiment.getTraces()) {
+ if (child.getName().equals(element.getName())) {
+ TmfTraceTypeUIUtils.setTraceType(child.getResource(), traceTypeHelper);
+ break;
+ }
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTracesHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTracesHandler.java
new file mode 100644
index 0000000000..1865df3bf0
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SelectTracesHandler.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.wizards.SelectTracesWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>SelectTracesHandler</u></b>
+ * <p>
+ */
+public class SelectTracesHandler extends AbstractHandler {
+
+ private TmfExperimentElement fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return false;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return false;
+ }
+ ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return false;
+ }
+ ISelection selection = selectionProvider.getSelection();
+
+ // Make sure there is only one selection and that it is an experiment
+ fExperiment = null;
+ if (selection instanceof TreeSelection) {
+ TreeSelection sel = (TreeSelection) selection;
+ // There should be only one item selected as per the plugin.xml
+ Object element = sel.getFirstElement();
+ if (element instanceof TmfExperimentElement) {
+ fExperiment = (TmfExperimentElement) element;
+ }
+ }
+
+ return (fExperiment != null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Fire the Select Traces Wizard
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ Shell shell = workbench.getActiveWorkbenchWindow().getShell();
+
+ TmfExperimentFolder experiments = (TmfExperimentFolder) fExperiment.getParent();
+ TmfProjectElement project = (TmfProjectElement) experiments.getParent();
+ SelectTracesWizard wizard = new SelectTracesWizard(project, fExperiment);
+ wizard.init(PlatformUI.getWorkbench(), null);
+ WizardDialog dialog = new WizardDialog(shell, wizard);
+ dialog.open();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SynchronizeTracesHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SynchronizeTracesHandler.java
new file mode 100644
index 0000000000..13706e7243
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/SynchronizeTracesHandler.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 École Polytechnique de Montréal
+ *
+ * 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:
+ * Geneviève Bastien - Initial implementation and API
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.tracecompass.tmf.core.synchronization.SynchronizationAlgorithm;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Handles the synchronization of an experiment, when the user selects this
+ * option in the menu
+ */
+public class SynchronizeTracesHandler extends AbstractHandler {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ private TreeSelection fSelection = null;
+ private static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return null;
+ }
+
+ // Get the selection
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart part = page.getActivePart();
+ if (part == null) {
+ return Boolean.FALSE;
+ }
+ ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
+ if (selectionProvider == null) {
+ return Boolean.FALSE;
+ }
+ ISelection selection = selectionProvider.getSelection();
+
+ // Make sure selection contains only traces
+ fSelection = null;
+ final ArrayList<TmfTraceElement> tl = new ArrayList<>();
+ final ArrayList<TmfExperimentElement> uiexperiment = new ArrayList<>();
+ if (selection instanceof TreeSelection) {
+ fSelection = (TreeSelection) selection;
+ Iterator<Object> iterator = fSelection.iterator();
+ while (iterator.hasNext()) {
+ Object element = iterator.next();
+ if (element instanceof TmfTraceElement) {
+ tl.add((TmfTraceElement) element);
+ } else if (element instanceof TmfExperimentElement) {
+ TmfExperimentElement exp = (TmfExperimentElement) element;
+ uiexperiment.add(exp);
+ for (TmfTraceElement trace : exp.getTraces()) {
+ tl.add(trace);
+ }
+ }
+ }
+ }
+
+ if ((uiexperiment.size() != 1) || (tl.size() < 2)) {
+ TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_WrongTraceNumber);
+ return null;
+ }
+
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+
+ final ITmfTrace[] traces = new ITmfTrace[tl.size()];
+ final TmfExperimentElement exp = uiexperiment.get(0);
+
+ for (int i = 0; i < tl.size(); i++) {
+ ITmfTrace trace = tl.get(i).instantiateTrace();
+ ITmfEvent traceEvent = tl.get(i).instantiateEvent();
+ if (trace == null) {
+ TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_WrongType + tl.get(i).getName());
+ for (int j = 0; j < i; j++) {
+ traces[j].dispose();
+ }
+ return;
+ }
+ try {
+ trace.initTrace(tl.get(i).getResource(), tl.get(i).getResource().getLocation().toOSString(), traceEvent.getClass());
+ TmfTraceManager.refreshSupplementaryFiles(trace);
+ } catch (TmfTraceException e) {
+ TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_InitError + CR + CR + e);
+ trace.dispose();
+ for (int j = 0; j < i; j++) {
+ traces[j].dispose();
+ }
+ return;
+ }
+ traces[i] = trace;
+ }
+
+ /*
+ * FIXME Unlike traces, there is no instanceExperiment, so
+ * we call this function here alone. Maybe it would be
+ * better to do this on experiment's element constructor?
+ */
+ exp.refreshSupplementaryFolder();
+ final TmfExperiment experiment = new TmfExperiment(ITmfEvent.class,
+ exp.getName(), traces, TmfExperiment.DEFAULT_INDEX_PAGE_SIZE, exp.getResource());
+
+ final SynchronizationAlgorithm syncAlgo = experiment.synchronizeTraces(true);
+ TmfTraceManager.refreshSupplementaryFiles(experiment);
+
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ List<TmfTraceElement> tracesToAdd = new ArrayList<>();
+ List<TmfTraceElement> tracesToRemove = new ArrayList<>();
+ /*
+ * For each trace in the experiment, if there is
+ * a transform equation, copy the original
+ * trace, so that a new state system will be
+ * generated with sync time.
+ */
+ for (TmfTraceElement traceel : tl) {
+ /*
+ * Find the trace corresponding to this
+ * element in the experiment
+ */
+ ITmfTrace expTrace = null;
+ for (ITmfTrace t : experiment.getTraces()) {
+ if (t.getResource().equals(traceel.getResource())) {
+ expTrace = t;
+ break;
+ }
+ }
+ if ((expTrace != null) && syncAlgo.isTraceSynced(expTrace.getHostId())) {
+
+ /* Find the original trace */
+ TmfTraceElement origtrace = traceel.getElementUnderTraceFolder();
+
+ /*
+ * Make sure a trace with the
+ * new name does not exist
+ */
+ String newname = traceel.getName();
+ IContainer parentFolder = origtrace.getResource().getParent();
+ boolean traceexists;
+ do {
+ traceexists = false;
+ newname += "_"; //$NON-NLS-1$
+ if (parentFolder.findMember(newname) != null) {
+ traceexists = true;
+ }
+ } while (traceexists);
+
+ /* Copy the original trace */
+ TmfTraceElement newtrace = origtrace.copy(newname);
+ if (newtrace == null) {
+ TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title,
+ Messages.SynchronizeTracesHandler_Error + CR + CR + String.format(Messages.SynchronizeTracesHandler_CopyProblem, origtrace.getName()));
+ continue;
+ }
+
+ /*
+ * Instantiate the new trace
+ * and set its sync formula
+ */
+ ITmfTrace trace = newtrace.instantiateTrace();
+ ITmfEvent traceEvent = newtrace.instantiateEvent();
+
+ try {
+ trace.initTrace(newtrace.getResource(), newtrace.getResource().getLocation().toOSString(), traceEvent.getClass());
+ } catch (TmfTraceException e) {
+ Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingForTrace, exp.getName(), traceel.getName()), e);
+ TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_Error + CR + CR + e.getMessage());
+ }
+ trace.setTimestampTransform(syncAlgo.getTimestampTransform(trace));
+ TmfTraceManager.refreshSupplementaryFiles(trace);
+ trace.dispose();
+
+ tracesToAdd.add(newtrace);
+ tracesToRemove.add(traceel);
+ }
+ }
+ experiment.dispose();
+
+ // Move synchronization file temporarily so that
+ // it doesn't get deleted by the experiment change
+ IFolder tmpFolder = exp.getTraceSupplementaryFolder(exp.getName() + '.' + experiment.getSynchronizationFolder(false));
+ IResource syncFile = null;
+ for (IResource resource : exp.getSupplementaryResources()) {
+ if (resource.getName().equals(experiment.getSynchronizationFolder(false))) {
+ try {
+ resource.move(tmpFolder.getFullPath(), false, null);
+ syncFile = resource;
+ break;
+ } catch (CoreException e) {
+ Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingExperiment, exp.getName()), e);
+ }
+ }
+ }
+
+ for (TmfTraceElement trace : tracesToRemove) {
+ try {
+ exp.removeTrace(trace);
+ } catch (CoreException e) {
+ Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingForTrace, exp.getName(), trace.getName()), e);
+ TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_Error + CR + CR + e.getMessage());
+ }
+ }
+ for (TmfTraceElement trace : tracesToAdd) {
+ exp.addTrace(trace);
+ }
+
+ // Move synchronization file back
+ if (tmpFolder.exists() && syncFile != null) {
+ try {
+ tmpFolder.move(syncFile.getFullPath(), false, null);
+ } catch (CoreException e) {
+ Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingExperiment, exp.getName()), e);
+ }
+ }
+ }
+ });
+ }
+ };
+ thread.start();
+
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TmfActionProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TmfActionProvider.java
new file mode 100644
index 0000000000..0ddd7eb8ae
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TmfActionProvider.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+* Copyright (c) 2012, 2014 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.actions.OpenWithMenu;
+import org.eclipse.ui.navigator.CommonActionProvider;
+import org.eclipse.ui.navigator.ICommonActionConstants;
+import org.eclipse.ui.navigator.ICommonActionExtensionSite;
+import org.eclipse.ui.navigator.ICommonMenuConstants;
+import org.eclipse.ui.navigator.ICommonViewerSite;
+import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;
+
+/**
+ * Base action provider.
+ *
+ * @author Patrick Tassé
+ */
+public class TmfActionProvider extends CommonActionProvider {
+
+ private OpenAction openAction;
+
+ private IWorkbenchPage page;
+
+ /**
+ * Default constructor
+ */
+ public TmfActionProvider() {
+ }
+
+ @Override
+ public void init(ICommonActionExtensionSite aSite) {
+ ICommonViewerSite viewSite = aSite.getViewSite();
+ if (viewSite instanceof ICommonViewerWorkbenchSite) {
+ ICommonViewerWorkbenchSite workbenchSite = (ICommonViewerWorkbenchSite) viewSite;
+ page = workbenchSite.getPage();
+ openAction = new OpenAction(page, workbenchSite.getSelectionProvider());
+ }
+ }
+
+ @Override
+ public void fillContextMenu(IMenuManager menu) {
+ ISelection selection = getContext().getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ if (structuredSelection.size() == 1 && structuredSelection.getFirstElement() instanceof TmfTraceElement) {
+ TmfTraceElement traceElement = (TmfTraceElement) structuredSelection.getFirstElement();
+ if (traceElement.getResource() instanceof IFile) {
+ MenuManager openWithMenu = new MenuManager(Messages.TmfActionProvider_OpenWith);
+ openWithMenu.add(new OpenWithMenu(page, traceElement.getResource()));
+ menu.insertAfter(ICommonMenuConstants.GROUP_OPEN_WITH, openWithMenu);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void fillActionBars(IActionBars actionBars) {
+ if (openAction.isEnabled()) {
+ actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN, openAction);
+ }
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TracePropertyTester.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TracePropertyTester.java
new file mode 100644
index 0000000000..4da0af5cd1
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/TracePropertyTester.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
+
+import java.util.Iterator;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+
+/**
+ * <b><u>TracePropertyTester</u></b>
+ * <p>
+ */
+public class TracePropertyTester extends PropertyTester {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final String IS_IN_TRACE_FOLDER = "isInTraceFolder"; //$NON-NLS-1$
+ private static final String IS_EXPERIMENT_TRACE = "isExperimentTrace"; //$NON-NLS-1$
+ private static final String HAS_SUPPLEMENTARY_FILES = "hasSupplementaryFiles"; //$NON-NLS-1$
+ private static final String TRACE_TYPE = "traceType"; //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Default constructor
+ */
+ public TracePropertyTester() {
+ }
+
+ // ------------------------------------------------------------------------
+ // IPropertyTester
+ // ------------------------------------------------------------------------
+
+ @Override
+ public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+
+ // Check if the selected elements are in the trace folder
+ if (IS_IN_TRACE_FOLDER.equals(property)) {
+ if (receiver instanceof IStructuredSelection) {
+ Iterator<?> iter = ((IStructuredSelection) receiver).iterator();
+ while (iter.hasNext()) {
+ Object item = iter.next();
+ if (item instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) item;
+ if (!(trace.getParent() instanceof TmfTraceFolder)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ // Check if the parent of a trace element is an experiment
+ if (IS_EXPERIMENT_TRACE.equals(property)) {
+ if (receiver instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) receiver;
+ return trace.getParent() instanceof TmfExperimentElement;
+ }
+ return false;
+ }
+
+ // Check if traces has supplementary files
+ if (HAS_SUPPLEMENTARY_FILES.equals(property)) {
+ if (receiver instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) receiver;
+ return trace.hasSupplementaryResources();
+ } else if (receiver instanceof TmfExperimentElement) {
+ TmfExperimentElement trace = (TmfExperimentElement) receiver;
+ boolean hasHistory = false;
+ for (TmfTraceElement aTrace : trace.getTraces()) {
+ hasHistory |= aTrace.hasSupplementaryResources();
+ }
+ hasHistory |= trace.hasSupplementaryResources();
+ return hasHistory;
+ }
+ return false;
+ }
+
+ // Check if the trace element is of a specific trace type
+ if (TRACE_TYPE.equals(property)) {
+ if (receiver instanceof TmfTraceElement) {
+ TmfTraceElement trace = (TmfTraceElement) receiver;
+ if (expectedValue instanceof String && expectedValue.equals(trace.getTraceType())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/messages.properties
new file mode 100644
index 0000000000..95ab3da1f3
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/handlers/messages.properties
@@ -0,0 +1,70 @@
+###############################################################################
+# Copyright (c) 2013, 2014 Ericsson
+#
+# 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:
+# Ericsson - Initial API and implementation
+###############################################################################
+
+# Delete message
+DeleteDialog_Title = Confirm Delete
+DeleteTraceHandler_Message = Are you sure you want to delete the selected trace(s)?
+DeleteTraceHandler_Error = Error deleting trace
+DeleteTraceHandler_TaskName = Deleting trace
+RemoveDialog_Title = Confirm Remove
+RemoveTraceFromExperimentHandler_Message = Are you sure you want to remove the selected trace(s)?
+RemoveTraceFromExperimentHandler_TaskName = Removing trace
+RemoveTraceFromExperimentHandler_Error = Error removing trace
+DeleteExperimentHandler_Message = Are you sure you want to delete this experiment?
+DeleteExperimentHandler_Error = Error deleting experiment
+DeleteFolderHandler_Message = Are you sure you want to delete the selected folder(s)?
+DeleteFolderHandler_Error = Error deleting folder
+DeleteFolderHandler_TaskName = Deleting folder
+DeleteTraceHandlerGeneric_Message = Are you sure you want to delete the selected elements?
+DeleteTraceHandlerGeneric_Error= Error deleting elements
+
+# Clear message
+ClearDialog_Title = Confirm Clear
+DeleteFolderHandlerClear_TaskName = Clearing folder
+DeleteFolderHandlerClear_Message = Are you sure you want to clear the selected folder(s)?
+DeleteFolderHandlerClear_Error = Error clearing folder
+
+# Set Trace Type
+SelectTraceTypeHandler_ErrorSelectingTrace=Error selecting trace type for trace
+SelectTraceTypeHandler_Title = Validation Error
+SelectTraceTypeHandler_TraceFailedValidation=A trace has failed validation
+SelectTraceTypeHandler_TracesFailedValidation=Several trace files failed validation
+SelectTraceTypeHandler_InvalidTraceType = Type could not be set for one or more traces
+
+# Drag and drop
+DropAdapterAssistant_RenameTraceTitle=Confirm rename trace
+DropAdapterAssistant_RenameTraceMessage=An element with the name ''{0}'' already exists in the target folder.\nRename the dropped trace?
+
+# Trace synchronization
+SynchronizeTracesHandler_InitError=Error initializing trace
+SynchronizeTracesHandler_CopyProblem=Couldn't copy the original trace %s
+SynchronizeTracesHandler_WrongTraceNumber=Experiment must have more than one trace
+SynchronizeTracesHandler_Title=Synchronize traces
+SynchronizeTracesHandler_WrongType=Trace is not a kernel trace:\n
+SynchronizeTracesHandler_Error=Error synchronizing experiment
+
+SynchronizeTracesHandler_ErrorSynchingExperiment=Error synchronizing experiment %s
+SynchronizeTracesHandler_ErrorSynchingForTrace=Error synchronizing experiment %s for trace %s
+
+ClearTraceOffsetHandler_Title=Clear time offset
+ClearTraceOffsetHandler_ConfirmMessage=Are you sure you want to clear the time offset for the selected trace(s)?
+
+# Delete Supplementary Files messages
+DeleteSupplementaryFiles_DeletionTask=Deleting supplementary files for {0}
+DeleteSupplementaryFiles_ProjectRefreshTask=Refreshing project {0}
+
+
+# Analysis modules
+AnalysisModule_Help=Help
+
+# TMF Action Provider
+TmfActionProvider_OpenWith=Open With
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfEditorLinkHelper.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfEditorLinkHelper.java
new file mode 100644
index 0000000000..d9af95a61b
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfEditorLinkHelper.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2015 Ericsson
+ *
+ * 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:
+ * Bernd Hufmann - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.tmf.ui.project.model;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.tracecompass.internal.tmf.ui.editors.ITmfEventsEditorConstants;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.ide.ResourceUtil;
+import org.eclipse.ui.navigator.ILinkHelper;
+import org.eclipse.ui.part.FileEditorInput;
+
+/**
+ * Implementation of ILinkHelper interface for linking with editor extension for traces and
+ * experiments.
+ *
+ * @author Bernd Hufmann
+ */
+public class TmfEditorLinkHelper implements ILinkHelper {
+
+ @Override
+ public IStructuredSelection findSelection(IEditorInput anInput) {
+ IFile file = ResourceUtil.getFile(anInput);
+ if (file != null) {
+
+ try {
+ // Get the trace type ID
+ String traceTypeId = file.getPersistentProperty(TmfCommonConstants.TRACETYPE);
+ if (traceTypeId == null) {
+ return StructuredSelection.EMPTY;
+ }
+
+ final TmfProjectElement project = TmfProjectRegistry.getProject(file.getProject(), true);
+
+ // Check for experiments, traces which are folders or traces which are files
+ if (ITmfEventsEditorConstants.EXPERIMENT_INPUT_TYPE_CONSTANTS.contains(traceTypeId)) {
+ // Case 1: Experiment
+ for (final TmfExperimentElement experimentElement : project.getExperimentsFolder().getExperiments()) {
+ if (experimentElement.getResource().equals(file.getParent())) {
+ return new StructuredSelection(experimentElement);
+ }
+ }
+ } else if (ITmfEventsEditorConstants.TRACE_INPUT_TYPE_CONSTANTS.contains(traceTypeId)) {
+ // Case 2: Trace that is a folder
+ for (final TmfTraceElement traceElement : project.getTracesFolder().getTraces()) {
+ if (traceElement.getResource().equals(file.getParent())) {
+ return new StructuredSelection(traceElement);
+ }
+ }
+ } else {
+ // Case 3: Trace that is a file
+ for (final TmfTraceElement traceElement : project.getTracesFolder().getTraces()) {
+ if (traceElement.getResource().equals(file)) {
+ return new StructuredSelection(traceElement);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ return StructuredSelection.EMPTY;
+ }
+ }
+ return StructuredSelection.EMPTY;
+ }
+
+ @Override
+ public void activateEditor(IWorkbenchPage aPage, IStructuredSelection aSelection) {
+ if (aSelection == null || aSelection.isEmpty()) {
+ return;
+ }
+
+ IFile file = null;
+
+ if ((aSelection.getFirstElement() instanceof TmfTraceElement)) {
+ TmfTraceElement traceElement = ((TmfTraceElement)aSelection.getFirstElement());
+
+ // If trace is under an experiment, use the original trace from the traces folder
+ traceElement = traceElement.getElementUnderTraceFolder();
+ file = traceElement.getBookmarksFile();
+ } else if ((aSelection.getFirstElement() instanceof TmfExperimentElement)) {
+ TmfExperimentElement experimentElement = (TmfExperimentElement) aSelection.getFirstElement();
+ file = experimentElement.getBookmarksFile();
+ }
+
+ if (file != null) {
+ IEditorInput tmpInput = new FileEditorInput(file);
+ IEditorPart localEditor = aPage.findEditor(tmpInput);
+ if (localEditor != null) {
+ // Editor found.
+ aPage.bringToTop(localEditor);
+ } else {
+ // Search in references for corresponding editor
+ IEditorReference[] refs = aPage.getEditorReferences();
+ for (IEditorReference editorReference : refs) {
+ try {
+ if (editorReference.getEditorInput().equals(tmpInput)) {
+ localEditor = editorReference.getEditor(true);
+ if (localEditor != null) {
+ aPage.bringToTop(localEditor);
+ }
+ }
+ } catch (PartInitException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfImportHelper.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfImportHelper.java
new file mode 100644
index 0000000000..24ea161dc1
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/model/TmfImportHelper.java
@@ -0,0 +1,76 @@
+/**********************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.model;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+
+/**
+ * Import helper used to import traces
+ *
+ * It has two purposes: - import files and directories into projects - set the
+ * resource types
+ *
+ * @author Matthew Khouzam
+ */
+public class TmfImportHelper {
+
+ /**
+ * Create a link and replace what was already there.
+ *
+ * @param parentFolder
+ * the resource to import to, does not contain the element name
+ * @param location
+ * where the resource (file/directory) is located
+ * @param targetName
+ * the name to display
+ * @return the resource created. Should not be null
+ * @throws CoreException
+ * an exception made by createLink.
+ */
+ public static IResource createLink(IFolder parentFolder, IPath location, String targetName) throws CoreException {
+ File source = new File(location.toString());
+ IResource res = null;
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ if (source.isDirectory()) {
+ IFolder folder = parentFolder.getFolder(targetName);
+ IStatus result = workspace.validateLinkLocation(folder, location);
+ if (result.isOK() || result.matches(IStatus.INFO | IStatus.WARNING)) {
+ folder.createLink(location, IResource.REPLACE, new NullProgressMonitor());
+ } else {
+ Activator.getDefault().logError(result.getMessage());
+ }
+ } else {
+ IFile file = parentFolder.getFile(targetName);
+ IStatus result = workspace.validateLinkLocation(file, location);
+ if (result.isOK() || result.matches(IStatus.INFO | IStatus.WARNING)) {
+ file.createLink(location, IResource.REPLACE,
+ new NullProgressMonitor());
+ } else {
+ Activator.getDefault().logError(result.getMessage());
+ }
+ }
+ res = parentFolder.findMember(targetName);
+ return res;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/operations/TmfWorkspaceModifyOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/operations/TmfWorkspaceModifyOperation.java
new file mode 100644
index 0000000000..6fe11e1098
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/operations/TmfWorkspaceModifyOperation.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson
+ *
+ * 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:
+ * Bernd Hufmann - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.tmf.ui.project.operations;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+
+/**
+ * Operation to modify the workspace that refreshes workspace at the end of the operation.
+ *
+ * For refreshing periodically use {@link WorkspaceModifyOperation} instead.
+ *
+ * @author Bernd Hufmann
+ *
+ */
+public abstract class TmfWorkspaceModifyOperation implements IRunnableWithProgress {
+
+ private ISchedulingRule rule;
+
+ /**
+ * Creates a new operation.
+ */
+ protected TmfWorkspaceModifyOperation() {
+ this(ResourcesPlugin.getWorkspace().getRoot());
+ }
+
+ /**
+ * Creates a new operation that will run using the provided scheduling rule.
+ *
+ * @param rule
+ * The ISchedulingRule to use or <code>null</code>.
+ */
+ protected TmfWorkspaceModifyOperation(ISchedulingRule rule) {
+ this.rule = rule;
+ }
+
+ @Override
+ public final synchronized void run(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ final InvocationTargetException[] iteHolder = new InvocationTargetException[1];
+ try {
+ IWorkspaceRunnable workspaceRunnable = new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor pm) throws CoreException {
+ try {
+ execute(pm);
+ } catch (InvocationTargetException e) {
+ // Pass it outside the workspace runnable
+ iteHolder[0] = e;
+ } catch (InterruptedException e) {
+ // Re-throw as OperationCanceledException, which will be
+ // caught and re-thrown as InterruptedException below.
+ throw new OperationCanceledException(e.getMessage());
+ }
+ // CoreException and OperationCanceledException are propagated
+ }
+ };
+
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ workspace.run(workspaceRunnable, rule, IWorkspace.AVOID_UPDATE, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } catch (OperationCanceledException e) {
+ throw new InterruptedException(e.getMessage());
+ }
+ // Re-throw the InvocationTargetException, if any occurred
+ if (iteHolder[0] != null) {
+ throw iteHolder[0];
+ }
+ }
+
+ /**
+ * Performs the steps that are to be treated as a single logical workspace
+ * change.
+ * <p>
+ * Subclasses must implement this method.
+ * </p>
+ *
+ * @param monitor
+ * the progress monitor to use to display progress and field user
+ * requests to cancel
+ * @exception CoreException
+ * if the operation fails due to a CoreException
+ * @exception InvocationTargetException
+ * if the operation fails due to an exception other than
+ * CoreException
+ * @exception InterruptedException
+ * if the operation detects a request to cancel, using
+ * <code>IProgressMonitor.isCanceled()</code>, it should exit
+ * by throwing <code>InterruptedException</code>. It is also
+ * possible to throw <code>OperationCanceledException</code>,
+ * which gets mapped to <code>InterruptedException</code> by
+ * the <code>run</code> method.
+ */
+ protected abstract void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException;
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/AbstractImportTraceWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/AbstractImportTraceWizardPage.java
new file mode 100644
index 0000000000..c14f1a9942
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/AbstractImportTraceWizardPage.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.tmf.core.TmfProjectNature;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.WizardResourceImportPage;
+
+/**
+ * The abstract import trace wizard page, the base for the import trace wizard
+ * pages.
+ *
+ * @author Matthew Khouzam
+ */
+abstract class AbstractImportTraceWizardPage extends WizardResourceImportPage {
+
+ /**
+ * Import String
+ */
+ protected static final String BATCH_IMPORT_WIZARD_PAGE = "BatchImportWizardPage"; //$NON-NLS-1$
+
+ /**
+ * The trace folder, something like "/<project name>/Traces/"
+ */
+ protected IFolder fTargetFolder;
+
+ /**
+ * The project "/<project name>"
+ */
+ protected IProject fProject;
+
+ /**
+ * The batch import trace wizard (parent)
+ */
+ private BatchImportTraceWizard fBatchImportTraceWizard;
+
+ /**
+ * @param name
+ * the name of the page
+ * @param selection
+ * The current selection
+ */
+ protected AbstractImportTraceWizardPage(String name, IStructuredSelection selection) {
+ super(name, selection);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param workbench
+ * The workbench reference.
+ * @param selection
+ * The current selection
+ */
+ public AbstractImportTraceWizardPage(IWorkbench workbench, IStructuredSelection selection) {
+ this(BATCH_IMPORT_WIZARD_PAGE, selection);
+ setTitle(null);
+ setDescription(null);
+
+ // Locate the target trace folder
+ IFolder traceFolder = null;
+ Object element = selection.getFirstElement();
+
+ if (element instanceof TmfTraceFolder) {
+ TmfTraceFolder tmfTraceFolder = (TmfTraceFolder) element;
+ fProject = (tmfTraceFolder.getProject().getResource());
+ traceFolder = tmfTraceFolder.getResource();
+ } else if (element instanceof IProject) {
+ IProject project = (IProject) element;
+ try {
+ if (project.hasNature(TmfProjectNature.ID)) {
+ traceFolder = (IFolder) project.findMember(TmfTracesFolder.TRACES_FOLDER_NAME);
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ // Set the target trace folder
+ if (traceFolder != null) {
+ fTargetFolder = (traceFolder);
+ String path = traceFolder.getFullPath().toOSString();
+ setContainerFieldValue(path);
+ }
+
+ }
+
+ /**
+ * The Batch Import Wizard
+ *
+ * @return the Batch Import Wizard
+ */
+ public BatchImportTraceWizard getBatchWizard() {
+ return fBatchImportTraceWizard;
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayout(new GridLayout());
+ composite.setFont(parent.getFont());
+ // arbitrary size
+ final GridData layoutData = new GridData();
+ parent.getShell().setLayoutData(layoutData);
+ parent.getShell().redraw();
+ this.setControl(composite);
+
+ // arbitrary sizes
+ parent.getShell().setMinimumSize(new Point(525, 400));
+ fBatchImportTraceWizard = (BatchImportTraceWizard) getWizard();
+ }
+
+ // the following methods are stubbed out on purpose.
+
+ @Override
+ protected void createSourceGroup(Composite parent) {
+ // do nothing
+ }
+
+ @Override
+ protected ITreeContentProvider getFileProvider() {
+ // do nothing
+ return null;
+ }
+
+ @Override
+ protected ITreeContentProvider getFolderProvider() {
+ // do nothing
+ return null;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java
new file mode 100644
index 0000000000..6a3a840a8d
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java
@@ -0,0 +1,695 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Marc-Andre Laperle - Log some exceptions
+ * Patrick Tasse - Add support for source location
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingQueue;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.model.TmfImportHelper;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceValidationHelper;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+
+/**
+ * Batch Import trace wizard.
+ *
+ * @author Matthew Khouzam
+ */
+public class BatchImportTraceWizard extends ImportTraceWizard {
+
+ private static final int WIN_HEIGHT = 400;
+ private static final int WIN_WIDTH = 800;
+ private static final Status CANCEL_STATUS = new Status(IStatus.CANCEL, Activator.PLUGIN_ID, ""); //$NON-NLS-1$
+ private static final int TOTALWORK = 65536;
+ // -----------------
+ // Constants
+ // -----------------
+
+ private static final int MAX_FILES = TOTALWORK - 1;
+ private static final String BATCH_IMPORT_WIZARD = "BatchImportTraceWizard"; //$NON-NLS-1$
+
+ // ------------------
+ // Fields
+ // ------------------
+
+ private IWizardPage fSelectDirectoriesPage;
+ private ImportTraceWizardScanPage fScanPage;
+ private IWizardPage fSelectTypePage;
+ private IWizardPage fOptions;
+
+ private final List<String> fTraceTypesToScan = new ArrayList<>();
+ private final Set<String> fParentFilesToScan = new HashSet<>();
+
+ private ImportTraceContentProvider fScannedTraces = new ImportTraceContentProvider(fTraceTypesToScan, fParentFilesToScan);
+
+ private final Map<TraceValidationHelper, Boolean> fResults = new HashMap<>();
+ private boolean fOverwrite = true;
+ private boolean fLinked = true;
+
+ private BlockingQueue<TraceValidationHelper> fTracesToScan;
+ private final Set<FileAndName> fTraces = new TreeSet<>();
+
+ private Map<String, Set<String>> fParentFiles = new HashMap<>();
+
+ // Target import directory (trace folder)
+ private IFolder fTargetFolder;
+
+ /**
+ * Returns the ScannedTraces model
+ *
+ * @return the ScannedTraces model
+ */
+ public ImportTraceContentProvider getScannedTraces() {
+ return fScannedTraces;
+ }
+
+ /**
+ * Constructor
+ */
+ public BatchImportTraceWizard() {
+ IDialogSettings workbenchSettings = Activator.getDefault().getDialogSettings();
+ IDialogSettings section = workbenchSettings.getSection(BATCH_IMPORT_WIZARD);
+ if (section == null) {
+ section = workbenchSettings.addNewSection(BATCH_IMPORT_WIZARD);
+ }
+ setDialogSettings(section);
+ setNeedsProgressMonitor(true);
+ }
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+
+ fSelectDirectoriesPage = new ImportTraceWizardSelectDirectoriesPage(workbench, selection);
+ fScanPage = new ImportTraceWizardScanPage(workbench, selection);
+ fSelectTypePage = new ImportTraceWizardSelectTraceTypePage(workbench, selection);
+ fOptions = new ImportTraceWizardPageOptions(workbench, selection);
+ // keep in case it's called later
+ Iterator<?> iter = selection.iterator();
+ while (iter.hasNext()) {
+ Object selected = iter.next();
+ if (selected instanceof TmfTraceFolder) {
+ fTargetFolder = ((TmfTraceFolder) selected).getResource();
+ break;
+ }
+ }
+ fResults.clear();
+ }
+
+ @Override
+ public void addPages() {
+ addPage(fSelectTypePage);
+ addPage(fSelectDirectoriesPage);
+ addPage(fScanPage);
+ addPage(fOptions);
+ final WizardDialog container = (WizardDialog) getContainer();
+ if (container != null) {
+ container.setPageSize(WIN_WIDTH, WIN_HEIGHT);
+ }
+ }
+
+ /**
+ * Add a file to scan
+ *
+ * @param fileName
+ * the file to scan
+ */
+ public void addFileToScan(final String fileName) {
+ String absolutePath = new File(fileName).getAbsolutePath();
+ if (!fParentFiles.containsKey(absolutePath)) {
+ fParentFiles.put(absolutePath, new HashSet<String>());
+ startUpdateTask(Messages.BatchImportTraceWizardAdd + ' ' + absolutePath, absolutePath);
+
+ }
+
+ }
+
+ /**
+ * Remove files from selection
+ *
+ * @param fileName
+ * the name of the file to remove
+ */
+ public void removeFile(final String fileName) {
+ fParentFiles.remove(fileName);
+ fParentFilesToScan.remove(fileName);
+ startUpdateTask(Messages.BatchImportTraceWizardRemove + ' ' + fileName, null);
+ }
+
+ private void startUpdateTask(final String taskName, final String fileAbsolutePath) {
+ try {
+ this.getContainer().run(true, true, new IRunnableWithProgress() {
+
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ synchronized (BatchImportTraceWizard.this) { // this should
+ // only run one
+ // at a time
+ SubMonitor sm;
+ sm = SubMonitor.convert(monitor);
+ sm.setTaskName(taskName);
+ sm.setWorkRemaining(TOTALWORK);
+ updateFiles(sm, fileAbsolutePath);
+ sm.done();
+ }
+ }
+ });
+ } catch (InvocationTargetException e) {
+ Activator.getDefault().logError(Messages.ImportTraceWizardImportProblem, e);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ /**
+ * The set of names of the selected files
+ *
+ * @return the set of names of the selected files
+ */
+ public Set<String> getFileNames() {
+ return fParentFilesToScan;
+ }
+
+ /**
+ * Reset the trace list to import
+ */
+ public void clearTraces() {
+ fTraces.clear();
+ }
+
+ @Override
+ public boolean performFinish() {
+ if (fTraces.isEmpty()) {
+ return false;
+ }
+ // if this turns out to be too slow, put in a progress monitor. Does not
+ // appear to be slow for the moment.
+ boolean success = importTraces();
+ return success;
+ }
+
+ private boolean importTraces() {
+ boolean success = false;
+ IOverwriteQuery overwriteQuery = new IOverwriteQuery() {
+ @Override
+ public String queryOverwrite(String file) {
+ return fOverwrite ? IOverwriteQuery.ALL : IOverwriteQuery.NO_ALL;
+ }
+ };
+ FileSystemStructureProvider fileSystemStructureProvider = FileSystemStructureProvider.INSTANCE;
+
+ for (FileAndName traceToImport : fTraces) {
+ try {
+ if (fLinked) {
+ if (TmfImportHelper.createLink(fTargetFolder, Path.fromOSString(traceToImport.getFile().getAbsolutePath()), traceToImport.getName()) == null) {
+ success = false;
+ }
+ else {
+ success = setTraceTypeAndSourceLocation(traceToImport).isOK();
+ }
+ }
+ else {
+ List<File> subList = new ArrayList<>();
+ IPath path = fTargetFolder.getFullPath();
+ File parentFile = traceToImport.getFile();
+ final boolean isFile = parentFile.isFile();
+ if (isFile) {
+ IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path.append(traceToImport.getName()));
+ if (fOverwrite || !resource.exists()) {
+ subList.add(parentFile);
+ parentFile = parentFile.getParentFile();
+ try (final FileInputStream source = new FileInputStream(traceToImport.getFile());) {
+ if (resource.exists()) {
+ resource.delete(IResource.FORCE, new NullProgressMonitor());
+ }
+ resource.create(source, true, new NullProgressMonitor());
+ }
+ setTraceTypeAndSourceLocation(traceToImport);
+ success = true;
+ }
+ } else {
+ path = path.addTrailingSeparator().append(traceToImport.getName());
+ // Add all files in trace directory
+ File[] fileList = traceToImport.getFile().listFiles();
+ for (File child : fileList) {
+ subList.add(child);
+ }
+
+ Collections.sort(subList, new Comparator<File>() {
+ @Override
+ public int compare(File o1, File o2) {
+ return o1.getAbsolutePath().compareTo(o2.getAbsolutePath());
+ }
+ });
+ ImportOperation operation = new ImportOperation(
+ path,
+ parentFile,
+ fileSystemStructureProvider,
+ overwriteQuery,
+ subList);
+ operation.setContext(getShell());
+ operation.setCreateContainerStructure(false);
+ if (executeImportOperation(operation)) {
+ setTraceTypeAndSourceLocation(traceToImport);
+ success = true;
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ }
+ }
+ return success;
+ }
+
+ private IStatus setTraceTypeAndSourceLocation(FileAndName traceToImport) {
+ IStatus status = Status.OK_STATUS;
+ IResource resource = fTargetFolder.findMember(traceToImport.getName());
+ if (resource != null) {
+ try {
+ // Set the trace type for this resource
+ String traceTypeId = traceToImport.getTraceTypeId();
+ TraceTypeHelper traceType = TmfTraceType.getTraceType(traceTypeId);
+ if (traceType != null) {
+ status = TmfTraceTypeUIUtils.setTraceType(resource, traceType);
+ }
+
+ // Set the source location for this resource
+ File file = traceToImport.getFile();
+ String sourceLocation = null;
+ IResource sourceResource;
+ if (file.isDirectory()) {
+ sourceResource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(Path.fromOSString(file.getAbsolutePath()));
+ } else {
+ sourceResource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(file.getAbsolutePath()));
+ }
+ if (sourceResource != null && sourceResource.exists()) {
+ sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION);
+ }
+ if (sourceLocation == null) {
+ sourceLocation = URIUtil.toUnencodedString(file.toURI());
+ }
+ resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ } catch (CoreException e) {
+ Activator.getDefault().logError(Messages.BatchImportTraceWizardErrorImportingTraceResource
+ + ' ' + resource.getName(), e);
+ }
+ }
+ return status;
+ }
+
+ @Override
+ public boolean canFinish() {
+ return super.canFinish() && hasTracesToImport() && !hasConflicts() && (fTargetFolder != null);
+ }
+
+ /**
+ * Returns if a trace to import is selected
+ *
+ * @return if there are traces to import
+ */
+ public boolean hasTracesToImport() {
+ return fTraces.size() > 0;
+ }
+
+ /**
+ * Reset the files to scan
+ */
+ public void clearFilesToScan() {
+ fTracesToScan.clear();
+ }
+
+ /**
+ * Set the trace types to scan
+ *
+ * @param tracesToScan
+ * a list of trace types to scan for
+ */
+ public void setTraceTypesToScan(List<String> tracesToScan) {
+ // intersection to know if there's a diff.
+ // if there's a diff, we need to re-enque everything
+ List<String> added = new ArrayList<>();
+ for (String traceLoc : tracesToScan) {
+ if (!fTraceTypesToScan.contains(traceLoc)) {
+ added.add(traceLoc);
+ }
+ }
+ fTraceTypesToScan.clear();
+ fTraceTypesToScan.addAll(tracesToScan);
+ updateTracesToScan(added);
+ }
+
+ /**
+ * Get the trace types to scan
+ *
+ * @return a list of traces to Scan for
+ */
+ public List<String> getTraceTypesToScan() {
+ return fTraceTypesToScan;
+ }
+
+ /**
+ * Add files to Import
+ *
+ * @param element
+ * add the file and tracetype to import
+ */
+ public void addFileToImport(FileAndName element) {
+ fTraces.add(element);
+ updateConflicts();
+ }
+
+ /**
+ * Remove the file to scan
+ *
+ * @param element
+ * the element to remove
+ */
+ public void removeFileToImport(FileAndName element) {
+ fTraces.remove(element);
+ element.setConflictingName(false);
+ updateConflicts();
+ }
+
+ /**
+ * Updates the trace to see if there are conflicts.
+ */
+ public void updateConflicts() {
+ final FileAndName[] fChildren = fTraces.toArray(new FileAndName[0]);
+ for (int i = 0; i < fChildren.length; i++) {
+ fChildren[i].setConflictingName(false);
+ }
+ for (int i = 1; i < fChildren.length; i++) {
+ for (int j = 0; j < i; j++) {
+ if (fChildren[i].getName().equals(fChildren[j].getName())) {
+ fChildren[i].setConflictingName(true);
+ fChildren[j].setConflictingName(true);
+ }
+ }
+ }
+ getContainer().updateButtons();
+ }
+
+ /**
+ * Is there a name conflict
+ */
+ boolean hasConflicts() {
+ boolean conflict = false;
+ for (FileAndName child : fTraces) {
+ conflict |= child.isConflictingName();
+ }
+ return conflict;
+ }
+
+ private boolean executeImportOperation(ImportOperation op) {
+ initializeOperation(op);
+
+ try {
+ getContainer().run(true, true, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Activator.getDefault().logError(Messages.ImportTraceWizardImportProblem, e);
+ return false;
+ }
+
+ IStatus status = op.getStatus();
+ if (!status.isOK()) {
+ ErrorDialog.openError(getContainer().getShell(), Messages.ImportTraceWizardImportProblem, null, status);
+ return false;
+ }
+
+ return true;
+ }
+
+ private static void initializeOperation(ImportOperation op) {
+ op.setCreateContainerStructure(false);
+ op.setOverwriteResources(false);
+ op.setVirtualFolders(false);
+ }
+
+ /**
+ * Override existing resources
+ *
+ * @param selection
+ * true or false
+ */
+ public void setOverwrite(boolean selection) {
+ fOverwrite = selection;
+ }
+
+ /**
+ * Is the trace linked?
+ *
+ * @param isLink
+ * true or false
+ */
+ public void setLinked(boolean isLink) {
+ fLinked = isLink;
+ }
+
+ /**
+ * @param tracesToScan
+ * sets the common traces to scan
+ */
+ public void setTracesToScan(BlockingQueue<TraceValidationHelper> tracesToScan) {
+ fTracesToScan = tracesToScan;
+ }
+
+ /**
+ * @param traceToScan
+ * The trace to scan
+ * @return if the trace has been scanned yet or not
+ */
+ public boolean hasScanned(TraceValidationHelper traceToScan) {
+ return fResults.containsKey(traceToScan);
+ }
+
+ /**
+ * Add a result to a cache
+ *
+ * @param traceToScan
+ * The trace that has been scanned
+ * @param validate
+ * if the trace is valid
+ */
+ public void addResult(TraceValidationHelper traceToScan, boolean validate) {
+ fResults.put(traceToScan, validate);
+ }
+
+ /**
+ * Gets if the trace has been scanned or not
+ *
+ * @param traceToScan
+ * the scanned trace
+ * @return whether it passes or not
+ */
+ public boolean getResult(TraceValidationHelper traceToScan) {
+ return fResults.get(traceToScan);
+ }
+
+ /**
+ * Returns the amount of files scanned
+ *
+ * @return the amount of files scanned
+ */
+ public int getNumberOfResults() {
+ return fResults.size();
+ }
+
+ private void updateTracesToScan(final List<String> added) {
+ // Treeset is used instead of a hashset since the traces should be read
+ // in the order they were added.
+ final Set<String> filesToScan = new TreeSet<>();
+ for (String name : fParentFiles.keySet()) {
+ filesToScan.addAll(fParentFiles.get(name));
+ }
+ IProgressMonitor pm = new NullProgressMonitor();
+ try {
+ updateScanQueue(pm, filesToScan, added);
+ } catch (InterruptedException e) {
+ }
+
+ }
+
+ /*
+ * I am a job. Make me work
+ */
+ private synchronized IStatus updateFiles(IProgressMonitor monitor, String traceToScanAbsPath) {
+ final Set<String> filesToScan = new TreeSet<>();
+
+ int workToDo = 1;
+ for (String name : fParentFiles.keySet()) {
+
+ final File file = new File(name);
+ final File[] listFiles = file.listFiles();
+ if (listFiles != null) {
+ workToDo += listFiles.length;
+ }
+ }
+ int step = TOTALWORK / workToDo;
+ try {
+ for (String name : fParentFiles.keySet()) {
+ final File fileToAdd = new File(name);
+ final Set<String> parentFilesToScan = fParentFiles.get(fileToAdd.getAbsolutePath());
+ recurse(parentFilesToScan, fileToAdd, monitor, step);
+ if (monitor.isCanceled()) {
+ fParentFilesToScan.remove(traceToScanAbsPath);
+ fParentFiles.remove(traceToScanAbsPath);
+ return CANCEL_STATUS;
+ }
+ }
+ filesToScan.clear();
+ for (String name : fParentFiles.keySet()) {
+ filesToScan.addAll(fParentFiles.get(name));
+ fParentFilesToScan.add(name);
+ }
+ IStatus cancelled = updateScanQueue(monitor, filesToScan, fTraceTypesToScan);
+ if (cancelled.matches(IStatus.CANCEL)) {
+ fParentFilesToScan.remove(traceToScanAbsPath);
+ fParentFiles.remove(traceToScanAbsPath);
+ }
+ } catch (InterruptedException e) {
+ monitor.done();
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
+ }
+
+ monitor.done();
+ return Status.OK_STATUS;
+ }
+
+ private IStatus updateScanQueue(IProgressMonitor monitor, final Set<String> filesToScan, final List<String> traceTypes) throws InterruptedException {
+ for (String fileToScan : filesToScan) {
+ for (String traceCat : traceTypes) {
+ TraceValidationHelper tv = new TraceValidationHelper(fileToScan, traceCat);
+ // for thread safety, keep checks in this order.
+ if (!fResults.containsKey(tv)) {
+ if (!fTracesToScan.contains(tv)) {
+ fTracesToScan.put(tv);
+ monitor.subTask(tv.getTraceToScan());
+ if (monitor.isCanceled()) {
+ fScanPage.refresh();
+ return CANCEL_STATUS;
+ }
+ }
+ }
+ }
+ }
+ fScanPage.refresh();
+ return Status.OK_STATUS;
+ }
+
+ private IStatus recurse(Set<String> filesToScan, File fileToAdd, IProgressMonitor monitor, int step) {
+ final String absolutePath = fileToAdd.getAbsolutePath();
+ if (!filesToScan.contains(absolutePath) && (filesToScan.size() < MAX_FILES)) {
+ filesToScan.add(absolutePath);
+ final File[] listFiles = fileToAdd.listFiles();
+ if (null != listFiles) {
+ for (File child : listFiles) {
+ monitor.subTask(child.getName());
+ if (monitor.isCanceled()) {
+ return CANCEL_STATUS;
+ }
+ IStatus retVal = recurse(filesToScan, child, monitor);
+ if (retVal.matches(IStatus.CANCEL)) {
+ return retVal;
+ }
+ monitor.worked(step);
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ private IStatus recurse(Set<String> filesToScan, File fileToAdd, IProgressMonitor monitor) {
+ final String absolutePath = fileToAdd.getAbsolutePath();
+ if (!filesToScan.contains(absolutePath) && (filesToScan.size() < MAX_FILES)) {
+ filesToScan.add(absolutePath);
+ final File[] listFiles = fileToAdd.listFiles();
+ if (null != listFiles) {
+ for (File child : listFiles) {
+ if (monitor.isCanceled()) {
+ return CANCEL_STATUS;
+ }
+ IStatus retVal = recurse(filesToScan, child, monitor);
+ if (retVal.matches(IStatus.CANCEL)) {
+ return retVal;
+ }
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Gets the folder in the resource (project)
+ *
+ * @param targetFolder
+ * the folder to import to
+ */
+ public void setTraceFolder(IFolder targetFolder) {
+ fTargetFolder = targetFolder;
+ if (this.getContainer() != null && this.getContainer().getCurrentPage() != null) {
+ this.getContainer().updateButtons();
+ }
+ }
+
+ /**
+ * Gets the target folder
+ *
+ * @return the target folder
+ */
+ public IFolder getTargetFolder() {
+ return fTargetFolder;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileAndName.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileAndName.java
new file mode 100644
index 0000000000..8120aa743c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileAndName.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.equalsNullable;
+
+/**
+ * File and name internal helper class <br>
+ * it has the file, a name to display, whether the name is conflicting and a
+ * reference to the configuration element defining its trace type.
+ *
+ * @author Matthew Khouzam
+ */
+class FileAndName implements Comparable<FileAndName> {
+
+ private final File fFile;
+ private String fTraceTypeId;
+ private String fName;
+ private boolean fConflict;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * A file and name
+ *
+ * @param f
+ * the file, can only be set here
+ * @param n
+ * the name, can be renamed
+ *
+ */
+ public FileAndName(File f, String n) {
+ fFile = f;
+ fName = n;
+ fTraceTypeId = null;
+ }
+
+ // ------------------------------------------------------------------------
+ // Getter / Setter
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the name
+ *
+ * @return the name
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Set the name
+ *
+ * @param name
+ * the name to set
+ */
+ public void setName(String name) {
+ this.fName = name;
+ }
+
+ /**
+ * Sets the configuration element of the
+ *
+ * @param elem
+ * the element
+ */
+ public void setTraceTypeId(String elem) {
+ fTraceTypeId = elem;
+ }
+
+ /**
+ * Gets the configuration element canonical name
+ *
+ * @return gets the configuration element canonical name
+ */
+ public String getTraceTypeId() {
+ return fTraceTypeId;
+ }
+
+ /**
+ * Get the file
+ *
+ * @return the file
+ */
+ public File getFile() {
+ return fFile;
+ }
+
+ /**
+ * Set that the name is conflicting or not
+ *
+ * @param conflict
+ * if the name is conflicting or not
+ */
+ public void setConflictingName(boolean conflict) {
+ fConflict = conflict;
+ }
+
+ /**
+ * Is the name conflicting?
+ *
+ * @return is the name conflicting?
+ */
+ public boolean isConflictingName() {
+ return fConflict;
+ }
+
+ /**
+ * Is the fileAndName renamed
+ *
+ * @return true if the name does not match the filename
+ */
+ public boolean isRenamed() {
+ return !fName.equals(fFile.getName());
+ }
+
+ // ------------------------------------------------------------------------
+ // Comparator & Equals
+ // ------------------------------------------------------------------------
+
+ @Override
+ public int compareTo(FileAndName o) {
+ int retVal = getFile().compareTo(o.getFile());
+ if (retVal == 0 && getTraceTypeId() != null && o.getTraceTypeId() != null) {
+ retVal = getTraceTypeId().compareTo(o.getTraceTypeId());
+ }
+ return retVal;
+ }
+
+ @Override
+ public int hashCode() {
+ // do not take "name" into account since it can change on the fly.
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((fTraceTypeId == null) ? 0 : fTraceTypeId.hashCode());
+ result = prime * result + ((fFile == null) ? 0 : fFile.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // do not take "name" into account since it can change on the fly.
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof FileAndName)) {
+ return false;
+ }
+ FileAndName other = (FileAndName) obj;
+ if (!equalsNullable(fTraceTypeId, other.fTraceTypeId)) {
+ return false;
+ }
+ if (!equalsNullable(fFile, other.fFile)) {
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipEntry.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipEntry.java
new file mode 100644
index 0000000000..d0ffc11136
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipEntry.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation. Inspired from TarEntry.
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+/**
+ * GZip entry
+ */
+public class GzipEntry {
+ private static final int MILLIS_PER_SECOND = 1000;
+ private static final int READ_WRITE_USER_READ_GROUP = 0644;
+ private static final String ROOT_DIR = "/"; //$NON-NLS-1$
+ private final String fName;
+ private final long fMode;
+ private final long fTime;
+ private final int fType;
+
+ /**
+ * Entry type for normal files. This is the only valid type for Gzip
+ * entries.
+ */
+ public static final int FILE = '0';
+
+ /**
+ * Entry type for directories. This doesn't really exist in a Gzip but it's
+ * useful to represent the root of the archive.
+ */
+ public static final int DIRECTORY = '5';
+
+ /**
+ * Create a new Root GzipEntry
+ */
+ public GzipEntry() {
+ fName = ROOT_DIR;
+ fMode = READ_WRITE_USER_READ_GROUP;
+ fType = DIRECTORY;
+ fTime = System.currentTimeMillis() / MILLIS_PER_SECOND;
+ }
+
+ /**
+ * Create a new GzipEntry for a file of the given name at the given position
+ * in the file.
+ *
+ * @param name
+ * filename
+ */
+ public GzipEntry(String name) {
+ fName = name;
+ fMode = READ_WRITE_USER_READ_GROUP;
+ fType = FILE;
+ fTime = System.currentTimeMillis() / MILLIS_PER_SECOND;
+ }
+
+ /**
+ * Returns the type of this file, can only be FILE for a real Gzip entry.
+ * DIRECTORY can be specified to represent a "dummy root" in the archive.
+ *
+ * @return file type
+ */
+ public int getFileType() {
+ return fType;
+ }
+
+ /**
+ * Returns the mode of the file in UNIX permissions format.
+ *
+ * @return file mode
+ */
+ public long getMode() {
+ return fMode;
+ }
+
+ /**
+ * Returns the name of the file.
+ *
+ * @return filename
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Returns the modification time of the file in seconds since January 1st
+ * 1970.
+ *
+ * @return time
+ */
+ public long getTime() {
+ return fTime;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFile.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFile.java
new file mode 100644
index 0000000000..a505ac6a99
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFile.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation.
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * Wrapper for a Gzipped file
+ */
+public class GzipFile implements AutoCloseable {
+
+ private static final String GZIP_EXTENSION = ".gz"; //$NON-NLS-1$
+
+ private final File fFile;
+ private final GzipEntry fEntry;
+ private GzipEntry fCurEntry;
+ private boolean fIsClosed = false;
+
+ private final InputStream fInternalEntryStream;
+
+ /**
+ * Create a new GzipFile for the given file.
+ *
+ * @param source the source file
+ * @throws IOException
+ * File not found and such
+ */
+ public GzipFile(File source) throws IOException {
+ fFile = source;
+
+ InputStream in = new FileInputStream(source);
+ try {
+ // Check if it's a GZIPInputStream.
+ fInternalEntryStream = new GZIPInputStream(in);
+ } catch (IOException e) {
+ in.close();
+ throw e;
+ }
+ String name = source.getName();
+ fEntry = new GzipEntry(name.substring(0, name.lastIndexOf(GZIP_EXTENSION)));
+ fCurEntry = fEntry;
+ }
+
+ /**
+ * Close the tar file input stream.
+ *
+ * @throws IOException if the file cannot be successfully closed
+ */
+ @Override
+ public void close() throws IOException {
+ if (fInternalEntryStream != null && !fIsClosed) {
+ fInternalEntryStream.close();
+ fIsClosed = true;
+
+ }
+ }
+
+ /**
+ * Create a new GzipFile for the given path name.
+ *
+ * @param filename
+ * the filename of the gzip file
+ * @throws IOException
+ * if the file cannot be opened
+ */
+ public GzipFile(String filename) throws IOException {
+ this(new File(filename));
+ }
+
+ /**
+ * Returns an enumeration cataloguing the tar archive.
+ *
+ * @return enumeration of all files in the archive
+ */
+ public Enumeration<GzipEntry> entries() {
+ return new Enumeration<GzipEntry>() {
+ @Override
+ public boolean hasMoreElements() {
+ return (fCurEntry != null);
+ }
+
+ @Override
+ public GzipEntry nextElement() {
+ GzipEntry oldEntry = fCurEntry;
+ fCurEntry = null;
+ return oldEntry;
+ }
+ };
+ }
+
+ /**
+ * Returns a new InputStream for the given file in the tar archive.
+ *
+ * @param entry
+ * the GzipEntry
+ * @return an input stream for the given file
+ */
+ public InputStream getInputStream(GzipEntry entry) {
+ if (entry != fEntry) {
+ throw new IllegalArgumentException();
+ }
+ return fInternalEntryStream;
+ }
+
+ /**
+ * Returns the path name of the file this archive represents.
+ *
+ * @return path
+ */
+ public String getName() {
+ return fFile.getPath();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipLeveledStructureProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipLeveledStructureProvider.java
new file mode 100644
index 0000000000..47da8ea657
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipLeveledStructureProvider.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation.
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
+import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider;
+
+/**
+ * Leveled Structure provider for Gzip file
+ */
+@SuppressWarnings("restriction")
+public class GzipLeveledStructureProvider implements ILeveledImportStructureProvider {
+
+ private final GzipFile fFile;
+ private final GzipEntry root = new GzipEntry();
+ private final GzipEntry fEntry;
+
+ /**
+ * Creates a <code>GzipFileStructureProvider</code>, which will operate on
+ * the passed Gzip file.
+ *
+ * @param sourceFile
+ * the source GzipFile
+ */
+ public GzipLeveledStructureProvider(GzipFile sourceFile) {
+ super();
+
+ fFile = sourceFile;
+ fEntry = sourceFile.entries().nextElement();
+ }
+
+ @Override
+ public List getChildren(Object element) {
+ ArrayList<Object> children = new ArrayList<>();
+ if (element == root) {
+ children.add(fEntry);
+ }
+ return children;
+ }
+
+ @Override
+ public InputStream getContents(Object element) {
+ return fFile.getInputStream((GzipEntry) element);
+ }
+
+ @Override
+ public String getFullPath(Object element) {
+ return ((GzipEntry) element).getName();
+ }
+
+ @Override
+ public String getLabel(Object element) {
+ if (element != root && element != fEntry) {
+ throw new IllegalArgumentException();
+ }
+ return ((GzipEntry) element).getName();
+ }
+
+ /**
+ * Returns the entry that this importer uses as the root sentinel.
+ *
+ * @return GzipEntry entry
+ */
+ @Override
+ public GzipEntry getRoot() {
+ return root;
+ }
+
+ @Override
+ public boolean closeArchive() {
+ try {
+ fFile.close();
+ } catch (IOException e) {
+ Activator.getDefault().logError(DataTransferMessages.ZipImport_couldNotClose
+ + fFile.getName(), e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isFolder(Object element) {
+ return ((GzipEntry) element).getFileType() == GzipEntry.DIRECTORY;
+ }
+
+ @Override
+ public void setStrip(int level) {
+ // Do nothing
+ }
+
+ @Override
+ public int getStrip() {
+ return 0;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConfirmation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConfirmation.java
new file mode 100644
index 0000000000..49f4ff8729
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConfirmation.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson.
+ *
+ * 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:
+ * Bernd Hufmann - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+/**
+ * Enumeration for import conflict dialog
+ *
+ * @author Bernd Hufmann
+ */
+public enum ImportConfirmation {
+
+ // ------------------------------------------------------------------------
+ // Enum definition
+ // ------------------------------------------------------------------------
+ /** Single rename */
+ RENAME(Messages.ImportTraceWizard_ImportConfigurationRename),
+ /** Rename all */
+ RENAME_ALL(Messages.ImportTraceWizard_ImportConfigurationRenameAll),
+ /** Single overwrite */
+ OVERWRITE(Messages.ImportTraceWizard_ImportConfigurationOverwrite),
+ /** Overwrite all */
+ OVERWRITE_ALL(Messages.ImportTraceWizard_ImportConfigurationOverwriteAll),
+ /** Single skip */
+ SKIP(Messages.ImportTraceWizard_ImportConfigurationSkip),
+ /** Skip all*/
+ SKIP_ALL(Messages.ImportTraceWizard_ImportConfigurationSkipAll),
+ /** Default value*/
+ CONTINUE("CONTINUE"); //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+ /**
+ * Name of enum
+ */
+ private final String fInName;
+
+ // ------------------------------------------------------------------------
+ // Constuctor
+ // ------------------------------------------------------------------------
+ /**
+ * Private constructor
+ *
+ * @param name
+ * the name of state
+ */
+ private ImportConfirmation(String name) {
+ fInName = name;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+ /**
+ * @return state name
+ */
+ public String getInName() {
+ return fInName;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConflictHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConflictHandler.java
new file mode 100644
index 0000000000..1c2f783ff6
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportConflictHandler.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson.
+ *
+ * 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:
+ * Bernd Hufmann - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+
+/**
+ * Handler to check for name clashes during import operations. It will allow
+ * users to select renaming, overwriting or skipping of a given trace as well
+ * as upcoming traces by keeping track of the user selection. In case of
+ * overwriting the original trace will be deleted.
+ *
+ * See {@link ImportConfirmation} for users selection choices.
+ *
+ * @author Bernd Hufmann
+ */
+public class ImportConflictHandler {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+ private Shell fShell;
+ private TmfTraceFolder fTraceFolderElement;
+ private ImportConfirmation fConfirmationMode;
+
+ // ------------------------------------------------------------------------
+ // Constructor(s)
+ // ------------------------------------------------------------------------
+ /**
+ * @param shell
+ * shell to display confirmation dialog
+ * @param folder
+ * Target folder for the traces
+ * @param initialMode
+ * Initial confirmation mode
+ */
+ public ImportConflictHandler(Shell shell, TmfTraceFolder folder, ImportConfirmation initialMode) {
+ fShell = shell;
+ fTraceFolderElement = folder;
+ fConfirmationMode = initialMode;
+ }
+
+ // ------------------------------------------------------------------------
+ // Operation(s)
+ // ------------------------------------------------------------------------
+ /**
+ * It checks for name clashes. In case of a name clash it will open a
+ * confirmation dialog where the use can rename, overwrite or skip
+ * the trace. The user has also the choice to rename, overwrite or
+ * skip all traces of subsequent calls to this method. This class will
+ * keep track about the {@link ImportConfirmation} mode selected by the
+ * user.
+ *
+ * In case of {@link ImportConfirmation#RENAME} or
+ * {@link ImportConfirmation#RENAME_ALL} a new name will be return by
+ * adding sequence number surrounded by (), e.g. (1) or (2).
+ *
+ * In case of {@link ImportConfirmation#OVERWRITE} or
+ * {@link ImportConfirmation#OVERWRITE_ALL} the original trace will be
+ * deleted and the original name will be returned.
+ *
+ * In case the dialog {@link ImportConfirmation#SKIP} or
+ * {@link ImportConfirmation#SKIP_ALL} it will return null to indicate
+ * the skipping.
+ *
+ * @param tracePath
+ * The trace to check
+ * @param monitor
+ * The progress monitor
+ * @return the trace name to use or null
+ * @throws InterruptedException
+ * If the dialog box was cancelled
+ * @throws CoreException
+ * If an error during deletion occurred
+ */
+ public String checkAndHandleNameClash(IPath tracePath, IProgressMonitor monitor) throws InterruptedException, CoreException {
+ ImportConfirmation mode = checkForNameClash(tracePath);
+ switch (mode) {
+ case RENAME:
+ case RENAME_ALL:
+ return rename(tracePath);
+ case OVERWRITE:
+ case OVERWRITE_ALL:
+ delete(tracePath, monitor);
+ //$FALL-THROUGH$
+ case CONTINUE:
+ return tracePath.lastSegment();
+ case SKIP:
+ case SKIP_ALL:
+ default:
+ return null;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Helper methods
+ // ------------------------------------------------------------------------
+ private ImportConfirmation checkForNameClash(IPath tracePath) throws InterruptedException {
+ // handle rename
+ if (getExistingTrace(tracePath) != null) {
+ if ((fConfirmationMode == ImportConfirmation.RENAME_ALL) ||
+ (fConfirmationMode == ImportConfirmation.OVERWRITE_ALL) ||
+ (fConfirmationMode == ImportConfirmation.SKIP_ALL)) {
+ return fConfirmationMode;
+ }
+
+ int returnCode = promptForOverwrite(tracePath);
+ if (returnCode < 0) {
+ // Cancel
+ throw new InterruptedException();
+ }
+ fConfirmationMode = ImportConfirmation.values()[returnCode];
+ return fConfirmationMode;
+ }
+ return ImportConfirmation.CONTINUE;
+ }
+
+ private int promptForOverwrite(IPath tracePath) {
+ final MessageDialog dialog = new MessageDialog(fShell,
+ null, null, NLS.bind(Messages.ImportTraceWizard_TraceAlreadyExists, tracePath.makeRelativeTo(fTraceFolderElement.getProject().getPath())),
+ MessageDialog.QUESTION, new String[] {
+ ImportConfirmation.RENAME.getInName(),
+ ImportConfirmation.RENAME_ALL.getInName(),
+ ImportConfirmation.OVERWRITE.getInName(),
+ ImportConfirmation.OVERWRITE_ALL.getInName(),
+ ImportConfirmation.SKIP.getInName(),
+ ImportConfirmation.SKIP_ALL.getInName(),
+ }, 4) {
+ @Override
+ protected int getShellStyle() {
+ return super.getShellStyle() | SWT.SHEET;
+ }
+ };
+
+ final int[] returnValue = new int[1];
+ fShell.getDisplay().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ returnValue[0] = dialog.open();
+ }
+ });
+ return returnValue[0];
+ }
+
+ private String rename(IPath tracePath) {
+ TmfTraceElement trace = getExistingTrace(tracePath);
+ if (trace == null) {
+ return tracePath.lastSegment();
+ }
+
+ // Not using IFolder on purpose to leave the door open to import
+ // directly into an IProject
+ IContainer folder = (IContainer) trace.getParent().getResource();
+ int i = 2;
+ while (true) {
+ String name = trace.getName() + '(' + Integer.toString(i++) + ')';
+ IResource resource = folder.findMember(name);
+ if (resource == null) {
+ return name;
+ }
+ }
+ }
+
+ private void delete(IPath tracePath, IProgressMonitor monitor) throws CoreException {
+ TmfTraceElement trace = getExistingTrace(tracePath);
+ if (trace == null) {
+ return;
+ }
+
+ trace.delete(monitor);
+ }
+
+ private TmfTraceElement getExistingTrace(IPath tracePath) {
+ List<TmfTraceElement> traces = fTraceFolderElement.getTraces();
+ for (TmfTraceElement t : traces) {
+ if (t.getPath().equals(tracePath)) {
+ return t;
+ }
+ }
+ return null;
+ }
+}
+
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceContentProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceContentProvider.java
new file mode 100644
index 0000000000..8cf1ff99b4
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceContentProvider.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+
+/**
+ * A helper class to show the trace types and files and names. it contains the
+ * model which can be defined as follows : {tracetype -> { file1, file2, ... }
+ * }+
+ *
+ * @author Matthew Khouzam
+ */
+class ImportTraceContentProvider implements ITreeContentProvider {
+
+ private final Map<String, String> fTraceTypes = new HashMap<>();
+ private final Map<String, Set<FileAndName>> fTraceFiles = new HashMap<>();
+ private final List<String> fTraceTypesToScan;
+ private final Set<String> fParentFilesToScan;
+
+ public ImportTraceContentProvider(List<String> traceTypesToScan, Set<String> parentFilesToScan) {
+ fTraceTypesToScan = traceTypesToScan;
+ fParentFilesToScan = parentFilesToScan;
+ }
+
+ /**
+ * Add a trace candidate to display
+ *
+ * @param traceTypeId
+ * the trace type id of the trace
+ * @param traceToOpen
+ * the trace file.
+ */
+ public synchronized void addCandidate(String traceTypeId, File traceToOpen) {
+ TraceTypeHelper traceTypeHelper = TmfTraceType.getTraceType(traceTypeId);
+ if (traceTypeHelper == null) {
+ return;
+ }
+ fTraceTypes.put(traceTypeHelper.getName(), traceTypeId);
+ if (!fTraceFiles.containsKey(traceTypeId)) {
+ fTraceFiles.put(traceTypeId, new TreeSet<FileAndName>());
+ }
+ final FileAndName traceFile = new FileAndName(traceToOpen, traceToOpen.getName());
+ traceFile.setTraceTypeId(traceTypeId);
+ final Set<FileAndName> categorySet = fTraceFiles.get(traceTypeId);
+ categorySet.add(traceFile);
+ }
+
+ /**
+ * Reset all the candidates
+ */
+ public synchronized void clearCandidates() {
+ fTraceTypes.clear();
+ fTraceFiles.clear();
+ }
+
+ @Override
+ public void dispose() {
+ fTraceFiles.clear();
+ fTraceTypes.clear();
+
+ }
+
+ @Override
+ public synchronized void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (oldInput != newInput && newInput != null) {
+ ImportTraceContentProvider input = (ImportTraceContentProvider) newInput;
+ clearCandidates();
+ fTraceTypes.putAll(input.fTraceTypes);
+ fTraceFiles.putAll(fTraceFiles);
+ }
+ }
+
+ @Override
+ public synchronized Object[] getElements(Object inputElement) {
+ List<String> candidates = new ArrayList<>();
+
+ for (String candidate : fTraceTypesToScan) {
+ for (Entry<String, String> entry : fTraceTypes.entrySet()) {
+ if (entry.getValue().equals(candidate)) {
+ candidates.add(entry.getKey());
+ break;
+ }
+ }
+
+ }
+ return candidates.toArray(new String[candidates.size()]);
+ }
+
+ @Override
+ public synchronized Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof String) {
+ final Set<FileAndName> children = fTraceFiles.get(fTraceTypes.get(parentElement));
+ if (children != null) {
+ Set<FileAndName> candidates = new TreeSet<>();
+ for (FileAndName child : children) {
+ for (String parent : fParentFilesToScan) {
+ // this is going to be slow, but less slow than UI
+ // display and should not be done for more than 10k
+ // elements.
+ if (child.getFile().getAbsolutePath().startsWith(parent)) {
+ candidates.add(child);
+ }
+ }
+ }
+ return candidates.toArray(new FileAndName[0]);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the brothers and systems of a file element
+ *
+ * @param element
+ * the child leaf
+ * @return the siblings of an element, including itself. Should never be
+ * null
+ */
+ public synchronized FileAndName[] getSiblings(FileAndName element) {
+ String key = (String) getParent(element);
+ return (FileAndName[]) getChildren(key);
+
+ }
+
+ @Override
+ public synchronized Object getParent(Object element) {
+ if (element instanceof FileAndName) {
+ for (String key : fTraceFiles.keySet()) {
+ Set<FileAndName> fanSet = fTraceFiles.get(key);
+ if (fanSet.contains(element)) {
+ return key;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public synchronized boolean hasChildren(Object element) {
+ if (element instanceof String) {
+ String key = (String) element;
+ return fTraceFiles.containsKey(fTraceTypes.get(key));
+ }
+ return false;
+ }
+
+ /**
+ * Gets the number of traces to import
+ *
+ * @return the number of traces to import
+ */
+ public synchronized int getSize() {
+ int tot = 0;
+ for (String s : fTraceFiles.keySet()) {
+ tot += fTraceFiles.get(s).size();
+ }
+ return tot;
+ }
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceLabelProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceLabelProvider.java
new file mode 100644
index 0000000000..25a34426d9
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceLabelProvider.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+
+import org.eclipse.jface.viewers.LabelProvider;
+
+/**
+ * Trace label provider for the candidate tree
+ *
+ * @author Matthew Khouzam
+ */
+class ImportTraceLabelProvider extends LabelProvider {
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof String) {
+ return (String) element;
+ }
+ if (element instanceof FileAndName) {
+ final File file = ((FileAndName) element).getFile();
+ if (file != null) { // should never not happen since file is final
+ // and always set automatically
+ return file.getName();
+ }
+ }
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizard.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizard.java
new file mode 100644
index 0000000000..654dbb22ac
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizard.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 Ericsson
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * The import trace wizard implementation.
+ * <p>
+ * @author Francois Chouinard
+ */
+public class ImportTraceWizard extends Wizard implements IImportWizard {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final String PLUGIN_ID = Activator.PLUGIN_ID;
+ private static final String IMPORT_WIZARD = "ImportTraceWizard"; //$NON-NLS-1$
+ private static final String ICON_PATH = "icons/wizban/trace_import_wiz.png"; //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ private IStructuredSelection fSelection;
+ private ImportTraceWizardPage fTraceImportWizardPage;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+ /**
+ * Default constructor
+ */
+ public ImportTraceWizard() {
+ IDialogSettings workbenchSettings = Activator.getDefault().getDialogSettings();
+ IDialogSettings section = workbenchSettings.getSection(IMPORT_WIZARD);
+ if (section == null) {
+ section = workbenchSettings.addNewSection(IMPORT_WIZARD);
+ }
+ setDialogSettings(section);
+ }
+
+ // ------------------------------------------------------------------------
+ // Wizard
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ fSelection = selection;
+
+ setWindowTitle(Messages.ImportTraceWizard_DialogTitle);
+ setDefaultPageImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, ICON_PATH));
+ setNeedsProgressMonitor(true);
+ }
+
+ @Override
+ public void addPages() {
+ super.addPages();
+ fTraceImportWizardPage = new ImportTraceWizardPage(fSelection);
+ addPage(fTraceImportWizardPage);
+ }
+
+ @Override
+ public boolean performFinish() {
+ return fTraceImportWizardPage.finish();
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java
new file mode 100644
index 0000000000..7377dec638
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java
@@ -0,0 +1,2365 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 Ericsson and others.
+ *
+ * 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:
+ * Francois Chouinard - Initial API and implementation
+ * Francois Chouinard - Got rid of dependency on internal platform class
+ * Francois Chouinard - Complete re-design
+ * Anna Dushistova(Montavista) - [383047] NPE while importing a CFT trace
+ * Matthew Khouzam - Moved out some common functions
+ * Patrick Tasse - Add sorting of file system elements
+ * Bernd Hufmann - Re-design of trace selection and trace validation
+ * Marc-Andre Laperle - Preserve folder structure on import
+ * Marc-Andre Laperle - Extract archives during import
+ * Marc-Andre Laperle - Add support for Gzip (non-Tar)
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.core.TmfProjectNature;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.ui.dialogs.FileSystemElement;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.dialogs.WizardResourceImportPage;
+import org.eclipse.ui.ide.dialogs.ResourceTreeAndListGroup;
+import org.eclipse.ui.internal.ide.DialogUtil;
+import org.eclipse.ui.internal.ide.dialogs.IElementFilter;
+import org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileManipulations;
+import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider;
+import org.eclipse.ui.internal.wizards.datatransfer.TarEntry;
+import org.eclipse.ui.internal.wizards.datatransfer.TarException;
+import org.eclipse.ui.internal.wizards.datatransfer.TarFile;
+import org.eclipse.ui.internal.wizards.datatransfer.TarLeveledStructureProvider;
+import org.eclipse.ui.internal.wizards.datatransfer.ZipLeveledStructureProvider;
+import org.eclipse.ui.model.AdaptableList;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.model.WorkbenchViewerComparator;
+import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+
+/**
+ * A variant of the standard resource import wizard for importing traces to
+ * given tracing project. If no project or tracing project was selected the
+ * wizard imports it to the default tracing project which is created if
+ * necessary.
+ *
+ * In our case traces could be files or a directory structure. This wizard
+ * supports both cases. It imports traces for a selected trace type or, if no
+ * trace type is selected, it tries to detect the trace type automatically.
+ * However, the automatic detection is a best-effort and cannot guarantee that
+ * the detection is successful. The reason for this is that there might be
+ * multiple trace types that can be assigned to a single trace.
+ *
+ *
+ * @author Francois Chouinard
+ */
+@SuppressWarnings("restriction")
+public class ImportTraceWizardPage extends WizardResourceImportPage {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+ private static final String IMPORT_WIZARD_PAGE_NAME = "ImportTraceWizardPage"; //$NON-NLS-1$
+ private static final String IMPORT_WIZARD_ROOT_DIRECTORY_ID = ".import_root_directory_id"; //$NON-NLS-1$;
+ private static final String IMPORT_WIZARD_ARCHIVE_FILE_NAME_ID = ".import_archive_file_name_id"; //$NON-NLS-1$
+ private static final String IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID = ".import_unrecognized_traces_id"; //$NON-NLS-1$
+ private static final String IMPORT_WIZARD_PRESERVE_FOLDERS_ID = ".import_preserve_folders_id"; //$NON-NLS-1$
+ private static final String IMPORT_WIZARD_IMPORT_FROM_DIRECTORY_ID = ".import_from_directory"; //$NON-NLS-1$
+
+ // constant from WizardArchiveFileResourceImportPage1
+ private static final String[] FILE_IMPORT_MASK = { "*.jar;*.zip;*.tar;*.tar.gz;*.tgz;*.gz", "*.*" }; //$NON-NLS-1$ //$NON-NLS-2$
+ private static final String TRACE_IMPORT_TEMP_FOLDER = ".traceImport"; //$NON-NLS-1$
+
+ /**
+ * A special trace type value to communicate that automatic trace type
+ * detection will occur instead of setting a specific trace type when
+ * importing the traces.
+ */
+ public static final String TRACE_TYPE_AUTO_DETECT = Messages.ImportTraceWizard_AutoDetection;
+
+ /**
+ * Preserve the folder structure of the import traces.
+ */
+ public static final int OPTION_PRESERVE_FOLDER_STRUCTURE = 1 << 1;
+ /**
+ * Create links to the trace files instead of copies.
+ */
+ public static final int OPTION_CREATE_LINKS_IN_WORKSPACE = 1 << 2;
+ /**
+ * Import files that were not recognized as the selected trace type.
+ */
+ public static final int OPTION_IMPORT_UNRECOGNIZED_TRACES = 1 << 3;
+ /**
+ * Overwrite existing resources without prompting.
+ */
+ public static final int OPTION_OVERWRITE_EXISTING_RESOURCES = 1 << 4;
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ // Target import directory ('Traces' folder)
+ private IFolder fTargetFolder;
+ // Target Trace folder element
+ private TmfTraceFolder fTraceFolderElement;
+ // Flag to handle destination folder change event
+ private Boolean fIsDestinationChanged = false;
+ private final Object fSyncObject = new Object();
+ // Combo box containing trace types
+ private Combo fTraceTypes;
+ // Button to ignore unrecognized traces or not
+ private Button fImportUnrecognizedButton;
+ // Button to overwrite existing resources or not
+ private Button fOverwriteExistingResourcesCheckbox;
+ // Button to link or copy traces to workspace
+ private Button fCreateLinksInWorkspaceButton;
+ // Button to preserve folder structure
+ private Button fPreserveFolderStructureButton;
+ private boolean entryChanged = false;
+ // The import from directory radio button
+ private Button fImportFromDirectoryRadio;
+ // The import from archive radio button
+ private Button fImportFromArchiveRadio;
+ // Flag to remember the "create links" checkbox when it gets disabled by
+ // the import from archive radio button
+ private Boolean fPreviousCreateLinksValue = true;
+
+ /** The archive name field */
+ protected Combo fArchiveNameField;
+ /** The archive browse button. */
+ protected Button fArchiveBrowseButton;
+ /** The directory name field */
+ protected Combo directoryNameField;
+ /** The directory browse button. */
+ protected Button directoryBrowseButton;
+
+ private ResourceTreeAndListGroup fSelectionGroup;
+
+ // Keep trace of the selection root so that we can dispose its related
+ // resources
+ private TraceFileSystemElement fSelectionGroupRoot;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor. Creates the trace wizard page.
+ *
+ * @param name
+ * The name of the page.
+ * @param selection
+ * The current selection
+ */
+ protected ImportTraceWizardPage(String name, IStructuredSelection selection) {
+ super(name, selection);
+ setTitle(Messages.ImportTraceWizard_FileSystemTitle);
+ setDescription(Messages.ImportTraceWizard_ImportTrace);
+
+ // Locate the target trace folder
+ IFolder traceFolder = null;
+ Object element = selection.getFirstElement();
+
+ if (element instanceof TmfTraceFolder) {
+ fTraceFolderElement = (TmfTraceFolder) element;
+ traceFolder = fTraceFolderElement.getResource();
+ } else if (element instanceof IProject) {
+ IProject project = (IProject) element;
+ try {
+ if (project.hasNature(TmfProjectNature.ID)) {
+ TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true);
+ fTraceFolderElement = projectElement.getTracesFolder();
+ traceFolder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME);
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ // If no tracing project was selected or trace folder doesn't exist use
+ // default tracing project
+ if (traceFolder == null) {
+ IProject project = TmfProjectRegistry.createProject(
+ TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME, null, new NullProgressMonitor());
+ TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true);
+ fTraceFolderElement = projectElement.getTracesFolder();
+ traceFolder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME);
+ }
+
+ // Set the target trace folder
+ if (traceFolder != null) {
+ fTargetFolder = traceFolder;
+ String path = traceFolder.getFullPath().toString();
+ setContainerFieldValue(path);
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param selection
+ * The current selection
+ */
+ public ImportTraceWizardPage(IStructuredSelection selection) {
+ this(IMPORT_WIZARD_PAGE_NAME, selection);
+ }
+
+ /**
+ * Create the import source selection widget. (Copied from
+ * WizardResourceImportPage but instead always uses the internal
+ * ResourceTreeAndListGroup to keep compatibility with Kepler)
+ */
+ @Override
+ protected void createFileSelectionGroup(Composite parent) {
+
+ // Just create with a dummy root.
+ fSelectionGroup = new ResourceTreeAndListGroup(parent,
+ new FileSystemElement("Dummy", null, true),//$NON-NLS-1$
+ getFolderProvider(), new WorkbenchLabelProvider(),
+ getFileProvider(), new WorkbenchLabelProvider(), SWT.NONE,
+ DialogUtil.inRegularFontMode(parent));
+
+ ICheckStateListener listener = new ICheckStateListener() {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ updateWidgetEnablements();
+ }
+ };
+
+ WorkbenchViewerComparator comparator = new WorkbenchViewerComparator();
+ fSelectionGroup.setTreeComparator(comparator);
+ fSelectionGroup.setListComparator(comparator);
+ fSelectionGroup.addCheckStateListener(listener);
+
+ }
+
+ // ------------------------------------------------------------------------
+ // WizardResourceImportPage
+ // ------------------------------------------------------------------------
+
+ @Override
+ protected void createSourceGroup(Composite parent) {
+ createSourceSelectionGroup(parent);
+ createFileSelectionGroup(parent);
+ createTraceTypeGroup(parent);
+ validateSourceGroup();
+ }
+
+ @Override
+ protected ITreeContentProvider getFileProvider() {
+ return new WorkbenchContentProvider() {
+ @Override
+ public Object[] getChildren(Object object) {
+ if (object instanceof TraceFileSystemElement) {
+ TraceFileSystemElement element = (TraceFileSystemElement) object;
+ return element.getFiles().getChildren(element);
+ }
+ return new Object[0];
+ }
+ };
+ }
+
+ @Override
+ protected ITreeContentProvider getFolderProvider() {
+ return new WorkbenchContentProvider() {
+ @Override
+ public Object[] getChildren(Object o) {
+ if (o instanceof TraceFileSystemElement) {
+ TraceFileSystemElement element = (TraceFileSystemElement) o;
+ return element.getFolders().getChildren();
+ }
+ return new Object[0];
+ }
+
+ @Override
+ public boolean hasChildren(Object o) {
+ if (o instanceof TraceFileSystemElement) {
+ TraceFileSystemElement element = (TraceFileSystemElement) o;
+ if (element.isPopulated()) {
+ return getChildren(element).length > 0;
+ }
+ // If we have not populated then wait until asked
+ return true;
+ }
+ return false;
+ }
+ };
+ }
+
+ // ------------------------------------------------------------------------
+ // Directory Selection Group (forked WizardFileSystemResourceImportPage1)
+ // ------------------------------------------------------------------------
+
+ /**
+ * creates the source selection group.
+ *
+ * @param parent
+ * the parent composite
+ */
+ protected void createSourceSelectionGroup(Composite parent) {
+
+ Composite sourceGroup = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.makeColumnsEqualWidth = false;
+ layout.marginWidth = 0;
+ sourceGroup.setLayout(layout);
+ sourceGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // import from directory radio button
+ fImportFromDirectoryRadio = new Button(sourceGroup, SWT.RADIO);
+ fImportFromDirectoryRadio
+ .setText(Messages.ImportTraceWizard_DirectoryLocation);
+
+ // import location entry combo
+ directoryNameField = createPathSelectionCombo(sourceGroup);
+ createDirectoryBrowseButton(sourceGroup);
+
+ // import from archive radio button
+ fImportFromArchiveRadio = new Button(sourceGroup, SWT.RADIO);
+ fImportFromArchiveRadio
+ .setText(Messages.ImportTraceWizard_ArchiveLocation);
+
+ // import location entry combo
+ fArchiveNameField = createPathSelectionCombo(sourceGroup);
+ createArchiveBrowseButton(sourceGroup);
+
+ fImportFromDirectoryRadio.setSelection(true);
+ fArchiveNameField.setEnabled(false);
+ fArchiveBrowseButton.setEnabled(false);
+
+ fImportFromDirectoryRadio.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ directoryRadioSelected();
+ }
+ });
+
+ fImportFromArchiveRadio.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ archiveRadioSelected();
+ }
+ });
+ }
+
+ /**
+ * Select or deselect all files in the file selection group
+ *
+ * @param checked
+ * whether or not the files should be checked
+ */
+ protected void setFileSelectionGroupChecked(boolean checked) {
+ if (fSelectionGroup != null) {
+ fSelectionGroup.setAllSelections(checked);
+ }
+ }
+
+ /**
+ * Create a combo that will be used to select a path to specify the source
+ * of the import. The parent is assumed to have a GridLayout.
+ *
+ * @param parent
+ * the parent composite
+ * @return the created path selection combo
+ */
+ protected Combo createPathSelectionCombo(Composite parent) {
+ Combo pathSelectionCombo = new Combo(parent, SWT.BORDER);
+
+ GridData layoutData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
+ layoutData.widthHint = new PixelConverter(pathSelectionCombo).convertWidthInCharsToPixels(25);
+ pathSelectionCombo.setLayoutData(layoutData);
+
+ TraverseListener traverseListener = new TraverseListener() {
+ @Override
+ public void keyTraversed(TraverseEvent e) {
+ if (e.detail == SWT.TRAVERSE_RETURN) {
+ e.doit = false;
+ entryChanged = false;
+ updateFromSourceField();
+ }
+ }
+ };
+
+ FocusAdapter focusAdapter = new FocusAdapter() {
+ @Override
+ public void focusLost(FocusEvent e) {
+ // Clear the flag to prevent constant update
+ if (entryChanged) {
+ entryChanged = false;
+ updateFromSourceField();
+ }
+ }
+ };
+
+ SelectionAdapter selectionAdapter = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ entryChanged = false;
+ updateFromSourceField();
+ }
+ };
+
+ ModifyListener modifyListner = new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ entryChanged = true;
+ }
+ };
+
+ pathSelectionCombo.addModifyListener(modifyListner);
+ pathSelectionCombo.addTraverseListener(traverseListener);
+ pathSelectionCombo.addFocusListener(focusAdapter);
+ pathSelectionCombo.addSelectionListener(selectionAdapter);
+
+ return pathSelectionCombo;
+ }
+
+ /**
+ * Create the directory browse button.
+ *
+ * @param parent
+ * the parent composite
+ */
+ protected void createDirectoryBrowseButton(Composite parent) {
+ directoryBrowseButton = createPathSelectionBrowseButton(parent);
+ directoryBrowseButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ handleSourceDirectoryBrowseButtonPressed();
+ }
+ });
+ }
+
+ /**
+ * Create the archive browse button.
+ *
+ * @param parent
+ * the parent composite
+ */
+ protected void createArchiveBrowseButton(Composite parent) {
+ fArchiveBrowseButton = createPathSelectionBrowseButton(parent);
+ fArchiveBrowseButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ handleArchiveBrowseButtonPressed(FILE_IMPORT_MASK);
+ }
+ });
+ }
+
+ /**
+ * Create a browse button that will be used to browse for a path to specify
+ * the source of the import. The parent is assumed to have a GridLayout.
+ *
+ * @param parent
+ * the parent composite
+ * @return the created path selection combo
+ */
+ protected Button createPathSelectionBrowseButton(Composite parent) {
+ Button pathSelectionBrowseButton = new Button(parent, SWT.PUSH);
+ pathSelectionBrowseButton.setText(Messages.ImportTraceWizard_BrowseButton);
+ setButtonLayoutData(pathSelectionBrowseButton);
+
+ return pathSelectionBrowseButton;
+ }
+
+ private void archiveRadioSelected() {
+ if (!isImportFromDirectory()) {
+ directoryNameField.setEnabled(false);
+ directoryBrowseButton.setEnabled(false);
+ fArchiveNameField.setEnabled(true);
+ fArchiveBrowseButton.setEnabled(true);
+ updateFromSourceField();
+ fArchiveNameField.setFocus();
+ if (fCreateLinksInWorkspaceButton != null) {
+ fPreviousCreateLinksValue = fCreateLinksInWorkspaceButton.getSelection();
+ fCreateLinksInWorkspaceButton.setSelection(false);
+ fCreateLinksInWorkspaceButton.setEnabled(false);
+ }
+ }
+ }
+
+ private void directoryRadioSelected() {
+ if (isImportFromDirectory()) {
+ directoryNameField.setEnabled(true);
+ directoryBrowseButton.setEnabled(true);
+ fArchiveNameField.setEnabled(false);
+ fArchiveBrowseButton.setEnabled(false);
+ updateFromSourceField();
+ directoryNameField.setFocus();
+ if (fCreateLinksInWorkspaceButton != null) {
+ fCreateLinksInWorkspaceButton.setSelection(fPreviousCreateLinksValue);
+ fCreateLinksInWorkspaceButton.setEnabled(true);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Browse for the source directory
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void handleEvent(Event event) {
+ if (event.widget == directoryBrowseButton) {
+ handleSourceDirectoryBrowseButtonPressed();
+ }
+
+ // Avoid overwriting destination path without repeatedly trigger
+ // call of handleEvent();
+ synchronized (fSyncObject) {
+ if (fIsDestinationChanged == false) {
+ event.display.asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (fSyncObject) {
+ fIsDestinationChanged = true;
+ String path = fTargetFolder.getFullPath().toString();
+ setContainerFieldValue(path);
+ }
+ }
+ });
+ } else {
+ fIsDestinationChanged = false;
+ }
+ }
+ super.handleEvent(event);
+ }
+
+ @Override
+ protected void handleContainerBrowseButtonPressed() {
+ // Do nothing so that destination directory cannot be changed.
+ }
+
+ /**
+ * Handle the button pressed event
+ */
+ protected void handleSourceDirectoryBrowseButtonPressed() {
+ String currentSource = directoryNameField.getText();
+ DirectoryDialog dialog = new DirectoryDialog(directoryNameField.getShell(), SWT.SAVE | SWT.SHEET);
+ dialog.setText(Messages.ImportTraceWizard_SelectTraceDirectoryTitle);
+ dialog.setMessage(Messages.ImportTraceWizard_SelectTraceDirectoryMessage);
+ dialog.setFilterPath(getSourceDirectoryName(currentSource));
+
+ String selectedDirectory = dialog.open();
+ if (selectedDirectory != null) {
+ // Just quit if the directory is not valid
+ if ((getSourceDirectory(selectedDirectory) == null) || selectedDirectory.equals(currentSource)) {
+ return;
+ }
+ // If it is valid then proceed to populate
+ setErrorMessage(null);
+ setSourcePath(selectedDirectory);
+ }
+ }
+
+ /**
+ * Handle the button pressed event
+ *
+ * @param extensions
+ * file extensions used to filter files shown to the user
+ */
+ protected void handleArchiveBrowseButtonPressed(String[] extensions) {
+ FileDialog dialog = new FileDialog(fArchiveNameField.getShell(), SWT.SHEET);
+ dialog.setFilterExtensions(extensions);
+ dialog.setText(Messages.ImportTraceWizard_SelectTraceArchiveTitle);
+ String fileName = fArchiveNameField.getText().trim();
+ if (!fileName.isEmpty()) {
+ File path = new File(fileName).getParentFile();
+ if (path != null && path.exists()) {
+ dialog.setFilterPath(path.toString());
+ }
+ }
+
+ String selectedArchive = dialog.open();
+ if (selectedArchive != null) {
+ setErrorMessage(null);
+ setSourcePath(selectedArchive);
+ updateWidgetEnablements();
+ }
+ }
+
+ private File getSourceDirectory() {
+ if (directoryNameField == null) {
+ return null;
+ }
+ return getSourceDirectory(directoryNameField.getText());
+ }
+
+ private File getSourceArchiveFile() {
+ if (fArchiveNameField == null) {
+ return null;
+ }
+
+ return getSourceArchiveFile(fArchiveNameField.getText());
+ }
+
+ private String getSourceContainerPath() {
+ if (isImportFromDirectory()) {
+ File sourceDirectory = getSourceDirectory();
+ if (sourceDirectory != null) {
+ return sourceDirectory.getAbsolutePath();
+ }
+ }
+ File sourceArchiveFile = getSourceArchiveFile();
+ if (sourceArchiveFile != null) {
+ return sourceArchiveFile.getParent();
+ }
+ return null;
+ }
+
+ private static File getSourceDirectory(String path) {
+ File sourceDirectory = new File(getSourceDirectoryName(path));
+ if (!sourceDirectory.exists() || !sourceDirectory.isDirectory()) {
+ return null;
+ }
+
+ return sourceDirectory;
+ }
+
+ private static File getSourceArchiveFile(String path) {
+ File sourceArchiveFile = new File(path);
+ if (!sourceArchiveFile.exists() || sourceArchiveFile.isDirectory()) {
+ return null;
+ }
+
+ return sourceArchiveFile;
+ }
+
+ private static String getSourceDirectoryName(String sourceName) {
+ IPath result = new Path(sourceName.trim());
+ if (result.getDevice() != null && result.segmentCount() == 0) {
+ result = result.addTrailingSeparator();
+ } else {
+ result = result.removeTrailingSeparator();
+ }
+ return result.toOSString();
+ }
+
+ private void updateFromSourceField() {
+ setSourcePath(getSourceField().getText());
+ updateWidgetEnablements();
+ }
+
+ private Combo getSourceField() {
+ if (directoryNameField == null) {
+ return fArchiveNameField;
+ }
+
+ return directoryNameField.isEnabled() ? directoryNameField : fArchiveNameField;
+ }
+
+ /**
+ * Set the source path that was selected by the user by various input
+ * methods (Browse button, typing, etc).
+ *
+ * Clients can also call this to set the path programmatically (hard-coded
+ * initial path) and this can also be overridden to be notified when the
+ * source path changes.
+ *
+ * @param path
+ * the source path
+ */
+ protected void setSourcePath(String path) {
+ Combo sourceField = getSourceField();
+ if (sourceField == null) {
+ return;
+ }
+
+ if (path.length() > 0) {
+ String[] currentItems = sourceField.getItems();
+ int selectionIndex = -1;
+ for (int i = 0; i < currentItems.length; i++) {
+ if (currentItems[i].equals(path)) {
+ selectionIndex = i;
+ }
+ }
+ if (selectionIndex < 0) {
+ int oldLength = currentItems.length;
+ String[] newItems = new String[oldLength + 1];
+ System.arraycopy(currentItems, 0, newItems, 0, oldLength);
+ newItems[oldLength] = path;
+ sourceField.setItems(newItems);
+ selectionIndex = oldLength;
+ }
+ sourceField.select(selectionIndex);
+ }
+ resetSelection();
+ }
+
+ // ------------------------------------------------------------------------
+ // File Selection Group (forked WizardFileSystemResourceImportPage1)
+ // ------------------------------------------------------------------------
+ private void resetSelection() {
+ if (fSelectionGroupRoot != null) {
+ disposeSelectionGroupRoot();
+ }
+ fSelectionGroupRoot = getFileSystemTree();
+ fSelectionGroup.setRoot(fSelectionGroupRoot);
+ }
+
+ private void disposeSelectionGroupRoot() {
+ if (fSelectionGroupRoot != null && fSelectionGroupRoot.getProvider() != null) {
+ FileSystemObjectImportStructureProvider provider = fSelectionGroupRoot.getProvider();
+ provider.dispose();
+ fSelectionGroupRoot = null;
+ }
+ }
+
+ private TraceFileSystemElement getFileSystemTree() {
+ Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> rootObjectAndProvider = getRootObjectAndProvider(getSourceFile());
+ if (rootObjectAndProvider == null) {
+ return null;
+ }
+ return selectFiles(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond());
+ }
+
+ @SuppressWarnings("resource")
+ private Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> getRootObjectAndProvider(File sourceFile) {
+ if (sourceFile == null) {
+ return null;
+ }
+
+ IFileSystemObject rootElement = null;
+ FileSystemObjectImportStructureProvider importStructureProvider = null;
+
+ // Import from directory
+ if (!isArchiveFile(sourceFile)) {
+ importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
+ rootElement = importStructureProvider.getIFileSystemObject(sourceFile);
+ } else {
+ // Import from archive
+ FileSystemObjectLeveledImportStructureProvider leveledImportStructureProvider = null;
+ String archivePath = sourceFile.getAbsolutePath();
+ if (isTarFile(archivePath)) {
+ if (ensureTarSourceIsValid(archivePath)) {
+ // We close the file when we dispose the import provider,
+ // see disposeSelectionGroupRoot
+ TarFile tarFile = getSpecifiedTarSourceFile(archivePath);
+ leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new TarLeveledStructureProvider(tarFile), archivePath);
+ }
+ } else if (ensureZipSourceIsValid(archivePath)) {
+ // We close the file when we dispose the import provider, see
+ // disposeSelectionGroupRoot
+ ZipFile zipFile = getSpecifiedZipSourceFile(archivePath);
+ leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new ZipLeveledStructureProvider(zipFile), archivePath);
+ } else if (ensureGzipSourceIsValid(archivePath)) {
+ // We close the file when we dispose the import provider, see
+ // disposeSelectionGroupRoot
+ GzipFile zipFile = null;
+ try {
+ zipFile = new GzipFile(archivePath);
+ leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new GzipLeveledStructureProvider(zipFile), archivePath);
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (leveledImportStructureProvider == null) {
+ return null;
+ }
+ rootElement = leveledImportStructureProvider.getRoot();
+ importStructureProvider = leveledImportStructureProvider;
+ }
+
+ if (rootElement == null) {
+ return null;
+ }
+
+ return new Pair<>(rootElement, importStructureProvider);
+ }
+
+ /**
+ * An import provider that makes use of the IFileSystemObject abstraction
+ * instead of using plain file system objects (File, TarEntry, ZipEntry, etc)
+ */
+ private static class FileSystemObjectImportStructureProvider implements IImportStructureProvider {
+
+ private IImportStructureProvider fImportProvider;
+ private String fArchivePath;
+
+ private FileSystemObjectImportStructureProvider(IImportStructureProvider importStructureProvider, String archivePath) {
+ fImportProvider = importStructureProvider;
+ fArchivePath = archivePath;
+ }
+
+ @Override
+ public List<IFileSystemObject> getChildren(Object element) {
+ @SuppressWarnings("rawtypes")
+ List children = fImportProvider.getChildren(((IFileSystemObject) element).getRawFileSystemObject());
+ List<IFileSystemObject> adapted = new ArrayList<>(children.size());
+ for (Object o : children) {
+ adapted.add(getIFileSystemObject(o));
+ }
+ return adapted;
+ }
+
+ public IFileSystemObject getIFileSystemObject(Object o) {
+ if (o == null) {
+ return null;
+ }
+
+ if (o instanceof File) {
+ return new FileFileSystemObject((File) o);
+ } else if (o instanceof TarEntry) {
+ return new TarFileSystemObject((TarEntry) o, fArchivePath);
+ } else if (o instanceof ZipEntry) {
+ return new ZipFileSystemObject((ZipEntry) o, fArchivePath);
+ } else if (o instanceof GzipEntry) {
+ return new GzipFileSystemObject((GzipEntry) o, fArchivePath);
+ }
+
+ throw new IllegalArgumentException("Object type not handled"); //$NON-NLS-1$
+ }
+
+ @Override
+ public InputStream getContents(Object element) {
+ return fImportProvider.getContents(((IFileSystemObject) element).getRawFileSystemObject());
+ }
+
+ @Override
+ public String getFullPath(Object element) {
+ return fImportProvider.getFullPath(((IFileSystemObject) element).getRawFileSystemObject());
+ }
+
+ @Override
+ public String getLabel(Object element) {
+ return fImportProvider.getLabel(((IFileSystemObject) element).getRawFileSystemObject());
+ }
+
+ @Override
+ public boolean isFolder(Object element) {
+ return fImportProvider.isFolder(((IFileSystemObject) element).getRawFileSystemObject());
+ }
+
+ /**
+ * Disposes of the resources associated with the provider.
+ */
+ public void dispose() {
+ }
+ }
+
+ /**
+ * An import provider that both supports using IFileSystemObject and adds
+ * "archive functionality" by delegating to a leveled import provider
+ * (TarLeveledStructureProvider, ZipLeveledStructureProvider)
+ */
+ private static class FileSystemObjectLeveledImportStructureProvider extends FileSystemObjectImportStructureProvider implements ILeveledImportStructureProvider {
+
+ private ILeveledImportStructureProvider fLeveledImportProvider;
+
+ private FileSystemObjectLeveledImportStructureProvider(ILeveledImportStructureProvider importStructureProvider, String archivePath) {
+ super(importStructureProvider, archivePath);
+ fLeveledImportProvider = importStructureProvider;
+ }
+
+ @Override
+ public IFileSystemObject getRoot() {
+ return getIFileSystemObject(fLeveledImportProvider.getRoot());
+ }
+
+ @Override
+ public void setStrip(int level) {
+ fLeveledImportProvider.setStrip(level);
+ }
+
+ @Override
+ public int getStrip() {
+ return fLeveledImportProvider.getStrip();
+ }
+
+ @Override
+ public boolean closeArchive() {
+ return fLeveledImportProvider.closeArchive();
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ closeArchive();
+ }
+ }
+
+ @SuppressWarnings("resource")
+ private boolean ensureZipSourceIsValid(String archivePath) {
+ ZipFile specifiedFile = getSpecifiedZipSourceFile(archivePath);
+ if (specifiedFile == null) {
+ return false;
+ }
+ return ArchiveFileManipulations.closeZipFile(specifiedFile, getShell());
+ }
+
+ private boolean ensureTarSourceIsValid(String archivePath) {
+ TarFile specifiedFile = getSpecifiedTarSourceFile(archivePath);
+ if (specifiedFile == null) {
+ return false;
+ }
+ return ArchiveFileManipulations.closeTarFile(specifiedFile, getShell());
+ }
+
+ private static ZipFile getSpecifiedZipSourceFile(String fileName) {
+ if (fileName.length() == 0) {
+ return null;
+ }
+
+ try {
+ return new ZipFile(fileName);
+ } catch (ZipException e) {
+ // ignore
+ } catch (IOException e) {
+ // ignore
+ }
+
+ return null;
+ }
+
+ private static boolean isTarFile(String fileName) {
+ TarFile specifiedTarSourceFile = getSpecifiedTarSourceFile(fileName);
+ if (specifiedTarSourceFile != null) {
+ try {
+ specifiedTarSourceFile.close();
+ return true;
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ return false;
+ }
+
+ private static TarFile getSpecifiedTarSourceFile(String fileName) {
+ if (fileName.length() == 0) {
+ return null;
+ }
+
+ // FIXME: Work around Bug 463633. Remove this block once we move to Eclipse 4.5.
+ if (new File(fileName).length() < 512) {
+ return null;
+ }
+
+ try {
+ return new TarFile(fileName);
+ } catch (TarException | IOException e) {
+ // ignore
+ }
+
+ return null;
+ }
+
+ private static boolean ensureGzipSourceIsValid(String archivePath) {
+ return isGzipFile(archivePath);
+ }
+
+ private TraceFileSystemElement selectFiles(final IFileSystemObject rootFileSystemObject,
+ final FileSystemObjectImportStructureProvider structureProvider) {
+ final TraceFileSystemElement[] results = new TraceFileSystemElement[1];
+ BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
+ @Override
+ public void run() {
+ // Create the root element from the supplied file system object
+ results[0] = createRootTraceFileElement(rootFileSystemObject, structureProvider);
+ }
+ });
+ return results[0];
+ }
+
+ private static TraceFileSystemElement createRootTraceFileElement(IFileSystemObject element,
+ FileSystemObjectImportStructureProvider provider) {
+ boolean isContainer = provider.isFolder(element);
+ String elementLabel = provider.getLabel(element);
+
+ // Use an empty label so that display of the element's full name
+ // doesn't include a confusing label
+ TraceFileSystemElement dummyParent = new TraceFileSystemElement("", null, true, provider);//$NON-NLS-1$
+ Object dummyParentFileSystemObject = element;
+ Object rawFileSystemObject = element.getRawFileSystemObject();
+ if (rawFileSystemObject instanceof File) {
+ dummyParentFileSystemObject = provider.getIFileSystemObject(((File) rawFileSystemObject).getParentFile());
+ }
+ dummyParent.setFileSystemObject(dummyParentFileSystemObject);
+ dummyParent.setPopulated();
+ TraceFileSystemElement result = new TraceFileSystemElement(
+ elementLabel, dummyParent, isContainer, provider);
+ result.setFileSystemObject(element);
+
+ // Get the files for the element so as to build the first level
+ result.getFiles();
+
+ return dummyParent;
+ }
+
+ // ------------------------------------------------------------------------
+ // Trace Type Group
+ // ------------------------------------------------------------------------
+ private final void createTraceTypeGroup(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.makeColumnsEqualWidth = false;
+ composite.setLayout(layout);
+ composite.setFont(parent.getFont());
+ GridData buttonData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ composite.setLayoutData(buttonData);
+
+ // Trace type label ("Trace Type:")
+ Label typeLabel = new Label(composite, SWT.NONE);
+ typeLabel.setText(Messages.ImportTraceWizard_TraceType);
+ typeLabel.setFont(parent.getFont());
+
+ // Trace type combo
+ fTraceTypes = new Combo(composite, SWT.BORDER | SWT.READ_ONLY);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+ fTraceTypes.setLayoutData(data);
+ fTraceTypes.setFont(parent.getFont());
+
+ String[] availableTraceTypes = TmfTraceType.getAvailableTraceTypes();
+ String[] traceTypeList = new String[availableTraceTypes.length + 1];
+ traceTypeList[0] = TRACE_TYPE_AUTO_DETECT;
+ for (int i = 0; i < availableTraceTypes.length; i++) {
+ traceTypeList[i + 1] = availableTraceTypes[i];
+ }
+ fTraceTypes.setItems(traceTypeList);
+ fTraceTypes.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWidgetEnablements();
+ boolean enabled = fTraceTypes.getText().equals(TRACE_TYPE_AUTO_DETECT);
+ fImportUnrecognizedButton.setEnabled(enabled);
+ }
+ });
+ fTraceTypes.select(0);
+
+ // Unrecognized checkbox
+ fImportUnrecognizedButton = new Button(composite, SWT.CHECK);
+ fImportUnrecognizedButton.setSelection(true);
+ fImportUnrecognizedButton.setText(Messages.ImportTraceWizard_ImportUnrecognized);
+ }
+
+ // ------------------------------------------------------------------------
+ // Options
+ // ------------------------------------------------------------------------
+
+ @Override
+ protected void createOptionsGroupButtons(Group optionsGroup) {
+
+ // Overwrite checkbox
+ fOverwriteExistingResourcesCheckbox = new Button(optionsGroup, SWT.CHECK);
+ fOverwriteExistingResourcesCheckbox.setFont(optionsGroup.getFont());
+ fOverwriteExistingResourcesCheckbox.setText(Messages.ImportTraceWizard_OverwriteExistingTrace);
+ fOverwriteExistingResourcesCheckbox.setSelection(false);
+
+ // Create links checkbox
+ fCreateLinksInWorkspaceButton = new Button(optionsGroup, SWT.CHECK);
+ fCreateLinksInWorkspaceButton.setFont(optionsGroup.getFont());
+ fCreateLinksInWorkspaceButton.setText(Messages.ImportTraceWizard_CreateLinksInWorkspace);
+ fCreateLinksInWorkspaceButton.setSelection(true);
+
+ fCreateLinksInWorkspaceButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWidgetEnablements();
+ }
+ });
+
+ fPreserveFolderStructureButton = new Button(optionsGroup, SWT.CHECK);
+ fPreserveFolderStructureButton.setFont(optionsGroup.getFont());
+ fPreserveFolderStructureButton.setText(Messages.ImportTraceWizard_PreserveFolderStructure);
+ fPreserveFolderStructureButton.setSelection(true);
+
+ updateWidgetEnablements();
+ }
+
+ // ------------------------------------------------------------------------
+ // Determine if the finish button can be enabled
+ // ------------------------------------------------------------------------
+ @Override
+ public boolean validateSourceGroup() {
+
+ File source = getSourceFile();
+ if (source == null) {
+ setMessage(Messages.ImportTraceWizard_SelectTraceSourceEmpty);
+ setErrorMessage(null);
+ return false;
+ }
+
+ if (sourceConflictsWithDestination(new Path(source.getPath()))) {
+ setMessage(null);
+ setErrorMessage(getSourceConflictMessage());
+ return false;
+ }
+
+ if (!isImportFromDirectory() && !ensureTarSourceIsValid(source.getAbsolutePath()) && !ensureZipSourceIsValid(source.getAbsolutePath()) && !ensureGzipSourceIsValid(source.getAbsolutePath())) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_BadArchiveFormat);
+ return false;
+ }
+
+ if (fSelectionGroup.getCheckedElementCount() == 0) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_SelectTraceNoneSelected);
+ return false;
+ }
+
+ IContainer container = getSpecifiedContainer();
+ if (container != null && container.isVirtual()) {
+ if (Platform.getPreferencesService().getBoolean(Activator.PLUGIN_ID, ResourcesPlugin.PREF_DISABLE_LINKING, false, null)) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_CannotImportFilesUnderAVirtualFolder);
+ return false;
+ }
+ if (fCreateLinksInWorkspaceButton == null || !fCreateLinksInWorkspaceButton.getSelection()) {
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_HaveToCreateLinksUnderAVirtualFolder);
+ return false;
+ }
+ }
+
+ setErrorMessage(null);
+ return true;
+ }
+
+ private File getSourceFile() {
+ return isImportFromDirectory() ? getSourceDirectory() : getSourceArchiveFile();
+ }
+
+ private boolean isImportFromDirectory() {
+ return fImportFromDirectoryRadio != null && fImportFromDirectoryRadio.getSelection();
+ }
+
+ private static boolean isArchiveFile(File sourceFile) {
+ String absolutePath = sourceFile.getAbsolutePath();
+ return isTarFile(absolutePath) || ArchiveFileManipulations.isZipFile(absolutePath) || isGzipFile(absolutePath);
+ }
+
+ private static boolean isGzipFile(String fileName) {
+ if (!fileName.isEmpty()) {
+ try (GzipFile specifiedTarSourceFile = new GzipFile(fileName);) {
+ return true;
+ } catch (IOException e) {
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void restoreWidgetValues() {
+ super.restoreWidgetValues();
+
+ IDialogSettings settings = getDialogSettings();
+ boolean value;
+ if (fImportUnrecognizedButton != null) {
+ if (settings.get(getPageStoreKey(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID)) == null) {
+ value = true;
+ } else {
+ value = settings.getBoolean(getPageStoreKey(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID));
+ }
+ fImportUnrecognizedButton.setSelection(value);
+ }
+
+ if (fPreserveFolderStructureButton != null) {
+ if (settings.get(getPageStoreKey(IMPORT_WIZARD_PRESERVE_FOLDERS_ID)) == null) {
+ value = true;
+ } else {
+ value = settings.getBoolean(getPageStoreKey(IMPORT_WIZARD_PRESERVE_FOLDERS_ID));
+ }
+ fPreserveFolderStructureButton.setSelection(value);
+ }
+
+ if (settings.get(getPageStoreKey(IMPORT_WIZARD_IMPORT_FROM_DIRECTORY_ID)) == null) {
+ value = true;
+ } else {
+ value = settings.getBoolean(getPageStoreKey(IMPORT_WIZARD_IMPORT_FROM_DIRECTORY_ID));
+ }
+
+ if (directoryNameField != null) {
+ restoreComboValues(directoryNameField, settings, getPageStoreKey(IMPORT_WIZARD_ROOT_DIRECTORY_ID));
+ }
+ if (fArchiveNameField != null) {
+ restoreComboValues(fArchiveNameField, settings, getPageStoreKey(IMPORT_WIZARD_ARCHIVE_FILE_NAME_ID));
+ }
+
+ if (fImportFromDirectoryRadio != null) {
+ fImportFromDirectoryRadio.setSelection(value);
+ if (value) {
+ directoryRadioSelected();
+ }
+ }
+ if (fImportFromArchiveRadio != null) {
+ fImportFromArchiveRadio.setSelection(!value);
+ if (!value) {
+ archiveRadioSelected();
+ }
+ }
+ }
+
+ @Override
+ protected void saveWidgetValues() {
+ // Persist dialog settings
+ IDialogSettings settings = getDialogSettings();
+ if (fImportUnrecognizedButton != null) {
+ settings.put(getPageStoreKey(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID), fImportUnrecognizedButton.getSelection());
+ }
+ if (fPreserveFolderStructureButton != null) {
+ settings.put(getPageStoreKey(IMPORT_WIZARD_PRESERVE_FOLDERS_ID), fPreserveFolderStructureButton.getSelection());
+ }
+ settings.put(getPageStoreKey(IMPORT_WIZARD_IMPORT_FROM_DIRECTORY_ID), isImportFromDirectory());
+
+ if (directoryNameField != null) {
+ saveComboValues(directoryNameField, settings, getPageStoreKey(IMPORT_WIZARD_ROOT_DIRECTORY_ID));
+ }
+ if (fArchiveNameField != null) {
+ saveComboValues(fArchiveNameField, settings, getPageStoreKey(IMPORT_WIZARD_ARCHIVE_FILE_NAME_ID));
+ }
+ }
+
+ private String getPageStoreKey(String key) {
+ return getName() + key;
+ }
+
+ private static void restoreComboValues(Combo combo, IDialogSettings settings, String key) {
+ String[] directoryNames = settings.getArray(key);
+ if ((directoryNames != null) && (directoryNames.length != 0)) {
+ for (int i = 0; i < directoryNames.length; i++) {
+ combo.add(directoryNames[i]);
+ }
+ }
+ }
+
+ private void saveComboValues(Combo combo, IDialogSettings settings, String key) {
+ // update names history
+ String[] directoryNames = settings.getArray(key);
+ if (directoryNames == null) {
+ directoryNames = new String[0];
+ }
+
+ String items[] = combo.getItems();
+ for (int i = 0; i < items.length; i++) {
+ directoryNames = addToHistory(directoryNames, items[i]);
+ }
+ settings.put(key, directoryNames);
+ }
+
+ // ------------------------------------------------------------------------
+ // Import the trace(s)
+ // ------------------------------------------------------------------------
+
+ /**
+ * Finish the import.
+ *
+ * @return <code>true</code> if successful else <code>false</code>
+ */
+ public boolean finish() {
+ String traceTypeLabel = getImportTraceTypeId();
+ String traceId = null;
+ if (!TRACE_TYPE_AUTO_DETECT.equals(traceTypeLabel)) {
+ traceId = TmfTraceType.getTraceTypeId(traceTypeLabel);
+ }
+
+ // Save dialog settings
+ saveWidgetValues();
+
+ IPath baseSourceContainerPath = new Path(getSourceContainerPath());
+ boolean importFromArchive = getSourceArchiveFile() != null;
+ int importOptionFlags = getImportOptionFlags();
+
+ final TraceValidateAndImportOperation operation = new TraceValidateAndImportOperation(traceId, baseSourceContainerPath, getContainerFullPath(), importFromArchive,
+ importOptionFlags);
+
+ IStatus status = Status.OK_STATUS;
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ operation.run(monitor);
+ monitor.done();
+ }
+ });
+
+ status = operation.getStatus();
+ } catch (InvocationTargetException e) {
+ status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportTraceWizard_ImportProblem, e);
+ } catch (InterruptedException e) {
+ status = Status.CANCEL_STATUS;
+ }
+ if (!status.isOK()) {
+ if (status.getSeverity() == IStatus.CANCEL) {
+ setMessage(Messages.ImportTraceWizard_ImportOperationCancelled);
+ setErrorMessage(null);
+ } else {
+ if (status.getException() != null) {
+ displayErrorDialog(status.getMessage() + ": " + status.getException()); //$NON-NLS-1$
+ }
+ setMessage(null);
+ setErrorMessage(Messages.ImportTraceWizard_ImportProblem);
+ }
+ return false;
+ }
+ setErrorMessage(null);
+ return true;
+ }
+
+ /**
+ * Get the trace type id to import as. This can also return
+ * {@link #TRACE_TYPE_AUTO_DETECT} to communicate that automatic trace type
+ * detection will occur instead of setting a specific trace type when
+ * importing the traces.
+ *
+ * @return the trace type id or {@link #TRACE_TYPE_AUTO_DETECT}
+ */
+ protected String getImportTraceTypeId() {
+ return fTraceTypes.getText();
+ }
+
+ /**
+ * Get import options in the form of flags (bits).
+ *
+ * @return the import flags.
+ * @see #OPTION_CREATE_LINKS_IN_WORKSPACE
+ * @see #OPTION_IMPORT_UNRECOGNIZED_TRACES
+ * @see #OPTION_OVERWRITE_EXISTING_RESOURCES
+ * @see #OPTION_PRESERVE_FOLDER_STRUCTURE
+ */
+ protected int getImportOptionFlags() {
+ int flags = 0;
+ if (fCreateLinksInWorkspaceButton != null && fCreateLinksInWorkspaceButton.getSelection()) {
+ flags |= OPTION_CREATE_LINKS_IN_WORKSPACE;
+ }
+ if (fImportUnrecognizedButton != null && fImportUnrecognizedButton.getSelection()) {
+ flags |= OPTION_IMPORT_UNRECOGNIZED_TRACES;
+ }
+ if (fOverwriteExistingResourcesCheckbox != null && fOverwriteExistingResourcesCheckbox.getSelection()) {
+ flags |= OPTION_OVERWRITE_EXISTING_RESOURCES;
+ }
+ if (fPreserveFolderStructureButton != null && fPreserveFolderStructureButton.getSelection()) {
+ flags |= OPTION_PRESERVE_FOLDER_STRUCTURE;
+ }
+ return flags;
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ disposeSelectionGroupRoot();
+ }
+
+ // ------------------------------------------------------------------------
+ // Classes
+ // ------------------------------------------------------------------------
+
+ private class TraceValidateAndImportOperation {
+ private IStatus fStatus;
+ private String fTraceType;
+ private IPath fDestinationContainerPath;
+ private IPath fBaseSourceContainerPath;
+ private boolean fImportFromArchive;
+ private int fImportOptionFlags;
+ private ImportConflictHandler fConflictHandler;
+ private String fCurrentPath;
+
+ private TraceValidateAndImportOperation(String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean importFromArchive, int importOptionFlags) {
+ fTraceType = traceId;
+ fBaseSourceContainerPath = baseSourceContainerPath;
+ fDestinationContainerPath = destinationContainerPath;
+ fImportOptionFlags = importOptionFlags;
+ fImportFromArchive = importFromArchive;
+
+ boolean overwriteExistingResources = (importOptionFlags & OPTION_OVERWRITE_EXISTING_RESOURCES) != 0;
+ if (overwriteExistingResources) {
+ fConflictHandler = new ImportConflictHandler(getContainer().getShell(), fTraceFolderElement, ImportConfirmation.OVERWRITE_ALL);
+ } else {
+ fConflictHandler = new ImportConflictHandler(getContainer().getShell(), fTraceFolderElement, ImportConfirmation.SKIP);
+ }
+ }
+
+ public void run(IProgressMonitor progressMonitor) {
+ try {
+
+ final List<TraceFileSystemElement> selectedFileSystemElements = new LinkedList<>();
+ IElementFilter passThroughFilter = new IElementFilter() {
+
+ @Override
+ public void filterElements(Collection elements, IProgressMonitor monitor) {
+ selectedFileSystemElements.addAll(elements);
+ }
+
+ @Override
+ public void filterElements(Object[] elements, IProgressMonitor monitor) {
+ for (int i = 0; i < elements.length; i++) {
+ selectedFileSystemElements.add((TraceFileSystemElement) elements[i]);
+ }
+ }
+ };
+
+ // List fileSystemElements will be filled using the
+ // passThroughFilter
+ SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 1);
+ fSelectionGroup.getAllCheckedListItems(passThroughFilter, subMonitor);
+
+ // Check if operation was cancelled.
+ ModalContext.checkCanceled(subMonitor);
+
+ // Temporary directory to contain any extracted files
+ IFolder destTempFolder = fTargetFolder.getProject().getFolder(TRACE_IMPORT_TEMP_FOLDER);
+ if (destTempFolder.exists()) {
+ SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+ destTempFolder.delete(true, monitor);
+ }
+ SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+ destTempFolder.create(IResource.HIDDEN, true, monitor);
+
+ subMonitor = SubMonitor.convert(progressMonitor, 2);
+ String baseSourceLocation;
+ if (fImportFromArchive) {
+ // When importing from archive, we first extract the
+ // *selected* files to a temporary folder then create new
+ // TraceFileSystemElements
+
+ SubMonitor archiveMonitor = SubMonitor.convert(subMonitor.newChild(1), 2);
+
+ // Extract selected files from source archive to temporary folder
+ extractArchiveContent(selectedFileSystemElements.iterator(), destTempFolder, archiveMonitor.newChild(1));
+
+ // Even if the files were extracted to temporary folder, they have to look like they originate from the source archive
+ baseSourceLocation = getRootElement(selectedFileSystemElements.get(0)).getSourceLocation();
+ // Extract additional archives contained in the extracted files (archives in archives)
+ List<TraceFileSystemElement> tempFolderFileSystemElements = createElementsForFolder(destTempFolder);
+ extractAllArchiveFiles(tempFolderFileSystemElements, destTempFolder, destTempFolder.getLocation(), archiveMonitor.newChild(1));
+ } else {
+ SubMonitor directoryMonitor = SubMonitor.convert(subMonitor.newChild(1), 2);
+ // Import selected files, excluding archives (done in a later step)
+ importFileSystemElements(directoryMonitor.newChild(1), selectedFileSystemElements);
+
+ // Extract archives in selected files (if any) to temporary folder
+ extractAllArchiveFiles(selectedFileSystemElements, destTempFolder, fBaseSourceContainerPath, directoryMonitor.newChild(1));
+ // Even if the files were extracted to temporary folder, they have to look like they originate from the source folder
+ baseSourceLocation = URIUtil.toUnencodedString(fBaseSourceContainerPath.toFile().getCanonicalFile().toURI());
+ }
+
+ /* Import extracted files that are now in the temporary folder, if any */
+
+ // We need to update the source container path because the
+ // "preserve folder structure" option would create the
+ // wrong trace folders otherwise.
+ fBaseSourceContainerPath = destTempFolder.getLocation();
+ List<TraceFileSystemElement> tempFolderFileSystemElements = createElementsForFolder(destTempFolder);
+ calculateSourceLocations(tempFolderFileSystemElements, baseSourceLocation);
+ // Never import extracted files as links, they would link to the
+ // temporary directory that will be deleted
+ fImportOptionFlags = fImportOptionFlags & ~OPTION_CREATE_LINKS_IN_WORKSPACE;
+ SubMonitor importTempMonitor = subMonitor.newChild(1);
+ importFileSystemElements(importTempMonitor, tempFolderFileSystemElements);
+
+ if (destTempFolder.exists()) {
+ destTempFolder.delete(true, progressMonitor);
+ }
+
+ setStatus(Status.OK_STATUS);
+ } catch (InterruptedException e) {
+ setStatus(Status.CANCEL_STATUS);
+ } catch (Exception e) {
+ String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$
+ (fCurrentPath != null ? fCurrentPath : ""); //$NON-NLS-1$
+ Activator.getDefault().logError(errorMessage, e);
+ setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage, e));
+ }
+ }
+
+ /**
+ * Import a collection of file system elements into the workspace.
+ */
+ private void importFileSystemElements(IProgressMonitor monitor, List<TraceFileSystemElement> fileSystemElements)
+ throws InterruptedException, TmfTraceImportException, CoreException, InvocationTargetException {
+ SubMonitor subMonitor = SubMonitor.convert(monitor, fileSystemElements.size());
+
+ ListIterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.listIterator();
+
+ // Map to remember already imported directory traces
+ final Map<String, TraceFileSystemElement> directoryTraces = new HashMap<>();
+ while (fileSystemElementsIter.hasNext()) {
+ ModalContext.checkCanceled(monitor);
+ fCurrentPath = null;
+ TraceFileSystemElement element = fileSystemElementsIter.next();
+ IFileSystemObject fileSystemObject = element.getFileSystemObject();
+ String resourcePath = element.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
+ element.setDestinationContainerPath(computeDestinationContainerPath(new Path(resourcePath)));
+
+ fCurrentPath = resourcePath;
+ SubMonitor sub = subMonitor.newChild(1);
+ if (element.isDirectory()) {
+ if (!directoryTraces.containsKey(resourcePath) && isDirectoryTrace(element)) {
+ directoryTraces.put(resourcePath, element);
+ validateAndImportTrace(element, sub);
+ }
+ } else {
+ TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
+ String parentPath = parentElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
+ parentElement.setDestinationContainerPath(computeDestinationContainerPath(new Path(parentPath)));
+ fCurrentPath = parentPath;
+ if (!directoryTraces.containsKey(parentPath)) {
+ if (isDirectoryTrace(parentElement)) {
+ directoryTraces.put(parentPath, parentElement);
+ validateAndImportTrace(parentElement, sub);
+ } else {
+ boolean validateFile = true;
+ TraceFileSystemElement grandParentElement = (TraceFileSystemElement) parentElement.getParent();
+ // Special case for LTTng trace that may contain index directory and files
+ if (grandParentElement != null) {
+ String grandParentPath = grandParentElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
+ grandParentElement.setDestinationContainerPath(computeDestinationContainerPath(new Path(parentPath)));
+ fCurrentPath = grandParentPath;
+ if (directoryTraces.containsKey(grandParentPath)) {
+ validateFile = false;
+ } else if (isDirectoryTrace(grandParentElement)) {
+ directoryTraces.put(grandParentPath, grandParentElement);
+ validateAndImportTrace(grandParentElement, sub);
+ validateFile = false;
+ }
+ }
+ if (validateFile && (fileSystemObject.exists())) {
+ validateAndImportTrace(element, sub);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Generate a new list of file system elements for the specified folder.
+ */
+ private List<TraceFileSystemElement> createElementsForFolder(IFolder folder) {
+ // Create the new import provider and root element based on the specified folder
+ FileSystemObjectImportStructureProvider importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
+ IFileSystemObject rootElement = importStructureProvider.getIFileSystemObject(new File(folder.getLocation().toOSString()));
+ TraceFileSystemElement createRootElement = createRootTraceFileElement(rootElement, importStructureProvider);
+ List<TraceFileSystemElement> list = new LinkedList<>();
+ getAllChildren(list, createRootElement);
+ return list;
+ }
+
+ /**
+ * Extract all file system elements (File) to destination folder (typically workspace/TraceProject/.traceImport)
+ */
+ private void extractAllArchiveFiles(List<TraceFileSystemElement> fileSystemElements, IFolder destFolder, IPath baseSourceContainerPath, IProgressMonitor progressMonitor) throws InterruptedException, CoreException, InvocationTargetException {
+ SubMonitor subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size());
+ ListIterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.listIterator();
+ while (fileSystemElementsIter.hasNext()) {
+ ModalContext.checkCanceled(subMonitor);
+
+ SubMonitor elementProgress = subMonitor.newChild(1);
+ TraceFileSystemElement element = fileSystemElementsIter.next();
+ File archiveFile = (File) element.getFileSystemObject().getRawFileSystemObject();
+ boolean isArchiveFileElement = element.getFileSystemObject() instanceof FileFileSystemObject && isArchiveFile(archiveFile);
+ if (isArchiveFileElement) {
+ elementProgress = SubMonitor.convert(elementProgress, 4);
+ IPath relativeToSourceContainer = new Path(element.getFileSystemObject().getAbsolutePath(null)).makeRelativeTo(baseSourceContainerPath);
+ IFolder folder = safeCreateExtractedFolder(destFolder, relativeToSourceContainer, elementProgress.newChild(1));
+ extractArchiveToFolder(archiveFile, folder, elementProgress.newChild(1));
+
+ // Delete original archive, we don't want to import this, just the extracted content
+ IFile fileRes = destFolder.getFile(relativeToSourceContainer);
+ fileRes.delete(true, elementProgress.newChild(1));
+ IPath newPath = destFolder.getFullPath().append(relativeToSourceContainer);
+ // Rename extracted folder (.extract) to original archive name
+ folder.move(newPath, true, elementProgress.newChild(1));
+ folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(newPath);
+
+ // Create the new import provider and root element based on
+ // the newly extracted temporary folder
+ FileSystemObjectImportStructureProvider importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
+ IFileSystemObject rootElement = importStructureProvider.getIFileSystemObject(new File(folder.getLocation().toOSString()));
+ TraceFileSystemElement newElement = createRootTraceFileElement(rootElement, importStructureProvider);
+ List<TraceFileSystemElement> extractedChildren = new ArrayList<>();
+ getAllChildren(extractedChildren, newElement);
+ extractAllArchiveFiles(extractedChildren, folder, folder.getLocation(), progressMonitor);
+ }
+ }
+ }
+
+ /**
+ * Extract a file (File) to a destination folder
+ */
+ private void extractArchiveToFolder(File sourceFile, IFolder destinationFolder, IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException {
+ Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> rootObjectAndProvider = getRootObjectAndProvider(sourceFile);
+ TraceFileSystemElement rootElement = createRootTraceFileElement(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond());
+ List<TraceFileSystemElement> fileSystemElements = new ArrayList<>();
+ getAllChildren(fileSystemElements, rootElement);
+ extractArchiveContent(fileSystemElements.listIterator(), destinationFolder, progressMonitor);
+ rootObjectAndProvider.getSecond().dispose();
+ }
+
+ /**
+ * Safely create a folder meant to receive extracted content by making sure there is no name clash.
+ */
+ private IFolder safeCreateExtractedFolder(IFolder destinationFolder, IPath relativeContainerRelativePath, IProgressMonitor monitor) throws CoreException {
+ SubMonitor subMonitor = SubMonitor.convert(monitor, 2);
+ IFolder extractedFolder;
+ String suffix = ""; //$NON-NLS-1$
+ int i = 2;
+ while (true) {
+ IPath fullPath = destinationFolder.getFullPath().append(relativeContainerRelativePath + ".extract" + suffix); //$NON-NLS-1$
+ IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(fullPath);
+ if (!folder.exists()) {
+ extractedFolder = folder;
+ break;
+ }
+ suffix = "(" + i + ")"; //$NON-NLS-1$//$NON-NLS-2$
+ i++;
+ }
+ subMonitor.worked(1);
+
+ TraceUtils.createFolder(extractedFolder, subMonitor.newChild(1));
+ return extractedFolder;
+ }
+
+ private void calculateSourceLocations(List<TraceFileSystemElement> fileSystemElements, String baseSourceLocation) {
+ for (TraceFileSystemElement element : fileSystemElements) {
+ IPath tempRelative = new Path(element.getFileSystemObject().getAbsolutePath(null)).makeRelativeTo(fBaseSourceContainerPath);
+ String sourceLocation = baseSourceLocation + tempRelative;
+ element.setSourceLocation(sourceLocation);
+
+ TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
+ tempRelative = new Path(parentElement.getFileSystemObject().getAbsolutePath(null)).makeRelativeTo(fBaseSourceContainerPath);
+ sourceLocation = baseSourceLocation + tempRelative + '/';
+ parentElement.setSourceLocation(sourceLocation);
+ }
+ }
+
+ /**
+ * Extract all file system elements (Tar, Zip elements) to destination folder (typically workspace/TraceProject/.traceImport or a subfolder of it)
+ */
+ private void extractArchiveContent(Iterator<TraceFileSystemElement> fileSystemElementsIter, IFolder tempFolder, IProgressMonitor progressMonitor) throws InterruptedException,
+ InvocationTargetException {
+ List<TraceFileSystemElement> subList = new ArrayList<>();
+ // Collect all the elements
+ while (fileSystemElementsIter.hasNext()) {
+ ModalContext.checkCanceled(progressMonitor);
+ TraceFileSystemElement element = fileSystemElementsIter.next();
+ if (element.isDirectory()) {
+ Object[] array = element.getFiles().getChildren();
+ for (int i = 0; i < array.length; i++) {
+ subList.add((TraceFileSystemElement) array[i]);
+ }
+ }
+ subList.add(element);
+ }
+
+ TraceFileSystemElement root = getRootElement(subList.get(0));
+
+ ImportProvider fileSystemStructureProvider = new ImportProvider();
+
+ IOverwriteQuery myQueryImpl = new IOverwriteQuery() {
+ @Override
+ public String queryOverwrite(String file) {
+ return IOverwriteQuery.NO_ALL;
+ }
+ };
+
+ progressMonitor.setTaskName(Messages.ImportTraceWizard_ExtractImportOperationTaskName);
+ IPath containerPath = tempFolder.getFullPath();
+ ImportOperation operation = new ImportOperation(containerPath, root, fileSystemStructureProvider, myQueryImpl, subList);
+ operation.setContext(getShell());
+
+ operation.setCreateContainerStructure(true);
+ operation.setOverwriteResources(false);
+ operation.setVirtualFolders(false);
+
+ operation.run(new SubProgressMonitor(progressMonitor, subList.size(), SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+ }
+
+ private TraceFileSystemElement getRootElement(TraceFileSystemElement element) {
+ TraceFileSystemElement root = element;
+ while (root.getParent() != null) {
+ root = (TraceFileSystemElement) root.getParent();
+ }
+ return root;
+ }
+
+ /**
+ * Get all the TraceFileSystemElements recursively.
+ *
+ * @param result
+ * the list accumulating the result
+ * @param rootElement
+ * the root element of the file system to be imported
+ */
+ private void getAllChildren(List<TraceFileSystemElement> result, TraceFileSystemElement rootElement) {
+ AdaptableList files = rootElement.getFiles();
+ for (Object file : files.getChildren()) {
+ result.add((TraceFileSystemElement) file);
+ }
+
+ AdaptableList folders = rootElement.getFolders();
+ for (Object folder : folders.getChildren()) {
+ getAllChildren(result, (TraceFileSystemElement) folder);
+ }
+ }
+
+ private IPath computeDestinationContainerPath(Path resourcePath) {
+ IPath destinationContainerPath = fDestinationContainerPath;
+
+ // We need to figure out the new destination path relative to the
+ // selected "base" source directory.
+ // Here for example, the selected source directory is /home/user
+ if ((fImportOptionFlags & OPTION_PRESERVE_FOLDER_STRUCTURE) != 0) {
+ // /home/user/bar/foo/trace -> /home/user/bar/foo
+ IPath sourceContainerPath = resourcePath.removeLastSegments(1);
+ if (fBaseSourceContainerPath.equals(resourcePath)) {
+ // Use resourcePath directory if fBaseSourceContainerPath
+ // points to a directory trace
+ sourceContainerPath = resourcePath;
+ }
+ // /home/user/bar/foo, /home/user -> bar/foo
+ IPath relativeContainerPath = sourceContainerPath.makeRelativeTo(fBaseSourceContainerPath);
+ // project/Traces + bar/foo -> project/Traces/bar/foo
+ destinationContainerPath = fDestinationContainerPath.append(relativeContainerPath);
+ }
+ return destinationContainerPath;
+ }
+
+ /**
+ * Import a single file system element into the workspace.
+ */
+ private void validateAndImportTrace(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor)
+ throws TmfTraceImportException, CoreException, InvocationTargetException, InterruptedException {
+ String parentContainerPath = fBaseSourceContainerPath.toOSString();
+ String path = fileSystemElement.getFileSystemObject().getAbsolutePath(parentContainerPath);
+ TraceTypeHelper traceTypeHelper = null;
+
+ File file = (File) fileSystemElement.getFileSystemObject().getRawFileSystemObject();
+ boolean isArchiveFileElement = fileSystemElement.getFileSystemObject() instanceof FileFileSystemObject && isArchiveFile(file);
+ if (isArchiveFileElement) {
+ // We'll be extracting this later, do not import as a trace
+ return;
+ }
+
+ if (fTraceType == null) {
+ // Auto Detection
+ try {
+ traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(path, null, null);
+ } catch (TmfTraceImportException e) {
+ // the trace did not match any trace type
+ }
+ if (traceTypeHelper == null) {
+ if ((fImportOptionFlags & OPTION_IMPORT_UNRECOGNIZED_TRACES) != 0) {
+ importResource(fileSystemElement, monitor);
+ }
+ return;
+ }
+ } else {
+ boolean isDirectoryTraceType = TmfTraceType.isDirectoryTraceType(fTraceType);
+ if (fileSystemElement.isDirectory() != isDirectoryTraceType) {
+ return;
+ }
+ traceTypeHelper = TmfTraceType.getTraceType(fTraceType);
+
+ if (traceTypeHelper == null) {
+ // Trace type not found
+ throw new TmfTraceImportException(Messages.ImportTraceWizard_TraceTypeNotFound);
+ }
+
+ if (!traceTypeHelper.validate(path).isOK()) {
+ // Trace type exist but doesn't validate for given trace.
+ return;
+ }
+ }
+
+ // Finally import trace
+ IResource importedResource = importResource(fileSystemElement, monitor);
+ if (importedResource != null) {
+ TmfTraceTypeUIUtils.setTraceType(importedResource, traceTypeHelper);
+ }
+
+ }
+
+ /**
+ * Imports a trace resource to project. In case of name collision the
+ * user will be asked to confirm overwriting the existing trace,
+ * overwriting or skipping the trace to be imported.
+ *
+ * @param fileSystemElement
+ * trace file system object to import
+ * @param monitor
+ * a progress monitor
+ * @return the imported resource or null if no resource was imported
+ *
+ * @throws InvocationTargetException
+ * if problems during import operation
+ * @throws InterruptedException
+ * if cancelled
+ * @throws CoreException
+ * if problems with workspace
+ */
+ private IResource importResource(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException, CoreException {
+
+ IPath tracePath = getInitialDestinationPath(fileSystemElement);
+ String newName = fConflictHandler.checkAndHandleNameClash(tracePath, monitor);
+ if (newName == null) {
+ return null;
+ }
+ fileSystemElement.setLabel(newName);
+
+ List<TraceFileSystemElement> subList = new ArrayList<>();
+
+ FileSystemElement parentFolder = fileSystemElement.getParent();
+
+ IPath containerPath = fileSystemElement.getDestinationContainerPath();
+ tracePath = containerPath.addTrailingSeparator().append(fileSystemElement.getLabel());
+ boolean createLinksInWorkspace = (fImportOptionFlags & OPTION_CREATE_LINKS_IN_WORKSPACE) != 0;
+ if (fileSystemElement.isDirectory() && !createLinksInWorkspace) {
+ containerPath = tracePath;
+
+ Object[] array = fileSystemElement.getFiles().getChildren();
+ for (int i = 0; i < array.length; i++) {
+ subList.add((TraceFileSystemElement) array[i]);
+ }
+ parentFolder = fileSystemElement;
+
+ } else {
+ subList.add(fileSystemElement);
+ }
+
+ ImportProvider fileSystemStructureProvider = new ImportProvider();
+
+ IOverwriteQuery myQueryImpl = new IOverwriteQuery() {
+ @Override
+ public String queryOverwrite(String file) {
+ return IOverwriteQuery.NO_ALL;
+ }
+ };
+
+ monitor.setTaskName(Messages.ImportTraceWizard_ImportOperationTaskName + " " + fileSystemElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString())); //$NON-NLS-1$
+ ImportOperation operation = new ImportOperation(containerPath, parentFolder, fileSystemStructureProvider, myQueryImpl, subList);
+ operation.setContext(getShell());
+
+ operation.setCreateContainerStructure(false);
+ operation.setOverwriteResources(false);
+ operation.setCreateLinks(createLinksInWorkspace);
+ operation.setVirtualFolders(false);
+
+ operation.run(new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+ String sourceLocation = fileSystemElement.getSourceLocation();
+ IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(tracePath);
+ if (sourceLocation != null) {
+ resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ }
+
+ return resource;
+ }
+
+ private boolean isDirectoryTrace(TraceFileSystemElement fileSystemElement) {
+ String path = fileSystemElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
+ if (TmfTraceType.isDirectoryTrace(path)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @return the initial destination path, before rename, if any
+ */
+ private IPath getInitialDestinationPath(TraceFileSystemElement fileSystemElement) {
+ IPath traceFolderPath = fileSystemElement.getDestinationContainerPath();
+ return traceFolderPath.append(fileSystemElement.getFileSystemObject().getLabel());
+ }
+
+ /**
+ * Set the status for this operation
+ *
+ * @param status
+ * the status
+ */
+ protected void setStatus(IStatus status) {
+ fStatus = status;
+ }
+
+ public IStatus getStatus() {
+ return fStatus;
+ }
+ }
+
+ /**
+ * The <code>TraceFileSystemElement</code> is a
+ * <code>FileSystemElement</code> that knows if it has been populated or
+ * not.
+ */
+ private static class TraceFileSystemElement extends FileSystemElement {
+
+ private boolean fIsPopulated = false;
+ private String fLabel = null;
+ private IPath fDestinationContainerPath;
+ private FileSystemObjectImportStructureProvider fProvider;
+ private String fSourceLocation;
+
+ public TraceFileSystemElement(String name, FileSystemElement parent, boolean isDirectory, FileSystemObjectImportStructureProvider provider) {
+ super(name, parent, isDirectory);
+ fProvider = provider;
+ }
+
+ public void setDestinationContainerPath(IPath destinationContainerPath) {
+ fDestinationContainerPath = destinationContainerPath;
+ }
+
+ public void setPopulated() {
+ fIsPopulated = true;
+ }
+
+ public boolean isPopulated() {
+ return fIsPopulated;
+ }
+
+ @Override
+ public AdaptableList getFiles() {
+ if (!fIsPopulated) {
+ populateElementChildren();
+ }
+ return super.getFiles();
+ }
+
+ @Override
+ public AdaptableList getFolders() {
+ if (!fIsPopulated) {
+ populateElementChildren();
+ }
+ return super.getFolders();
+ }
+
+ /**
+ * Sets the label for the trace to be used when importing at trace.
+ *
+ * @param name
+ * the label for the trace
+ */
+ public void setLabel(String name) {
+ fLabel = name;
+ }
+
+ /**
+ * Returns the label for the trace to be used when importing at trace.
+ *
+ * @return the label of trace resource
+ */
+ public String getLabel() {
+ if (fLabel == null) {
+ return getFileSystemObject().getLabel();
+ }
+ return fLabel;
+ }
+
+ /**
+ * The full path to the container that will contain the trace
+ *
+ * @return the destination container path
+ */
+ public IPath getDestinationContainerPath() {
+ return fDestinationContainerPath;
+ }
+
+ /**
+ * Populates the children of the specified parent
+ * <code>FileSystemElement</code>
+ */
+ private void populateElementChildren() {
+ List<IFileSystemObject> allchildren = fProvider.getChildren(this.getFileSystemObject());
+ Object child = null;
+ TraceFileSystemElement newelement = null;
+ Iterator<IFileSystemObject> iter = allchildren.iterator();
+ while (iter.hasNext()) {
+ child = iter.next();
+ newelement = new TraceFileSystemElement(fProvider.getLabel(child), this, fProvider.isFolder(child), fProvider);
+ newelement.setFileSystemObject(child);
+ }
+ setPopulated();
+ }
+
+ public FileSystemObjectImportStructureProvider getProvider() {
+ return fProvider;
+ }
+
+ @Override
+ public IFileSystemObject getFileSystemObject() {
+ Object fileSystemObject = super.getFileSystemObject();
+ return (IFileSystemObject) fileSystemObject;
+ }
+
+ public String getSourceLocation() {
+ if (fSourceLocation == null) {
+ fSourceLocation = getFileSystemObject().getSourceLocation();
+ }
+ return fSourceLocation;
+ }
+
+ public void setSourceLocation(String sourceLocation) {
+ fSourceLocation = sourceLocation;
+ }
+ }
+
+ /**
+ * This interface abstracts the differences between different kinds of
+ * FileSystemObjects such as File, TarEntry, ZipEntry, etc. This allows
+ * clients (TraceFileSystemElement, TraceValidateAndImportOperation) to
+ * handle all the types transparently.
+ */
+ private interface IFileSystemObject {
+ String getLabel();
+
+ String getName();
+
+ String getAbsolutePath(String parentContainerPath);
+
+ String getSourceLocation();
+
+ Object getRawFileSystemObject();
+
+ boolean exists();
+ }
+
+ /**
+ * The "File" implementation of an IFileSystemObject
+ */
+ private static class FileFileSystemObject implements IFileSystemObject {
+
+ private File fFileSystemObject;
+
+ private FileFileSystemObject(File fileSystemObject) {
+ fFileSystemObject = fileSystemObject;
+ }
+
+ @Override
+ public String getLabel() {
+ String name = fFileSystemObject.getName();
+ if (name.length() == 0) {
+ return fFileSystemObject.getPath();
+ }
+ return name;
+ }
+
+ @Override
+ public String getName() {
+ return fFileSystemObject.getName();
+ }
+
+ @Override
+ public String getAbsolutePath(String parentContainerPath) {
+ return fFileSystemObject.getAbsolutePath();
+ }
+
+ @Override
+ public boolean exists() {
+ return fFileSystemObject.exists();
+ }
+
+ @Override
+ public String getSourceLocation() {
+ IResource sourceResource;
+ String sourceLocation = null;
+ if (fFileSystemObject.isDirectory()) {
+ sourceResource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(Path.fromOSString(fFileSystemObject.getAbsolutePath()));
+ } else {
+ sourceResource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(fFileSystemObject.getAbsolutePath()));
+ }
+ if (sourceResource != null && sourceResource.exists()) {
+ try {
+ sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION);
+ } catch (CoreException e) {
+ // Something went wrong with the already existing resource.
+ // This is not a problem, we'll assign a new location below.
+ }
+ }
+ if (sourceLocation == null) {
+ try {
+ sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.getCanonicalFile().toURI());
+ } catch (IOException e) {
+ // Something went wrong canonicalizing the file. We can still use the URI but there might be extra ../ in it.
+ sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.toURI());
+ }
+ }
+ return sourceLocation;
+ }
+
+ @Override
+ public Object getRawFileSystemObject() {
+ return fFileSystemObject;
+ }
+ }
+
+ /**
+ * The "Tar" implementation of an IFileSystemObject, entries can also be Gzipped and are uncompressed transparently.
+ */
+ private static class TarFileSystemObject implements IFileSystemObject {
+
+ private TarEntry fFileSystemObject;
+ private String fArchivePath;
+
+ private TarFileSystemObject(TarEntry fileSystemObject, String archivePath) {
+ fFileSystemObject = fileSystemObject;
+ fArchivePath = archivePath;
+ }
+
+ @Override
+ public String getLabel() {
+ return new Path(fFileSystemObject.getName()).lastSegment();
+ }
+
+ @Override
+ public String getName() {
+ return fFileSystemObject.getName();
+ }
+
+ @Override
+ public String getAbsolutePath(String parentContainerPath) {
+ return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString();
+ }
+
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public String getSourceLocation() {
+ File file = new File(fArchivePath);
+ try {
+ file = file.getCanonicalFile();
+ } catch (IOException e) {
+ // Will still work but might have extra ../ in the path
+ }
+ URI uri = file.toURI();
+ IPath entryPath = new Path(fFileSystemObject.getName());
+
+ URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath);
+ return URIUtil.toUnencodedString(jarURI);
+ }
+
+ @Override
+ public Object getRawFileSystemObject() {
+ return fFileSystemObject;
+ }
+ }
+
+ /**
+ * The "GZIP" implementation of an IFileSystemObject. For a GZIP file that is not in a tar.
+ */
+ private static class GzipFileSystemObject implements IFileSystemObject {
+
+ private GzipEntry fFileSystemObject;
+ private String fArchivePath;
+
+ private GzipFileSystemObject(GzipEntry fileSystemObject, String archivePath) {
+ fFileSystemObject = fileSystemObject;
+ fArchivePath = archivePath;
+ }
+
+ @Override
+ public String getLabel() {
+ return new Path(fFileSystemObject.getName()).lastSegment();
+ }
+
+ @Override
+ public String getName() {
+ return fFileSystemObject.getName();
+ }
+
+ @Override
+ public String getAbsolutePath(String parentContainerPath) {
+ return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString();
+ }
+
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public String getSourceLocation() {
+ File file = new File(fArchivePath);
+ try {
+ file = file.getCanonicalFile();
+ } catch (IOException e) {
+ // Will still work but might have extra ../ in the path
+ }
+ URI uri = file.toURI();
+ IPath entryPath = new Path(fFileSystemObject.getName());
+
+ URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath);
+ return URIUtil.toUnencodedString(jarURI);
+ }
+
+ @Override
+ public Object getRawFileSystemObject() {
+ return fFileSystemObject;
+ }
+ }
+
+ /**
+ * The "Zip" implementation of an IFileSystemObject
+ */
+ private static class ZipFileSystemObject implements IFileSystemObject {
+
+ private ZipEntry fFileSystemObject;
+ private String fArchivePath;
+
+ private ZipFileSystemObject(ZipEntry fileSystemObject, String archivePath) {
+ fFileSystemObject = fileSystemObject;
+ fArchivePath = archivePath;
+ }
+
+ @Override
+ public String getLabel() {
+ return new Path(fFileSystemObject.getName()).lastSegment();
+ }
+
+ @Override
+ public String getName() {
+ return fFileSystemObject.getName();
+ }
+
+ @Override
+ public String getAbsolutePath(String parentContainerPath) {
+ return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString();
+ }
+
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public String getSourceLocation() {
+ File file = new File(fArchivePath);
+ try {
+ file = file.getCanonicalFile();
+ } catch (IOException e) {
+ // Will still work but might have extra ../ in the path
+ }
+ URI uri = file.toURI();
+ IPath entryPath = new Path(fFileSystemObject.getName());
+
+ URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath);
+ return URIUtil.toUnencodedString(jarURI);
+ }
+
+ @Override
+ public Object getRawFileSystemObject() {
+ return fFileSystemObject;
+ }
+ }
+
+ private class ImportProvider implements IImportStructureProvider {
+
+ ImportProvider() {
+ }
+
+ @Override
+ public String getLabel(Object element) {
+ TraceFileSystemElement resource = (TraceFileSystemElement) element;
+ return resource.getLabel();
+ }
+
+ @Override
+ public List getChildren(Object element) {
+ TraceFileSystemElement resource = (TraceFileSystemElement) element;
+ Object[] array = resource.getFiles().getChildren();
+ List<Object> list = new ArrayList<>();
+ for (int i = 0; i < array.length; i++) {
+ list.add(array[i]);
+ }
+ return list;
+ }
+
+ @Override
+ public InputStream getContents(Object element) {
+ TraceFileSystemElement resource = (TraceFileSystemElement) element;
+ return resource.getProvider().getContents(resource.getFileSystemObject());
+ }
+
+ @Override
+ public String getFullPath(Object element) {
+ TraceFileSystemElement resource = (TraceFileSystemElement) element;
+ return resource.getProvider().getFullPath(resource.getFileSystemObject());
+ }
+
+ @Override
+ public boolean isFolder(Object element) {
+ TraceFileSystemElement resource = (TraceFileSystemElement) element;
+ return resource.isDirectory();
+ }
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPageOptions.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPageOptions.java
new file mode 100644
index 0000000000..056169c1ac
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPageOptions.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Marc-Andre Laperle - Use common method to get opened tmf projects
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * This page selects the project to import to.
+ *
+ * @author Matthew Khouzam
+ */
+public class ImportTraceWizardPageOptions extends AbstractImportTraceWizardPage {
+
+ private List fProjects;
+ private final Map<String, IProject> fProjectsMap = new LinkedHashMap<>();
+
+ /**
+ * Import page that tells where the trace will go
+ *
+ * @param workbench
+ * The workbench reference.
+ * @param selection
+ * The current selection
+ */
+ public ImportTraceWizardPageOptions(IWorkbench workbench, IStructuredSelection selection) {
+ super(workbench, selection);
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ IFolder originalFolder = getBatchWizard().getTargetFolder();
+ IProject proj = null;
+ if (originalFolder != null) {
+ proj = originalFolder.getProject();
+ }
+
+ Composite optionPane = (Composite) this.getControl();
+ optionPane.setLayout(new GridLayout());
+ optionPane.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
+
+ fProjects = new List(optionPane, SWT.V_SCROLL);
+ fProjects.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ for (IProject project : TraceUtils.getOpenedTmfProjects()) {
+ final String name = project.getName();
+ fProjectsMap.put(name, project);
+ fProjects.add(name);
+ }
+
+ fProjects.getSelection();
+ fProjects.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWithSelection();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ updateWithSelection();
+ }
+ });
+ if (proj != null) {
+ fProjects.setSelection(fProjects.indexOf(proj.getName()));
+ } else if (fProjects.getItemCount() > 0) {
+ fProjects.setSelection(0);
+ updateWithSelection();
+ }
+ setMessage(Messages.SharedSelectProject);
+ this.setTitle(Messages.ImportTraceWizardPageOptionsTitle);
+ }
+
+ private void updateWithSelection() {
+ String[] selection = fProjects.getSelection();
+ if (selection.length > 0) {
+ final String listItem = selection[0];
+ IFolder folder = fProjectsMap.get(listItem).getFolder(TmfTracesFolder.TRACES_FOLDER_NAME);
+ getBatchWizard().setTraceFolder(folder);
+ ImportTraceWizardPageOptions.this.setErrorMessage(null);
+ } else {
+ ImportTraceWizardPageOptions.this.setErrorMessage(Messages.SharedSelectProject);
+ }
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardScanPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardScanPage.java
new file mode 100644
index 0000000000..cdbd4fd816
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardScanPage.java
@@ -0,0 +1,565 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.text.DecimalFormat;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.TreeViewerEditor;
+import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+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.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceValidationHelper;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * <b>Import page that scans files, can be cancelled</b> this page is the third
+ * of three pages shown. This one selects the traces to be imported that are to
+ * be scanned.
+ *
+ * @author Matthew Khouzam
+ */
+public class ImportTraceWizardScanPage extends AbstractImportTraceWizardPage {
+
+ private static final int COL_WIDTH = 200;
+ private static final int MAX_TRACES = 65536;
+ private CheckboxTreeViewer traceTypeViewer;
+
+ final ScanRunnable fRunnable = new ScanRunnable("Scan job"); //$NON-NLS-1$
+ private final BlockingQueue<TraceValidationHelper> fTracesToScan = new ArrayBlockingQueue<>(MAX_TRACES);
+ private volatile boolean fCanRun = true;
+
+ // --------------------------------------------------------------------------------
+ // Constructor and destructor
+ // --------------------------------------------------------------------------------
+
+ /**
+ * Import page that scans files, can be cancelled.
+ *
+ * @param name
+ * The name of the page.
+ * @param selection
+ * The current selection
+ */
+ protected ImportTraceWizardScanPage(String name, IStructuredSelection selection) {
+ super(name, selection);
+ }
+
+ /**
+ * Import page that scans files, can be cancelled
+ *
+ * @param workbench
+ * The workbench reference.
+ * @param selection
+ * The current selection
+ */
+ public ImportTraceWizardScanPage(IWorkbench workbench, IStructuredSelection selection) {
+ super(workbench, selection);
+ }
+
+ @Override
+ public void dispose() {
+ fCanRun = false;
+ fRunnable.done(Status.OK_STATUS);
+ super.dispose();
+ }
+
+ /*
+ * Init
+ */
+
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ final Composite control = (Composite) this.getControl();
+ setTitle(Messages.ImportTraceWizardScanPageTitle);
+ traceTypeViewer = new CheckboxTreeViewer(control, SWT.CHECK);
+ traceTypeViewer.setContentProvider(getBatchWizard().getScannedTraces());
+ traceTypeViewer.getTree().setHeaderVisible(true);
+ traceTypeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ traceTypeViewer.setInput(getBatchWizard().getScannedTraces());
+ traceTypeViewer.addCheckStateListener(new ImportTraceCheckStateListener());
+
+ TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(traceTypeViewer, new FocusCellOwnerDrawHighlighter(traceTypeViewer));
+ ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(traceTypeViewer) {
+ };
+ TreeViewerEditor.create(traceTypeViewer, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
+ | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
+ | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
+
+ final TextCellEditor textCellEditor = new TextCellEditor(traceTypeViewer.getTree());
+ // --------------------
+ // Column 1
+ // --------------------
+ TreeViewerColumn column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
+ column.getColumn().setWidth(COL_WIDTH);
+ column.getColumn().setText(Messages.ImportTraceWizardTraceDisplayName);
+ column.setLabelProvider(new FirstColumnLabelProvider());
+ column.setEditingSupport(new ColumnEditorSupport(traceTypeViewer, textCellEditor));
+
+ // --------------------
+ // Column 2
+ // --------------------
+
+ column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
+ column.getColumn().setWidth(500);
+ column.getColumn().setText(Messages.ImportTraceWizardImportCaption);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element instanceof FileAndName) {
+ FileAndName elem = (FileAndName) element;
+ return elem.getFile().getPath();
+ }
+ return null;
+ }
+ });
+ // --------------------
+ // Column 3
+ // --------------------
+
+ column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
+
+ column.getColumn().setWidth(80);
+ column.getColumn().setText(Messages.ImportTraceWizardScanPageSize);
+ column.getColumn().setAlignment(SWT.RIGHT);
+ column.setLabelProvider(new ColumnLabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof FileAndName) {
+
+ FileAndName elem = (FileAndName) element;
+ long len = recurseSize(elem.getFile());
+ if (len > 0) {
+ double sizeb10 = Math.log10(len);
+ DecimalFormat df = new DecimalFormat();
+ df.setMaximumFractionDigits(2);
+ df.setMinimumFractionDigits(0);
+ if (sizeb10 > 12) {
+ final double tbSize = len / 1024.0 / 1024 / 1024 / 1024;
+ return df.format(tbSize) + Messages.ImportTraceWizardScanPageTerabyte;
+ }
+ if (sizeb10 > 9) {
+ final double gbSize = len / 1024.0 / 1024 / 1024;
+ return df.format(gbSize) + Messages.ImportTraceWizardScanPageGigabyte;
+ }
+ if (sizeb10 > 6) {
+ final double mbSize = len / 1024.0 / 1024;
+ return df.format(mbSize) + Messages.ImportTraceWizardScanPageMegabyte;
+ }
+ if (sizeb10 > 3) {
+ final double kbSize = len / 1024.0;
+ return df.format(kbSize) + Messages.ImportTraceWizardScanPageKilobyte;
+ }
+ }
+ return Long.toString(len) + Messages.ImportTraceWizardScanPagebyte;
+
+ }
+ return null;
+ }
+
+ private long recurseSize(File file) {
+ if (file.isFile() && file.canRead()) {
+ return file.length();
+ }
+ long size = 0;
+ if (file.exists() && file.isDirectory() && file.canRead()) {
+ final File[] listFiles = file.listFiles();
+ if (listFiles != null) {
+ for (File child : listFiles) {
+ if (child.isFile() && child.canRead()) {
+ size += child.length();
+ } else if (child.isDirectory()) {
+ size += recurseSize(child);
+ } else {
+ Activator.getDefault().logError("Unknown \"file\" type for " + child + ' ' + child.toString()); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ return size;
+ }
+ });
+
+ init();
+ getBatchWizard().setTracesToScan(fTracesToScan);
+ getBatchWizard().setTraceFolder(fTargetFolder);
+
+ fRunnable.schedule();
+ setErrorMessage(Messages.ImportTraceWizardScanPageSelectAtleastOne);
+ }
+
+ private void init() {
+ Composite optionPane = (Composite) this.getControl();
+
+ optionPane.setLayout(new GridLayout());
+ optionPane.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
+
+ final Button fLink = new Button(optionPane, SWT.RADIO);
+ fLink.setText(Messages.ImportTraceWizardLinkTraces);
+ fLink.setSelection(true);
+ fLink.setLayoutData(new GridData());
+
+ final Button fCopy = new Button(optionPane, SWT.RADIO);
+ fCopy.setText(Messages.ImportTraceWizardCopyTraces);
+ fCopy.setLayoutData(new GridData());
+
+ final SelectionListener linkedListener = new RadioChooser(fLink);
+
+ fLink.addSelectionListener(linkedListener);
+ fCopy.addSelectionListener(linkedListener);
+
+ Button fOverwrite = new Button(optionPane, SWT.CHECK);
+ fOverwrite.setText(Messages.ImportTraceWizardOverwriteTraces);
+ fOverwrite.setLayoutData(new GridData());
+ fOverwrite.setSelection(true);
+ fOverwrite.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ getBatchWizard().setOverwrite(((Button) e.widget).getSelection());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ /*
+ * Helper classes
+ */
+
+ private final class RadioChooser implements SelectionListener {
+ private final Button isLinked;
+
+ public RadioChooser(Button desiredButton) {
+ isLinked = desiredButton;
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+
+ final Button widget = (Button) e.widget;
+ getBatchWizard().setLinked(widget.equals(isLinked));
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+
+ }
+ }
+
+ private final class ColumnEditorSupport extends EditingSupport {
+ private final TextCellEditor textCellEditor;
+
+ private ColumnEditorSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+ super(viewer);
+ this.textCellEditor = textCellEditor;
+ }
+
+ @Override
+ protected boolean canEdit(Object element) {
+ return element instanceof FileAndName;
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element) {
+ return textCellEditor;
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ if (element instanceof FileAndName) {
+ return ((FileAndName) element).getName();
+ }
+ return null;
+ }
+
+ @Override
+ protected void setValue(Object element, Object value) {
+ FileAndName fan = (FileAndName) element;
+ fan.setName((String) value);
+ getBatchWizard().updateConflicts();
+ traceTypeViewer.update(element, null);
+ traceTypeViewer.refresh();
+ }
+ }
+
+ private final class FirstColumnLabelProvider extends ColumnLabelProvider {
+ Image fConflict;
+
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof FileAndName) {
+ final FileAndName fan = (FileAndName) element;
+ if (fan.isConflictingName()) {
+ if (fConflict == null) {
+ fConflict = Activator.getDefault().getImageFromImageRegistry(ITmfImageConstants.IMG_UI_CONFLICT);
+ }
+ return fConflict;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof FileAndName) {
+ FileAndName elem = (FileAndName) element;
+ return elem.getName();
+ }
+ if (element instanceof String) {
+ return (String) element;
+ }
+ return null;
+ }
+ }
+
+ private final class ImportTraceCheckStateListener implements ICheckStateListener {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ final CheckboxTreeViewer tv = (CheckboxTreeViewer)
+ event.getSource();
+ if (event.getElement() instanceof FileAndName) {
+ final FileAndName element = (FileAndName) event.getElement();
+ if (event.getChecked()) {
+ getBatchWizard().addFileToImport(element);
+ traceTypeViewer.update(element, null);
+ }
+ else {
+ getBatchWizard().removeFileToImport(element);
+ traceTypeViewer.update(element, null);
+ }
+ maintainCheckIntegrity(tv, element);
+ }
+ if (event.getElement() instanceof String) {
+
+ tv.setSubtreeChecked(event.getElement(), event.getChecked());
+ final Object[] children =
+ getBatchWizard().getScannedTraces().getChildren(event.getElement());
+ if (event.getChecked()) {
+ for (int i = 0; i < children.length; i++) {
+ final FileAndName element = (FileAndName) children[i];
+ getBatchWizard().addFileToImport(element);
+ traceTypeViewer.update(children[i], null);
+ }
+ }
+ else {
+ for (int i = 0; i < children.length; i++) {
+ getBatchWizard().removeFileToImport((FileAndName) children[i]);
+
+ }
+ }
+
+ }
+ getBatchWizard().updateConflicts();
+ if (getBatchWizard().hasConflicts()) {
+ setErrorMessage(Messages.ImportTraceWizardScanPageRenameError);
+ } else if (!getBatchWizard().hasTracesToImport()) {
+ setErrorMessage(Messages.ImportTraceWizardScanPageSelectAtleastOne);
+ } else {
+ setErrorMessage(null);
+ }
+ getWizard().getContainer().updateButtons();
+ traceTypeViewer.update(event.getElement(), null);
+ }
+
+ private void maintainCheckIntegrity(final CheckboxTreeViewer viewer, final FileAndName element) {
+ final ImportTraceContentProvider scannedTraces = getBatchWizard().getScannedTraces();
+ String parentElement = (String) scannedTraces.getParent(element);
+ boolean allChecked = true;
+ final FileAndName[] siblings = scannedTraces.getSiblings(element);
+ if (siblings != null) {
+ for (FileAndName child : siblings) {
+ allChecked &= viewer.getChecked(child);
+ }
+ }
+ viewer.setChecked(parentElement, allChecked);
+ }
+ }
+
+ private final class ScanRunnable extends Job {
+
+ // monitor is stored here, starts as the main monitor but becomes a
+ // submonitor
+ private IProgressMonitor fMonitor;
+
+ public ScanRunnable(String name) {
+ super(name);
+ this.setSystem(true);
+ }
+
+ private synchronized IProgressMonitor getMonitor() {
+ return fMonitor;
+ }
+
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ /*
+ * Set up phase, it is synchronous
+ */
+ fMonitor = monitor;
+ final Control control = traceTypeViewer.getControl();
+ // please note the sync exec here is to allow us to set
+ control.getDisplay().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ // monitor gets overwritten here so it's necessary to save
+ // it in a field.
+ fMonitor = SubMonitor.convert(getMonitor());
+ getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
+ ((SubMonitor) getMonitor()).setWorkRemaining(IProgressMonitor.UNKNOWN);
+ }
+ });
+ /*
+ * At this point we start calling async execs and updating the view.
+ * This is a good candidate to parallelise.
+ */
+ while (fCanRun == true) {
+ boolean updated = false;
+ boolean validCombo;
+ if (fTracesToScan.isEmpty() && !control.isDisposed()) {
+ control.getDisplay().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ if (!control.isDisposed()) {
+ getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
+ getMonitor().subTask(Messages.ImportTraceWizardPageScanDone);
+ ImportTraceWizardScanPage.this.setMessage(Messages.ImportTraceWizardPageScanScanning + ' ' + Messages.ImportTraceWizardPageScanDone);
+ }
+ }
+ });
+ }
+ try {
+ final TraceValidationHelper traceToScan = fTracesToScan.take();
+
+ if (!getBatchWizard().hasScanned(traceToScan)) {
+ getBatchWizard().addResult(traceToScan, TmfTraceType.validate(traceToScan));
+ }
+
+ /*
+ * The following is to update the UI
+ */
+ validCombo = getBatchWizard().getResult(traceToScan);
+ if (validCombo) {
+ // Synched on it's parent
+
+ getBatchWizard().getScannedTraces().addCandidate(traceToScan.getTraceType(), new File(traceToScan.getTraceToScan()));
+ updated = true;
+ }
+ final int scanned = getBatchWizard().getNumberOfResults();
+ final int total = scanned + fTracesToScan.size();
+ final int prevVal = (int) ((scanned - 1) * 100.0 / total);
+ final int curVal = (int) ((scanned) * 100.0 / total);
+ if (curVal != prevVal) {
+ updated = true;
+ }
+ /*
+ * update the progress
+ */
+ if (updated) {
+ if (!control.isDisposed()) {
+ control.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!control.isDisposed()) {
+ getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
+ getMonitor().subTask(traceToScan.getTraceToScan());
+ getMonitor().worked(1);
+ ImportTraceWizardScanPage.this.setMessage(Messages.ImportTraceWizardPageScanScanning + ' '
+ + Integer.toString(curVal)
+ + '%');
+ }
+ }
+ }
+ );
+ }
+ }
+
+ /*
+ * here we update the table
+ */
+ final boolean editing = traceTypeViewer.isCellEditorActive();
+ if (updated && !editing) {
+ if (!control.isDisposed()) {
+ control.getDisplay().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ if (!control.isDisposed()) {
+ if (!traceTypeViewer.isCellEditorActive()) {
+ traceTypeViewer.refresh();
+ }
+ }
+ }
+ });
+ }
+ }
+ } catch (InterruptedException e) {
+ return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, new String());
+ }
+ }
+ return Status.OK_STATUS;
+ }
+ }
+
+ /**
+ * Refresh the view and the corresponding model.
+ */
+ public void refresh() {
+ final Control control = traceTypeViewer.getControl();
+ if (!control.isDisposed()) {
+ control.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!control.isDisposed()) {
+ traceTypeViewer.refresh();
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectDirectoriesPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectDirectoriesPage.java
new file mode 100644
index 0000000000..c2d61c9387
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectDirectoriesPage.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Marc-Andre Laperle - Remember last selected directory
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+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.DirectoryDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * <b>Select the directories to scan for traces</b> this page is the second of
+ * three pages shown. This one selects the files to be scanned.
+ *
+ * @author Matthew Khouzam
+ */
+public class ImportTraceWizardSelectDirectoriesPage extends AbstractImportTraceWizardPage {
+
+ /**
+ * ID
+ */
+ public static String ID = "org.eclipse.linuxtools.tmf.ui.project.wizards.importtrace.ImportTraceWizardPagePopulate"; //$NON-NLS-1$
+
+ private static final String STORE_DIRECTORY_ID = ID + ".STORE_DIRECTORY_ID"; //$NON-NLS-1$
+
+ /**
+ * Constructor. Creates the trace wizard page.
+ *
+ * @param name
+ * The name of the page.
+ * @param selection
+ * The current selection
+ */
+ protected ImportTraceWizardSelectDirectoriesPage(String name, IStructuredSelection selection) {
+ super(name, selection);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param workbench
+ * The workbench reference.
+ * @param selection
+ * The current selection
+ */
+ public ImportTraceWizardSelectDirectoriesPage(IWorkbench workbench, IStructuredSelection selection) {
+ super(workbench, selection);
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ final Composite control = (Composite) this.getControl();
+ control.setLayout(new GridLayout(2, false));
+ control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ final Table selectedFiles = new Table(control, SWT.H_SCROLL | SWT.V_SCROLL);
+ selectedFiles.clearAll();
+ selectedFiles.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ selectedFiles.setLinesVisible(true);
+
+ Composite buttonArea = new Composite(control, SWT.None);
+ buttonArea.setLayout(new GridLayout());
+ buttonArea.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+
+ Button addFile = new Button(buttonArea, SWT.PUSH);
+ addFile.setText(Messages.ImportTraceWizardAddFile);
+ addFile.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ addFile.addSelectionListener(new AddFileHandler());
+ addFile.setAlignment(SWT.CENTER);
+
+ Button addDirectory = new Button(buttonArea, SWT.PUSH);
+ addDirectory.setText(Messages.ImportTraceWizardAddDirectory);
+ addDirectory.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ addDirectory.addSelectionListener(new AddDirectoryHandler());
+ addDirectory.setAlignment(SWT.CENTER);
+
+ Button removeFile = new Button(buttonArea, SWT.PUSH);
+ removeFile.setText(Messages.ImportTraceWizardRemove);
+ removeFile.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ removeFile.addSelectionListener(new RemoveFileHandler(selectedFiles));
+ removeFile.setAlignment(SWT.CENTER);
+
+// int maxSize = Math.max(addFile.getSize().x, Math.max(addDirectory.getSize().x, removeFile.getSize().x));
+// int maxHeight = Math.max(addFile.getSize().y, Math.max(addDirectory.getSize().y, removeFile.getSize().y));
+// addFile.setSize(maxSize, maxHeight);
+// addDirectory.setSize(maxSize, maxHeight);
+// removeFile.setSize(maxSize, maxHeight);
+
+ this.setTitle(Messages.ImportTraceWizardDirectoryTitle);
+ }
+
+ private void updateButtons() {
+ BatchImportTraceWizard wiz = getBatchWizard();
+ updateTable();
+ wiz.getContainer().updateButtons();
+ }
+
+ private void updateTable() {
+ final Table selectedFiles = (Table) ((Composite) getControl()).getChildren()[0];
+ selectedFiles.clearAll();
+ selectedFiles.setItemCount(0);
+ for (String s : ((BatchImportTraceWizard) getWizard()).getFileNames()) {
+ TableItem ti = new TableItem(selectedFiles, SWT.None);
+ ti.setText(s);
+ }
+ }
+
+ @Override
+ public boolean canFlipToNextPage() {
+ final Table selectedFiles = (Table) ((Composite) getControl()).getChildren()[0];
+ boolean canLoad = selectedFiles.getItemCount() > 0;
+ if (canLoad) {
+ setErrorMessage(null);
+ } else {
+ setErrorMessage(Messages.ImportTraceWizardDirectoryHint);
+ }
+ return canLoad;
+ }
+
+ private final class AddFileHandler implements SelectionListener {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+
+ FileDialog dialog = new
+ FileDialog(Display.getCurrent().getActiveShell(), SWT.NONE);
+
+ String lastDirectory = getLastSelectedDirectory();
+ if (lastDirectory != null) {
+ dialog.setFilterPath(lastDirectory);
+ }
+
+ String fn = dialog.open();
+ if (null != fn) {
+ File f = new File(fn);
+ if (f.exists()) {
+ getBatchWizard().addFileToScan(fn);
+ saveSelectedDirectory(f.getParentFile());
+ }
+ }
+ updateButtons();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ }
+
+ private final class AddDirectoryHandler implements SelectionListener {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+
+ // BUG BUG BUG BUG BUG IN SWT. Cannot read multiple files in a
+ // fake directory.
+
+// FileDialog dialog = new
+// FileDialog(Display.getCurrent().getActiveShell(), SWT.OPEN |
+// SWT.MULTI);
+// dialog.setFilterPath(".");
+// if (null != dialog.open()) {
+// for (String fn : dialog.getFileNames()) {
+// final String pathname = dialog.getFilterPath() +
+// File.separator + fn;
+// File f = new File(pathname);
+// if (f.exists()) {
+// ((BatchImportTraceWizard) getWizard()).addFile(fn, f);
+// }
+// }
+// }
+
+ DirectoryDialog dialog = new
+ DirectoryDialog(Display.getCurrent().getActiveShell(), SWT.NONE);
+ String lastDirectory = getLastSelectedDirectory();
+ if (lastDirectory != null) {
+ dialog.setFilterPath(lastDirectory);
+ }
+
+ String fn = dialog.open();
+ if (null != fn) {
+ File f = new File(fn);
+ if (f.exists()) {
+ getBatchWizard().addFileToScan(fn);
+ saveSelectedDirectory(f);
+ }
+ }
+ updateButtons();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ }
+
+ private String getLastSelectedDirectory() {
+ final IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ final String directory = settings.get(STORE_DIRECTORY_ID);
+ if (directory != null && !directory.isEmpty()) {
+ final File file = new File(directory);
+ if (file.exists()) {
+ return directory.toString();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private void saveSelectedDirectory(File directory) {
+ final IDialogSettings settings = getDialogSettings();
+ if (settings != null && directory != null && directory.exists()) {
+ settings.put(STORE_DIRECTORY_ID, directory.toString());
+ }
+ }
+
+ private final class RemoveFileHandler implements SelectionListener {
+ private final Table selectedFiles;
+
+ private RemoveFileHandler(Table selectedFiles) {
+ this.selectedFiles = selectedFiles;
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ TableItem selectedToRemove[] = selectedFiles.getSelection();
+ for (TableItem victim : selectedToRemove) {
+ String victimName = victim.getText();
+ ((BatchImportTraceWizard) getWizard()).removeFile(victimName);
+ }
+ updateButtons();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectTraceTypePage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectTraceTypePage.java
new file mode 100644
index 0000000000..dc403d5488
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardSelectTraceTypePage.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2015 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.SWT;
+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.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * <b>Select trace types to import</b>, this page is the first of three pages
+ * shown. This one selects the type of traces that are to be scanned.
+ *
+ * @author Matthew Khouzam
+ */
+public class ImportTraceWizardSelectTraceTypePage extends AbstractImportTraceWizardPage {
+
+ private CheckboxTreeViewer fTreeView;
+ private final TraceTypeContentProvider fProvider = new TraceTypeContentProvider();
+
+ /**
+ * Select trace types to import
+ *
+ * @param name
+ * The name of the page.
+ * @param selection
+ * The current selection
+ */
+ protected ImportTraceWizardSelectTraceTypePage(String name, IStructuredSelection selection) {
+ super(name, selection);
+ }
+
+ /**
+ * Select trace types to import
+ *
+ * @param workbench
+ * The workbench reference.
+ * @param selection
+ * The current selection
+ */
+ public ImportTraceWizardSelectTraceTypePage(IWorkbench workbench, IStructuredSelection selection) {
+ super(workbench, selection);
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ Composite control = (Composite) this.getControl();
+
+ final ICheckStateListener listener = new TraceTypeCheckListener();
+
+ setTitle(Messages.ImportTraceWizardSelectTraceTypePageTitle);
+
+ fTreeView = new CheckboxTreeViewer(control, SWT.BORDER);
+ fTreeView.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ fTreeView.setContentProvider(fProvider);
+ fTreeView.setInput(fProvider);
+ fTreeView.setLabelProvider(new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return element.toString();
+ }
+ });
+ fTreeView.addCheckStateListener(listener);
+
+ // populateTree(treeView);
+
+ Composite buttonArea = new Composite(control, SWT.NONE);
+ buttonArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ buttonArea.setLayout(new GridLayout(2, false));
+
+ Button selectAll = new Button(buttonArea, SWT.NONE);
+ selectAll.setText(Messages.ImportTraceWizardSelectAll);
+ selectAll.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
+ selectAll.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ String elements[] = (String[]) ((ITreeContentProvider) fTreeView.getContentProvider()).getElements(null);
+ for (String key : elements) {
+ fTreeView.setSubtreeChecked(key, true);
+ }
+ getWizard().getContainer().updateButtons();
+ }
+ });
+
+ Button selectNone = new Button(buttonArea, SWT.NONE);
+ selectNone.setText(Messages.ImportTraceWizardPageSelectNone);
+ selectNone.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
+ selectNone.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ String elements[] = (String[]) ((ITreeContentProvider) fTreeView.getContentProvider()).getElements(null);
+ for (String key : elements) {
+ fTreeView.setSubtreeChecked(key, false);
+ }
+ getWizard().getContainer().updateButtons();
+ }
+ });
+ fTreeView.expandAll();
+ }
+
+ @Override
+ public boolean canFlipToNextPage() {
+ List<String> tracesToScan = new ArrayList<>();
+ String elements[] = (String[]) fProvider.getElements(null);
+ for (String traceFamily : elements) {
+ final TraceTypeHelper[] children = (TraceTypeHelper[]) fProvider.getChildren(traceFamily);
+ if (children != null) {
+ for (TraceTypeHelper traceType : children) {
+ if (fTreeView.getChecked(traceType)) {
+ tracesToScan.add(traceType.getTraceTypeId());
+ }
+ }
+ }
+ }
+ ((BatchImportTraceWizard) getWizard()).setTraceTypesToScan(tracesToScan);
+ if (tracesToScan.isEmpty()) {
+ setErrorMessage(Messages.ImportTraceWizardPageSelectHint);
+ } else {
+ setErrorMessage(null);
+ }
+ return super.canFlipToNextPage() && !tracesToScan.isEmpty();
+ }
+
+ private final class TraceTypeCheckListener implements ICheckStateListener {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+
+ boolean checkStatus = event.getChecked();
+ Object element = event.getElement();
+
+ fTreeView.setGrayed(element, false);
+ fTreeView.setSubtreeChecked(element, checkStatus);
+ ITreeContentProvider tcp = (ITreeContentProvider) fTreeView.getContentProvider();
+ String parentElement = (String) tcp.getParent(element);
+ if (parentElement != null) {
+ TraceTypeHelper[] siblings = (TraceTypeHelper[]) tcp.getChildren(parentElement);
+ final TraceTypeHelper first = siblings[0];
+ final boolean isFirstChecked = fTreeView.getChecked(first);
+ boolean allSame = true;
+ for (TraceTypeHelper peer : siblings) {
+ final boolean peerChecked = fTreeView.getChecked(peer);
+ if (peerChecked != isFirstChecked) {
+ allSame = false;
+ }
+ }
+ if (allSame) {
+ fTreeView.setGrayed(parentElement, false);
+ fTreeView.setChecked(parentElement, checkStatus);
+ } else {
+ fTreeView.setChecked(parentElement, false);
+ fTreeView.setGrayed(parentElement, true);
+ }
+ }
+ getWizard().getContainer().updateButtons();
+
+ }
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/Messages.java
new file mode 100644
index 0000000000..db2cbb4e4c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/Messages.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ * Bernd Hufmann - Add ImportTraceWizard messages
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * The messages for import trace wizards.
+ * @author Matthew Khouzam
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.messages"; //$NON-NLS-1$
+
+ // Import Trace Wizard
+ /**
+ * The dialog title of the import trace wizard
+ */
+ public static String ImportTraceWizard_DialogTitle;
+ /**
+ * The title of the file system within the import trace wizard
+ */
+ public static String ImportTraceWizard_FileSystemTitle;
+ /**
+ * The title of the the import trace wizard page.
+ */
+ public static String ImportTraceWizard_ImportTrace;
+ /**
+ * The label of the directory location (import trace wizard)
+ */
+ public static String ImportTraceWizard_DirectoryLocation;
+ /**
+ * The label of the archive location (import trace wizard)
+ */
+ public static String ImportTraceWizard_ArchiveLocation;
+ /**
+ * The title of the select trace directory dialog (import trace wizard)
+ */
+ public static String ImportTraceWizard_SelectTraceDirectoryTitle;
+ /**
+ * The title of the select trace archive dialog (import trace wizard)
+ */
+ public static String ImportTraceWizard_SelectTraceArchiveTitle;
+ /**
+ * The message of the select trace directory dialog (import trace wizard)
+ */
+ public static String ImportTraceWizard_SelectTraceDirectoryMessage;
+ /**
+ * The title of the trace type label (import trace wizard)
+ */
+ public static String ImportTraceWizard_TraceType;
+ /**
+ * The label of the overwrite checkbox (import trace wizard)
+ */
+ public static String ImportTraceWizard_OverwriteExistingTrace;
+ /**
+ * The label of the checkbox to create a link to the trace in workspace (import trace wizard)
+ */
+ public static String ImportTraceWizard_CreateLinksInWorkspace;
+ /**
+ * The label of the checkbox to preserve the folder structure of selected the traces in workspace (import trace wizard)
+ */
+ public static String ImportTraceWizard_PreserveFolderStructure;
+ /**
+ * The error message for invalid trace directory (import trace wizard)
+ */
+ public static String ImportTraceWizard_InvalidTraceDirectory;
+ /**
+ * The error message when a trace validation failed (import trace wizard).
+ */
+ public static String ImportTraceWizard_TraceValidationFailed;
+ /**
+ * The error message when a trace already exists in project (import trace wizard).
+ */
+ public static String ImportTraceWizard_TraceAlreadyExists;
+ /**
+ * The title of rename button for import configuration dialog.
+ */
+ public static String ImportTraceWizard_ImportConfigurationRename;
+ /**
+ * The title of rename all button for import configuration dialog.
+ */
+ public static String ImportTraceWizard_ImportConfigurationRenameAll;
+ /**
+ * The title of overwrite button for import configuration dialog.
+ */
+ public static String ImportTraceWizard_ImportConfigurationOverwrite;
+ /**
+ * The title of overwrite all button for import configuration dialog.
+ */
+ public static String ImportTraceWizard_ImportConfigurationOverwriteAll;
+ /**
+ * The title of skip button for import configuration dialog.
+ */
+ public static String ImportTraceWizard_ImportConfigurationSkip;
+ /**
+ * The title of skip all button for import configuration dialog.
+ */
+ public static String ImportTraceWizard_ImportConfigurationSkipAll;
+ /**
+ * The error message when trace source is empty (import trace wizard).
+ */
+ public static String ImportTraceWizard_SelectTraceSourceEmpty;
+ /**
+ * The error message when the specified archive file is not valid.
+ */
+ public static String ImportTraceWizard_BadArchiveFormat;
+ /**
+ * The error message when no trace is selected (import trace wizard).
+ */
+ public static String ImportTraceWizard_SelectTraceNoneSelected;
+ /**
+ * The error message when an error occurred during import operation.
+ */
+ public static String ImportTraceWizard_ImportProblem;
+ /**
+ * The error message if destination directory is a virtual folder.
+ */
+ public static String ImportTraceWizard_CannotImportFilesUnderAVirtualFolder;
+ /**
+ * The error message if destination directory is a virtual folder (for a link).
+ */
+ public static String ImportTraceWizard_HaveToCreateLinksUnderAVirtualFolder;
+ /**
+ * The label string of the browse button.
+ */
+ public static String ImportTraceWizard_BrowseButton;
+ /**
+ * The information label string.
+ */
+ public static String ImportTraceWizard_Information;
+ /**
+ * The label of the checkbox to import unrecognized trace files
+ */
+ public static String ImportTraceWizard_ImportUnrecognized;
+ /**
+ * The message when the import operation was cancelled.
+ */
+ public static String ImportTraceWizard_ImportOperationCancelled;
+ /**
+ * The message when the trace type is not found.
+ */
+ public static String ImportTraceWizard_TraceTypeNotFound;
+ /**
+ * The import operation task name.
+ */
+ public static String ImportTraceWizard_ImportOperationTaskName;
+ /**
+ * The extract import operation task name
+ */
+ public static String ImportTraceWizard_ExtractImportOperationTaskName;
+ /**
+ * The label to indicate that trace type auto detection shall be used.
+ */
+ public static String ImportTraceWizard_AutoDetection;
+
+
+ // Batch Import Wizard
+ public static String ImportTraceWizardImportProblem ;
+ public static String ImportTraceWizardImportCaption;
+ public static String ImportTraceWizardTraceDisplayName;
+ public static String ImportTraceWizardLinkTraces;
+ public static String ImportTraceWizardCopyTraces;
+ public static String ImportTraceWizardOverwriteTraces;
+ public static String ImportTraceWizardAddFile;
+ public static String ImportTraceWizardAddDirectory;
+ public static String ImportTraceWizardRemove;
+ public static String ImportTraceWizardDirectoryTitle;
+ public static String ImportTraceWizardDirectoryHint;
+ public static String ImportTraceWizardScanPagebyte;
+
+ public static String ImportTraceWizardScanPageGigabyte;
+
+ public static String ImportTraceWizardScanPageKilobyte;
+
+ public static String ImportTraceWizardScanPageMegabyte;
+
+ public static String ImportTraceWizardScanPageRenameError;
+ public static String ImportTraceWizardScanPageSelectAtleastOne;
+
+ public static String ImportTraceWizardScanPageSize;
+ public static String ImportTraceWizardSelectAll;
+ public static String ImportTraceWizardScanPageTerabyte;
+
+ public static String ImportTraceWizardScanPageTitle;
+ public static String ImportTraceWizardSelectTraceTypePageTitle;
+ public static String ImportTraceWizardPageOptionsTitle;
+ public static String ImportTraceWizardPageScanDone;
+ public static String ImportTraceWizardPageScanScanning;
+ public static String ImportTraceWizardPageSelectNone;
+ public static String ImportTraceWizardPageSelectHint;
+ public static String BatchImportTraceWizardRemove;
+ public static String BatchImportTraceWizardAdd;
+ public static String BatchImportTraceWizardErrorImportingTraceResource;
+
+ public static String SharedSelectProject;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceTypeContentProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceTypeContentProvider.java
new file mode 100644
index 0000000000..a79c1cbce8
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceTypeContentProvider.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+
+/**
+ * Trace type content provider, a helper for showing trace types
+ *
+ * @author Matthew Khouzam
+ */
+public class TraceTypeContentProvider implements ITreeContentProvider {
+
+ private final List<String> fTraceCategory = new ArrayList<>();
+ private final Map<String, List<TraceTypeHelper>> fTraceType = new HashMap<>();
+
+ /**
+ * Default Constructor
+ */
+ public TraceTypeContentProvider() {
+ fTraceType.clear();
+ fTraceCategory.clear();
+
+ for (String category : TmfTraceType.getTraceCategories()) {
+ List<TraceTypeHelper> value = TmfTraceType.getTraceTypes(category);
+ if (!value.isEmpty()) {
+ fTraceCategory.add(category);
+ fTraceType.put(category, value);
+ }
+ }
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // Do nothing
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return fTraceCategory.toArray(new String[0]);
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof String) {
+ final List<TraceTypeHelper> children = fTraceType.get(parentElement);
+ if (children != null) {
+ return children.toArray(new TraceTypeHelper[0]);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element instanceof TraceTypeHelper) {
+ for (String key : fTraceCategory) {
+ List<TraceTypeHelper> traceSet = fTraceType.get(key);
+ if (traceSet != null) {
+ if (traceSet.contains(element)) {
+ return key;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ if (element instanceof String) {
+ String key = (String) element;
+ return fTraceType.containsKey(key);
+ }
+ return false;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/messages.properties
new file mode 100644
index 0000000000..f3fdaf8e0c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/messages.properties
@@ -0,0 +1,81 @@
+###############################################################################
+# Copyright (c) 2013, 2014 Ericsson
+#
+# 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:
+# Ericsson - Initial API and implementation
+###############################################################################
+
+# ImportTraceWizard
+ImportTraceWizard_DialogTitle=Trace Import
+ImportTraceWizard_FileSystemTitle=File system
+ImportTraceWizard_ImportTrace=Import a trace from the local file system
+ImportTraceWizard_DirectoryLocation=Select roo&t directory:
+ImportTraceWizard_ArchiveLocation=Select &archive file:
+ImportTraceWizard_BrowseButton=B&rowse...
+ImportTraceWizard_TraceType=Trace Type:
+ImportTraceWizard_SelectTraceDirectoryTitle=Select trace directory
+ImportTraceWizard_SelectTraceArchiveTitle=Select trace archive file
+ImportTraceWizard_SelectTraceDirectoryMessage=Select directory to import trace from
+ImportTraceWizard_OverwriteExistingTrace=Overwrite existing trace without warning
+ImportTraceWizard_CreateLinksInWorkspace=Create lin&ks in workspace
+ImportTraceWizard_PreserveFolderStructure=Preserve &folder structure
+ImportTraceWizard_TraceValidationFailed=Validation failed for trace resource {0}
+ImportTraceWizard_TraceAlreadyExists=Trace with name "{0}" already exists in project. Do you want to rename, overwrite or skip?
+ImportTraceWizard_ImportConfigurationRename=Rename
+ImportTraceWizard_ImportConfigurationRenameAll=Rename All
+ImportTraceWizard_ImportConfigurationOverwrite=Overwrite
+ImportTraceWizard_ImportConfigurationOverwriteAll=Overwrite All
+ImportTraceWizard_ImportConfigurationSkip=Skip
+ImportTraceWizard_ImportConfigurationSkipAll=Skip All
+ImportTraceWizard_InvalidTraceDirectory=Invalid trace directory
+ImportTraceWizard_SelectTraceSourceEmpty=Source must not be empty
+ImportTraceWizard_BadArchiveFormat=Source file is not a valid tar or zip file.
+ImportTraceWizard_SelectTraceNoneSelected=No trace selected
+ImportTraceWizard_ImportProblem=Import problem
+ImportTraceWizard_CannotImportFilesUnderAVirtualFolder=Can not import trace under a virtual folder
+ImportTraceWizard_HaveToCreateLinksUnderAVirtualFolder=Have to create link under a virtual folder
+ImportTraceWizard_Information=Information
+ImportTraceWizard_ImportUnrecognized=Import unrecognized traces
+ImportTraceWizard_ImportOperationCancelled=Import operation cancelled
+ImportTraceWizard_TraceTypeNotFound=No trace type helper found
+ImportTraceWizard_ImportOperationTaskName=Importing
+ImportTraceWizard_ExtractImportOperationTaskName=Extracting files
+ImportTraceWizard_AutoDetection=<Automatic Detection>
+
+# BatchImportTraceWizard
+ImportTraceWizardImportCaption=Trace to import
+ImportTraceWizardTraceDisplayName=Trace display name
+ImportTraceWizardLinkTraces=Link traces (Recommended)
+ImportTraceWizardCopyTraces=Copy traces
+ImportTraceWizardOverwriteTraces=Overwrite existing traces (recommended)
+ImportTraceWizardAddFile=Add File...
+ImportTraceWizardAddDirectory=Add Directory...
+ImportTraceWizardRemove=Remove
+ImportTraceWizardDirectoryTitle=Pick directories and files to scan
+ImportTraceWizardDirectoryHint=Select at least one file or directory to scan
+ImportTraceWizardScanPagebyte=\ B
+ImportTraceWizardScanPageGigabyte=\ GB
+ImportTraceWizardScanPageKilobyte=\ KB
+ImportTraceWizardScanPageMegabyte=\ MB
+ImportTraceWizardScanPageRenameError=Each selected trace must have a unique name, please rename.
+ImportTraceWizardScanPageSelectAtleastOne=Select at least one trace to import
+ImportTraceWizardScanPageSize=Size
+ImportTraceWizardSelectAll=Select All
+ImportTraceWizardScanPageTerabyte=\ TB
+ImportTraceWizardScanPageTitle=Valid traces
+ImportTraceWizardSelectTraceTypePageTitle=Available trace types
+ImportTraceWizardPageOptionsTitle=Select Target Project
+ImportTraceWizardPageScanDone=Done\!
+ImportTraceWizardPageScanScanning=Scanning:
+ImportTraceWizardPageSelectNone=Deselect All
+ImportTraceWizardPageSelectHint=Select at least one trace type
+BatchImportTraceWizardRemove=Removing
+BatchImportTraceWizardAdd=Adding
+BatchImportTraceWizardErrorImportingTraceResource=Error importing trace resource
+ImportTraceWizardImportProblem=Error
+SharedSelectProject=Select a project to import to
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageOperation.java
new file mode 100644
index 0000000000..c3585f31ff
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageOperation.java
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ui.internal.wizards.datatransfer.TarEntry;
+import org.eclipse.ui.internal.wizards.datatransfer.TarException;
+import org.eclipse.ui.internal.wizards.datatransfer.TarFile;
+
+/**
+ * An abstract operation containing common code useful for other trace package
+ * operations
+ *
+ * @author Marc-Andre Laperle
+ */
+@SuppressWarnings("restriction")
+public abstract class AbstractTracePackageOperation {
+ private IStatus fStatus;
+ // Result of this operation, if any
+ private TracePackageElement[] fResultElements;
+
+ private final String fFileName;
+
+ /**
+ * Constructs a new trace package operation
+ *
+ * @param fileName
+ * the output file name
+ */
+ public AbstractTracePackageOperation(String fileName) {
+ fFileName = fileName;
+ }
+
+ /**
+ * Run the operation. The status (result) of the operation can be obtained
+ * with {@link #getStatus}
+ *
+ * @param progressMonitor
+ * the progress monitor to use to display progress and receive
+ * requests for cancellation
+ */
+ public abstract void run(IProgressMonitor progressMonitor);
+
+ /**
+ * Returns the status of the operation (result)
+ *
+ * @return the status of the operation
+ */
+ public IStatus getStatus() {
+ return fStatus;
+ }
+
+ /**
+ * Get the resulting elements for this operation, if any
+ *
+ * @return the resulting elements or null if no result is produced by this
+ * operation
+ */
+ public TracePackageElement[] getResultElements() {
+ return fResultElements;
+ }
+
+ /**
+ * Set the resulting elements for this operation, if any
+ *
+ * @param elements
+ * the resulting elements produced by this operation, can be set
+ * to null
+ */
+ public void setResultElements(TracePackageElement[] elements) {
+ fResultElements = elements;
+ }
+
+ /**
+ * Set the status for this operation
+ *
+ * @param status
+ * the status
+ */
+ protected void setStatus(IStatus status) {
+ fStatus = status;
+ }
+
+ /**
+ * Get the file name of the package
+ *
+ * @return the file name
+ */
+ protected String getFileName() {
+ return fFileName;
+ }
+
+ /**
+ * Answer a handle to the archive file currently specified as being the
+ * source. Return null if this file does not exist or is not of valid
+ * format.
+ *
+ * @return the archive file
+ */
+ public ArchiveFile getSpecifiedArchiveFile() {
+ if (fFileName.length() == 0) {
+ return null;
+ }
+
+ try {
+ return new ZipArchiveFile(new ZipFile(fFileName));
+ } catch (IOException e) {
+ // ignore
+ }
+
+ try {
+ return new TarArchiveFile(new TarFile(fFileName));
+ } catch (TarException | IOException e) {
+ // ignore
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the number of checked elements in the array and the children
+ *
+ * @param elements
+ * the elements to check for checked
+ * @return the number of checked elements
+ */
+ protected int getNbCheckedElements(TracePackageElement[] elements) {
+ int totalWork = 0;
+ for (TracePackageElement tracePackageElement : elements) {
+ TracePackageElement[] children = tracePackageElement.getChildren();
+ if (children != null && children.length > 0) {
+ totalWork += getNbCheckedElements(children);
+ } else if (tracePackageElement.isChecked()) {
+ ++totalWork;
+ }
+ }
+
+ return totalWork;
+ }
+
+ /**
+ * Returns whether or not the Files element is checked under the given trace
+ * package element
+ *
+ * @param tracePackageElement
+ * the trace package element
+ * @return whether or not the Files element is checked under the given trace
+ * package element
+ */
+ public static boolean isFilesChecked(TracePackageElement tracePackageElement) {
+ for (TracePackageElement element : tracePackageElement.getChildren()) {
+ if (element instanceof TracePackageFilesElement) {
+ return element.isChecked();
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Common interface between ZipEntry and TarEntry
+ */
+ protected interface ArchiveEntry {
+ /**
+ * The name of the entry
+ *
+ * @return The name of the entry
+ */
+ String getName();
+ }
+
+ /**
+ * Common interface between ZipFile and TarFile
+ */
+ protected interface ArchiveFile {
+ /**
+ * Returns an enumeration cataloging the archive.
+ *
+ * @return enumeration of all files in the archive
+ */
+ Enumeration<? extends ArchiveEntry> entries();
+
+ /**
+ * Close the file input stream.
+ *
+ * @throws IOException
+ */
+ void close() throws IOException;
+
+ /**
+ * Returns a new InputStream for the given file in the archive.
+ *
+ * @param entry
+ * the given file
+ * @return an input stream for the given file
+ * @throws TarException
+ * @throws IOException
+ */
+ InputStream getInputStream(ArchiveEntry entry) throws TarException, IOException;
+ }
+
+ /**
+ * Adapter for TarFile to ArchiveFile
+ */
+ protected class TarArchiveFile implements ArchiveFile {
+
+ private TarFile fTarFile;
+
+ /**
+ * Constructs a TarAchiveFile for a TarFile
+ *
+ * @param tarFile
+ * the TarFile
+ */
+ public TarArchiveFile(TarFile tarFile) {
+ this.fTarFile = tarFile;
+ }
+
+ @Override
+ public Enumeration<? extends ArchiveEntry> entries() {
+ Vector<ArchiveEntry> v = new Vector<>();
+ for (Enumeration<?> e = fTarFile.entries(); e.hasMoreElements();) {
+ v.add(new TarArchiveEntry((TarEntry) e.nextElement()));
+ }
+
+ return v.elements();
+ }
+
+ @Override
+ public void close() throws IOException {
+ fTarFile.close();
+ }
+
+ @Override
+ public InputStream getInputStream(ArchiveEntry entry) throws TarException, IOException {
+ return fTarFile.getInputStream(((TarArchiveEntry) entry).getTarEntry());
+ }
+ }
+
+ /**
+ * Adapter for TarEntry to ArchiveEntry
+ */
+ protected class TarArchiveEntry implements ArchiveEntry {
+ private TarEntry fTarEntry;
+
+ /**
+ * Constructs a TarArchiveEntry for a TarEntry
+ *
+ * @param tarEntry
+ * the TarEntry
+ */
+ public TarArchiveEntry(TarEntry tarEntry) {
+ this.fTarEntry = tarEntry;
+ }
+
+ @Override
+ public String getName() {
+ return fTarEntry.getName();
+ }
+
+ /**
+ * Get the corresponding TarEntry
+ *
+ * @return the corresponding TarEntry
+ */
+ public TarEntry getTarEntry() {
+ return fTarEntry;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+ }
+
+ /**
+ * Adapter for ArchiveEntry to ArchiveEntry
+ */
+ protected class ZipAchiveEntry implements ArchiveEntry {
+
+ private ZipEntry fZipEntry;
+
+ /**
+ * Constructs a ZipAchiveEntry for a ZipEntry
+ *
+ * @param zipEntry
+ * the ZipEntry
+ */
+ public ZipAchiveEntry(ZipEntry zipEntry) {
+ this.fZipEntry = zipEntry;
+ }
+
+ @Override
+ public String getName() {
+ return fZipEntry.getName();
+ }
+
+ /**
+ * Get the corresponding ZipEntry
+ *
+ * @return the corresponding ZipEntry
+ */
+ public ZipEntry getZipEntry() {
+ return fZipEntry;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+ }
+
+ /**
+ * Adapter for ZipFile to ArchiveFile
+ */
+ protected class ZipArchiveFile implements ArchiveFile {
+
+ private ZipFile fZipFile;
+
+ /**
+ * Constructs a ZipArchiveFile for a ZipFile
+ *
+ * @param zipFile
+ * the ZipFile
+ */
+ public ZipArchiveFile(ZipFile zipFile) {
+ this.fZipFile = zipFile;
+ }
+
+ @Override
+ public Enumeration<? extends ArchiveEntry> entries() {
+ Vector<ArchiveEntry> v = new Vector<>();
+ for (Enumeration<?> e = fZipFile.entries(); e.hasMoreElements();) {
+ v.add(new ZipAchiveEntry((ZipEntry) e.nextElement()));
+ }
+
+ return v.elements();
+ }
+
+ @Override
+ public void close() throws IOException {
+ fZipFile.close();
+ }
+
+ @Override
+ public InputStream getInputStream(ArchiveEntry entry) throws TarException, IOException {
+ return fZipFile.getInputStream(((ZipAchiveEntry) entry).getZipEntry());
+ }
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageWizardPage.java
new file mode 100644
index 0000000000..b8aa56bc3c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageWizardPage.java
@@ -0,0 +1,570 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+
+/**
+ * An abstract wizard page containing common code useful for both import and
+ * export trace package wizard pages
+ *
+ * @author Marc-Andre Laperle
+ */
+public abstract class AbstractTracePackageWizardPage extends WizardPage {
+
+ private static final int COMBO_HISTORY_LENGTH = 5;
+ private static final String STORE_FILE_PATHS_ID = ".STORE_FILEPATHS_ID"; //$NON-NLS-1$
+
+ private final String fStoreFilePathId;
+ private final IStructuredSelection fSelection;
+
+ private CheckboxTreeViewer fElementViewer;
+ private Button fSelectAllButton;
+ private Button fDeselectAllButton;
+ private Combo fFilePathCombo;
+ private Button fBrowseButton;
+
+ /**
+ * Create the trace package wizard page
+ *
+ * @param pageName
+ * the name of the page
+ * @param title
+ * the title for this wizard page, or null if none
+ * @param titleImage
+ * the image descriptor for the title of this wizard page, or
+ * null if none
+ * @param selection
+ * the current object selection
+ */
+ protected AbstractTracePackageWizardPage(String pageName, String title, ImageDescriptor titleImage, IStructuredSelection selection) {
+ super(pageName, title, titleImage);
+ fStoreFilePathId = getName() + STORE_FILE_PATHS_ID;
+ fSelection = selection;
+ }
+
+ /**
+ * Create the element viewer
+ *
+ * @param compositeParent
+ * the parent composite
+ */
+ protected void createElementViewer(Composite compositeParent) {
+ fElementViewer = new CheckboxTreeViewer(compositeParent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.CHECK);
+
+ fElementViewer.addCheckStateListener(new ICheckStateListener() {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ TracePackageElement element = (TracePackageElement) event.getElement();
+ if (!element.isEnabled()) {
+ fElementViewer.setChecked(element, element.isChecked());
+ } else {
+ setSubtreeChecked(fElementViewer, element, true, event.getChecked());
+ }
+ maintainCheckIntegrity(element);
+
+ if (element.getParent() != null) {
+ // Uncheck everything in this trace if Trace files are unchecked
+ if (element instanceof TracePackageFilesElement) {
+ if (!element.isChecked()) {
+ setSubtreeChecked(fElementViewer, element.getParent(), false, false);
+ }
+ // Check Trace files if anything else is selected
+ } else if (element.isChecked()) {
+ TracePackageElement parent = element.getParent();
+ while (parent != null) {
+ for (TracePackageElement e : parent.getChildren()) {
+ if (e instanceof TracePackageFilesElement) {
+ setSubtreeChecked(fElementViewer, e, false, true);
+ break;
+ }
+ }
+ parent = parent.getParent();
+ }
+ }
+ }
+
+
+ updateApproximateSelectedSize();
+ updatePageCompletion();
+ }
+
+ private void maintainCheckIntegrity(final TracePackageElement element) {
+ TracePackageElement parentElement = element.getParent();
+ boolean allChecked = true;
+ boolean oneChecked = false;
+ if (parentElement != null) {
+ if (parentElement.getChildren() != null) {
+ for (TracePackageElement child : parentElement.getChildren()) {
+ if (fElementViewer.getGrayed(child)) {
+ oneChecked = true;
+ allChecked = false;
+ break;
+ }
+ boolean checked = fElementViewer.getChecked(child);
+ oneChecked |= checked;
+ allChecked &= checked;
+ }
+ }
+ if (oneChecked && !allChecked) {
+ fElementViewer.setGrayChecked(parentElement, true);
+ } else {
+ fElementViewer.setGrayed(parentElement, false);
+ fElementViewer.setChecked(parentElement, allChecked);
+ }
+ maintainCheckIntegrity(parentElement);
+ }
+ }
+ });
+ GridData layoutData = new GridData(GridData.FILL_BOTH);
+ fElementViewer.getTree().setLayoutData(layoutData);
+ fElementViewer.setContentProvider(new TracePackageContentProvider());
+ fElementViewer.setLabelProvider(new TracePackageLabelProvider());
+ }
+
+ /**
+ * Create the input for the element viewer
+ *
+ * @return the input for the element viewer
+ */
+ protected abstract Object createElementViewerInput();
+
+ /**
+ * Create the file path group that allows the user to type or browse for a
+ * file path
+ *
+ * @param parent
+ * the parent composite
+ * @param label
+ * the label to describe the file path (i.e. import/export)
+ * @param fileDialogStyle
+ * SWT.OPEN or SWT.SAVE
+ */
+ protected void createFilePathGroup(Composite parent, String label, final int fileDialogStyle) {
+
+ Composite filePathSelectionGroup = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ filePathSelectionGroup.setLayout(layout);
+ filePathSelectionGroup.setLayoutData(new GridData(
+ GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+
+ Label destinationLabel = new Label(filePathSelectionGroup, SWT.NONE);
+ destinationLabel.setText(label);
+
+ fFilePathCombo = new Combo(filePathSelectionGroup, SWT.SINGLE
+ | SWT.BORDER);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.GRAB_HORIZONTAL);
+ data.grabExcessHorizontalSpace = true;
+ fFilePathCombo.setLayoutData(data);
+
+ fBrowseButton = new Button(filePathSelectionGroup,
+ SWT.PUSH);
+ fBrowseButton.setText(org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_Browse);
+ fBrowseButton.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ handleFilePathBrowseButtonPressed(fileDialogStyle);
+ }
+ });
+ setButtonLayoutData(fBrowseButton);
+ }
+
+ /**
+ * Update the page with the file path the current file path selection
+ */
+ protected abstract void updateWithFilePathSelection();
+
+ /**
+ * Creates the buttons for selecting all or none of the elements.
+ *
+ * @param parent
+ * the parent control
+ * @return the button group
+ */
+ protected Composite createButtonsGroup(Composite parent) {
+
+ // top level group
+ Composite buttonComposite = new Composite(parent, SWT.NONE);
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ buttonComposite.setLayout(layout);
+ buttonComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
+ | GridData.HORIZONTAL_ALIGN_FILL));
+
+ fSelectAllButton = new Button(buttonComposite, SWT.PUSH);
+ fSelectAllButton.setText(org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_SelectAll);
+
+ SelectionListener listener = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setAllChecked(fElementViewer, true, true);
+ updateApproximateSelectedSize();
+ updatePageCompletion();
+ }
+ };
+ fSelectAllButton.addSelectionListener(listener);
+
+ fDeselectAllButton = new Button(buttonComposite, SWT.PUSH);
+ fDeselectAllButton.setText(org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_DeselectAll);
+
+ listener = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setAllChecked(fElementViewer, true, false);
+ updateApproximateSelectedSize();
+ updatePageCompletion();
+ }
+ };
+ fDeselectAllButton.addSelectionListener(listener);
+
+ return buttonComposite;
+ }
+
+ /**
+ * Restore widget values to the values that they held last time this wizard
+ * was used to completion.
+ */
+ protected void restoreWidgetValues() {
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ String[] directoryNames = settings.getArray(fStoreFilePathId);
+ if (directoryNames == null || directoryNames.length == 0) {
+ return;
+ }
+
+ for (int i = 0; i < directoryNames.length; i++) {
+ fFilePathCombo.add(directoryNames[i]);
+ }
+ }
+ }
+
+ /**
+ * Save widget values to Dialog settings
+ */
+ protected void saveWidgetValues() {
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ // update directory names history
+ String[] directoryNames = settings.getArray(fStoreFilePathId);
+ if (directoryNames == null) {
+ directoryNames = new String[0];
+ }
+
+ directoryNames = addToHistory(directoryNames, getFilePathValue());
+ settings.put(fStoreFilePathId, directoryNames);
+ }
+ }
+
+ /**
+ * Determine if the page is complete and update the page appropriately.
+ */
+ protected void updatePageCompletion() {
+ boolean pageComplete = determinePageCompletion();
+ setPageComplete(pageComplete);
+ if (pageComplete) {
+ setErrorMessage(null);
+ }
+ }
+
+ /**
+ * Determine if the page is completed or not
+ *
+ * @return true if the page is completed, false otherwise
+ */
+ protected boolean determinePageCompletion() {
+ return fElementViewer.getCheckedElements().length > 0 && !getFilePathValue().isEmpty();
+ }
+
+ /**
+ * Handle error status
+ *
+ * @param status
+ * the error status
+ */
+ protected void handleErrorStatus(IStatus status) {
+
+ Throwable exception = status.getException();
+ String message = status.getMessage().length() > 0 ? status.getMessage() : org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation;
+
+ if (!status.isMultiStatus()) {
+ handleError(message, exception);
+ return;
+ }
+
+ // Build a string with all the children status messages, exception
+ // messages and stack traces
+ StringBuilder sb = new StringBuilder();
+ for (IStatus childStatus : status.getChildren()) {
+ StringBuilder childSb = new StringBuilder();
+ if (!childStatus.getMessage().isEmpty()) {
+ childSb.append(childStatus.getMessage() + '\n');
+ }
+
+ Throwable childException = childStatus.getException();
+ if (childException != null) {
+ String reason = childException.getMessage();
+ // Some system exceptions have no message
+ if (reason == null) {
+ reason = childException.toString();
+ }
+
+ String stackMessage = getExceptionStackMessage(childException);
+ if (stackMessage == null) {
+ stackMessage = reason;
+ }
+
+ childSb.append(stackMessage);
+ }
+
+ if (childSb.length() > 0) {
+ childSb.insert(0, '\n');
+ sb.append(childSb.toString());
+ }
+ }
+
+ // ErrorDialog only prints the call stack for a CoreException
+ exception = new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, sb.toString(), null));
+ final Status statusWithException = new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorMultipleProblems, exception);
+
+ Activator.getDefault().logError(message, exception);
+ ErrorDialog.openError(getContainer().getShell(), org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_InternalErrorTitle, message, statusWithException);
+ }
+
+ /**
+ * Handle errors occurring in the wizard operations
+ *
+ * @param message
+ * the error message
+ * @param exception
+ * the exception attached to the message
+ */
+ protected void handleError(String message, Throwable exception) {
+ Activator.getDefault().logError(message, exception);
+ displayErrorDialog(message, exception);
+ }
+
+ private static String getExceptionStackMessage(Throwable exception) {
+ String stackMessage = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ exception.printStackTrace(ps);
+ ps.flush();
+ try {
+ baos.flush();
+ stackMessage = baos.toString();
+ } catch (IOException e) {
+ }
+
+ return stackMessage;
+ }
+
+ private void displayErrorDialog(String message, Throwable exception) {
+ if (exception == null) {
+ final Status s = new Status(IStatus.ERROR, Activator.PLUGIN_ID, message);
+ ErrorDialog.openError(getContainer().getShell(), org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_InternalErrorTitle, null, s);
+ return;
+ }
+
+ String reason = exception.getMessage();
+ // Some system exceptions have no message
+ if (reason == null) {
+ reason = exception.toString();
+ }
+
+ String stackMessage = getExceptionStackMessage(exception);
+ if (stackMessage == null || stackMessage.isEmpty()) {
+ stackMessage = reason;
+ }
+
+ // ErrorDialog only prints the call stack for a CoreException
+ CoreException coreException = new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, stackMessage, exception));
+ final Status s = new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, reason, coreException);
+ ErrorDialog.openError(getContainer().getShell(), org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_InternalErrorTitle, message, s);
+ }
+
+ /**
+ * A version of setSubtreeChecked that is aware of isEnabled
+ *
+ * @param viewer
+ * the viewer
+ * @param element
+ * the element
+ * @param enabledOnly
+ * if only enabled elements should be considered
+ * @param checked
+ * true if the item should be checked, and false if it should be
+ * unchecked
+ */
+ protected static void setSubtreeChecked(CheckboxTreeViewer viewer, TracePackageElement element, boolean enabledOnly, boolean checked) {
+ if (!enabledOnly || element.isEnabled()) {
+ viewer.setChecked(element, checked);
+ if (checked) {
+ viewer.setGrayed(element, false);
+ }
+ element.setChecked(checked);
+ if (element.getChildren() != null) {
+ for (TracePackageElement child : element.getChildren()) {
+ setSubtreeChecked(viewer, child, enabledOnly, checked);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets all items in the element viewer to be checked or unchecked
+ *
+ * @param viewer
+ * the viewer
+ * @param enabledOnly
+ * if only enabled elements should be considered
+ * @param checked
+ * whether or not items should be checked
+ */
+ protected static void setAllChecked(CheckboxTreeViewer viewer, boolean enabledOnly, boolean checked) {
+ TreeItem[] items = viewer.getTree().getItems();
+ for (int i = 0; i < items.length; i++) {
+ Object element = items[i].getData();
+ setSubtreeChecked(viewer, (TracePackageElement) element, enabledOnly, checked);
+ }
+ }
+
+ private static void addToHistory(List<String> history, String newEntry) {
+ history.remove(newEntry);
+ history.add(0, newEntry);
+
+ // since only one new item was added, we can be over the limit
+ // by at most one item
+ if (history.size() > COMBO_HISTORY_LENGTH) {
+ history.remove(COMBO_HISTORY_LENGTH);
+ }
+ }
+
+ private static String[] addToHistory(String[] history, String newEntry) {
+ ArrayList<String> l = new ArrayList<>(Arrays.asList(history));
+ addToHistory(l, newEntry);
+ String[] r = new String[l.size()];
+ l.toArray(r);
+ return r;
+ }
+
+ /**
+ * Open an appropriate file dialog so that the user can specify a file to
+ * import/export
+ * @param fileDialogStyle
+ */
+ private void handleFilePathBrowseButtonPressed(int fileDialogStyle) {
+ FileDialog dialog = new FileDialog(getContainer().getShell(), fileDialogStyle | SWT.SHEET);
+ dialog.setFilterExtensions(new String[] { "*.zip;*.tar.gz;*.tar;*.tgz", "*.*" }); //$NON-NLS-1$ //$NON-NLS-2$
+ dialog.setText(Messages.TracePackage_FileDialogTitle);
+ String currentSourceString = getFilePathValue();
+ int lastSeparatorIndex = currentSourceString.lastIndexOf(File.separator);
+ if (lastSeparatorIndex != -1) {
+ dialog.setFilterPath(currentSourceString.substring(0, lastSeparatorIndex));
+ }
+ String selectedFileName = dialog.open();
+
+ if (selectedFileName != null) {
+ setFilePathValue(selectedFileName);
+ updateWithFilePathSelection();
+ }
+ }
+
+ /**
+ * Get the current file path value
+ *
+ * @return the current file path value
+ */
+ protected String getFilePathValue() {
+ return fFilePathCombo.getText().trim();
+ }
+
+ /**
+ * Set the file path value
+ *
+ * @param value
+ * file path value
+ */
+ protected void setFilePathValue(String value) {
+ fFilePathCombo.setText(value);
+ updatePageCompletion();
+ }
+
+ /**
+ * Update the approximate size of the selected elements
+ */
+ protected void updateApproximateSelectedSize() {
+ }
+
+ /**
+ * Get the element tree viewer
+ *
+ * @return the element tree viewer
+ */
+ protected CheckboxTreeViewer getElementViewer() {
+ return fElementViewer;
+ }
+
+ /**
+ * Get the file path combo box
+ *
+ * @return the file path combo box
+ */
+ protected Combo getFilePathCombo() {
+ return fFilePathCombo;
+ }
+
+ /**
+ * Get the object selection when the wizard was created
+ *
+ * @return the object selection
+ */
+ protected IStructuredSelection getSelection() {
+ return fSelection;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/ITracePackageConstants.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/ITracePackageConstants.java
new file mode 100644
index 0000000000..f7458455fe
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/ITracePackageConstants.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+/**
+ * Constants used in the trace package (XML attribute and element names, etc).
+ *
+ * @author Marc-Andre Laperle
+ */
+public interface ITracePackageConstants {
+
+ /**
+ * The file name for the package manifest file
+ */
+ public static final String MANIFEST_FILENAME = "export-manifest.xml"; //$NON-NLS-1$
+
+ /**
+ * The root element of an export
+ */
+ public static final String TMF_EXPORT_ELEMENT = "tmf-export"; //$NON-NLS-1$
+
+ /**
+ * Element representing a single trace
+ */
+ public static final String TRACE_ELEMENT = "trace"; //$NON-NLS-1$
+
+ /**
+ * Attribute for the name of a trace
+ */
+ public static final String TRACE_NAME_ATTRIB = "name"; //$NON-NLS-1$
+
+ /**
+ * Attribute for the type of a trace
+ */
+ public static final String TRACE_TYPE_ATTRIB = "type"; //$NON-NLS-1$
+
+ /**
+ * Element representing a single supplementary file
+ */
+ public static final String SUPPLEMENTARY_FILE_ELEMENT = "supplementary-file"; //$NON-NLS-1$
+
+ /**
+ * Attribute for the name of a supplementary file
+ */
+ public static final String SUPPLEMENTARY_FILE_NAME_ATTRIB = "name"; //$NON-NLS-1$
+
+ /**
+ * Element representing a trace file or folder
+ */
+ public static final String TRACE_FILE_ELEMENT = "file"; //$NON-NLS-1$
+
+ /**
+ * Attribute for the name of the file
+ */
+ public static final String TRACE_FILE_NAME_ATTRIB = "name"; //$NON-NLS-1$
+
+ /**
+ * Element representing the bookmarks of a trace
+ */
+ public static final String BOOKMARKS_ELEMENT = "bookmarks"; //$NON-NLS-1$
+
+ /**
+ * Element representing a single bookmark of a trace
+ */
+ public static final String BOOKMARK_ELEMENT = "bookmark"; //$NON-NLS-1$
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/Messages.java
new file mode 100644
index 0000000000..06f49daaf5
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/Messages.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages common to trace package operations
+ *
+ * @author Marc-Andre Laperle
+ */
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.messages"; //$NON-NLS-1$
+
+ /**
+ * Text for supplementary files in the element viewer
+ */
+ public static String TracePackage_SupplementaryFiles;
+
+ /**
+ * Text for trace in the element viewer
+ */
+ public static String TracePackage_TraceElement;
+
+ /**
+ * Text for bookmarks in the element viewer
+ */
+ public static String TracePackage_Bookmarks;
+
+ /**
+ * Text for browse button in the wizard pages
+ */
+ public static String TracePackage_Browse;
+
+ /**
+ * Title for the file dialog
+ */
+ public static String TracePackage_FileDialogTitle;
+
+ /**
+ * Text for browse select all button in the wizard pages
+ */
+ public static String TracePackage_SelectAll;
+
+ /**
+ * Text for browse deselect all button in the wizard pages
+ */
+ public static String TracePackage_DeselectAll;
+
+ /**
+ * Generic error message for wizard operations
+ */
+ public static String TracePackage_ErrorOperation;
+
+ /**
+ * Generic error when multiple problems occur (MultiStatus)
+ */
+ public static String TracePackage_ErrorMultipleProblems;
+
+ /**
+ * Generic dialog message for error in wizard operations
+ */
+ public static String TracePackage_InternalErrorTitle;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageBookmarkElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageBookmarkElement.java
new file mode 100644
index 0000000000..06d6651604
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageBookmarkElement.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+
+/**
+ * A trace package element representing the bookmarks of a trace
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageBookmarkElement extends TracePackageElement {
+ private static final String BOOKMARK_IMAGE_PATH = "icons/elcl16/bookmark_obj.gif"; //$NON-NLS-1$
+ private final List<Map<String, String>> bookmarkAttribs;
+
+ /**
+ * Construct a bookmark element containing all the bookmarks
+ *
+ * @param parent
+ * the parent node
+ * @param bookmarkAttribs
+ * the bookmarks for the trace
+ */
+ public TracePackageBookmarkElement(TracePackageElement parent, List<Map<String, String>> bookmarkAttribs) {
+ super(parent);
+ this.bookmarkAttribs = bookmarkAttribs;
+ }
+
+ @Override
+ public long getSize(boolean checkedOnly) {
+ return 0;
+ }
+
+ @Override
+ public String getText() {
+ return Messages.TracePackage_Bookmarks;
+ }
+
+ @Override
+ public Image getImage() {
+ return Activator.getDefault().getImageFromImageRegistry(BOOKMARK_IMAGE_PATH);
+ }
+
+ /**
+ * Get all the bookmarks
+ *
+ * @return the bookmarks
+ */
+ public List<Map<String, String>> getBookmarks() {
+ return bookmarkAttribs;
+ }
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageContentProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageContentProvider.java
new file mode 100644
index 0000000000..278b29b854
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageContentProvider.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * A content provider to display the content of a trace package in a tree
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageContentProvider implements ITreeContentProvider {
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof TracePackageElement[]) {
+ return (TracePackageElement[]) inputElement;
+ }
+ return null;
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ return ((TracePackageElement) parentElement).getVisibleChildren();
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ return ((TracePackageElement) element).getParent();
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ TracePackageElement traceTransferElement = (TracePackageElement) element;
+ TracePackageElement[] visibleChildren = traceTransferElement.getVisibleChildren();
+ return visibleChildren != null && visibleChildren.length > 0;
+ }
+
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageElement.java
new file mode 100644
index 0000000000..60fec72e7c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageElement.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2015 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ * Patrick Tasse - Add list methods
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.model.WorkbenchAdapter;
+
+/**
+ * An ExportTraceElement represents an item in the ExportTraceWizard tree.
+ *
+ * @author Marc-Andre Laperle
+ */
+public abstract class TracePackageElement extends WorkbenchAdapter {
+ private final List<TracePackageElement> fChildren;
+ private TracePackageElement fParent;
+ private boolean fEnabled;
+ private boolean fChecked;
+ private boolean fVisible;
+
+ /**
+ *
+ * @param parent
+ * the parent of this element, can be set to null
+ */
+ public TracePackageElement(TracePackageElement parent) {
+ fParent = parent;
+ fEnabled = true;
+ fVisible = true;
+ fChildren = new ArrayList<>();
+ if (parent != null) {
+ parent.addChild(this);
+ }
+ }
+
+ /**
+ * Add a child at the end of the element's children list.
+ *
+ * @param child
+ * the element to add as a child
+ */
+ public void addChild(TracePackageElement child) {
+ child.setParent(this);
+ fChildren.add(child);
+ }
+
+ /**
+ * Insert a child at the specified position in the element's children list.
+ *
+ * @param index
+ * the index at which the element is to be inserted
+ * @param child
+ * the element to insert as a child
+ */
+ public void addChild(int index, TracePackageElement child) {
+ fChildren.add(index, child);
+ child.setParent(this);
+ }
+
+ /**
+ * Remove a child from the element's children list.
+ *
+ * @param child
+ * the child to remove
+ */
+ public void removeChild(TracePackageElement child) {
+ fChildren.remove(child);
+ child.setParent(null);
+ }
+
+ /**
+ * Returns the index of the specified child in the element's children list.
+ *
+ * @param child
+ * the child to search for
+ * @return the index of the child in the list, or -1 if not found
+ */
+ public int indexOf(TracePackageElement child) {
+ return fChildren.indexOf(child);
+ }
+
+ /**
+ * @return the parent of this element or null if there is no parent
+ */
+ public TracePackageElement getParent() {
+ return fParent;
+ }
+
+ private void setParent(TracePackageElement parent) {
+ fParent = parent;
+ }
+
+ /**
+ * Get the text representation of this element to be displayed in the tree.
+ *
+ * @return the text representation
+ */
+ public abstract String getText();
+
+ /**
+ * Get the children of this element
+ *
+ * @return the children of this element
+ */
+ public TracePackageElement[] getChildren() {
+ return fChildren.toArray(new TracePackageElement[fChildren.size()]);
+ }
+
+ /**
+ * Get the visible children of this element
+ *
+ * @return the visible children of this element
+ */
+ public TracePackageElement[] getVisibleChildren() {
+ List<TracePackageElement> visibleChildren = new ArrayList<>();
+ for (TracePackageElement child : fChildren) {
+ if (child.isVisible()) {
+ visibleChildren.add(child);
+ }
+ }
+ return visibleChildren.toArray(new TracePackageElement[0]);
+ }
+
+ /**
+ * Get the total size of the element including its children
+ *
+ * @param checkedOnly
+ * only count checked elements
+ *
+ * @return the total size of the element
+ */
+ public long getSize(boolean checkedOnly) {
+ long size = 0;
+ if (fChildren != null) {
+ for (TracePackageElement child : fChildren) {
+ size += child.getSize(checkedOnly);
+ }
+ }
+
+ return size;
+ }
+
+ /**
+ * Get the image representation of this element to be displayed in the tree.
+ *
+ * @return the image representation
+ */
+ public Image getImage() {
+ return null;
+ }
+
+ /**
+ * Returns whether or not the element is enabled (grayed and not
+ * modifiable).
+ *
+ * @return whether or not the element is enabled
+ */
+ public boolean isEnabled() {
+ return fEnabled;
+ }
+
+ /**
+ * Returns whether or not the element is checked.
+ *
+ * @return whether or not the element is checked
+ */
+ public boolean isChecked() {
+ return fChecked;
+ }
+
+ /**
+ * Returns whether or not the element is visible.
+ *
+ * @return whether or not the element is visible
+ */
+ public boolean isVisible() {
+ return fVisible;
+ }
+
+ /**
+ * Sets whether or not the element should be enabled (grayed and not
+ * modifiable).
+ *
+ * @param enabled
+ * if the element should be enabled
+ */
+ public void setEnabled(boolean enabled) {
+ fEnabled = enabled;
+ }
+
+ /**
+ * Sets whether or not the element should be checked.
+ *
+ * @param checked
+ * if the element should be checked
+ */
+ public void setChecked(boolean checked) {
+ fChecked = checked;
+ }
+
+ /**
+ * Sets whether or not the element is visible.
+ *
+ * @param visible
+ * if the element should be visible
+ */
+ public void setVisible(boolean visible) {
+ fVisible = visible;
+ }
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageFilesElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageFilesElement.java
new file mode 100644
index 0000000000..fccbadfcdf
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageFilesElement.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+
+/**
+ * An ExportTraceElement representing the trace files of a trace.
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageFilesElement extends TracePackageElement {
+
+ private static final String TRACE_ICON_PATH = "icons/elcl16/trace.gif"; //$NON-NLS-1$
+ private String fFileName;
+ private final IResource fResource;
+ private long fSize = -1;
+
+ /**
+ * Constructs an instance of ExportTraceFilesElement when exporting
+ *
+ * @param parent
+ * the parent of this element, can be set to null
+ * @param resource
+ * the resource representing the trace file or folder in the
+ * workspace
+ */
+ public TracePackageFilesElement(TracePackageElement parent, IResource resource) {
+ super(parent);
+ fFileName = null;
+ fResource = resource;
+ }
+
+ /**
+ * Constructs an instance of ExportTraceFilesElement when importing
+ *
+ * @param parent
+ * the parent of this element, can be set to null
+ * @param fileName
+ * the name of the file to be imported
+ */
+ public TracePackageFilesElement(TracePackageElement parent, String fileName) {
+ super(parent);
+ fFileName = fileName;
+ fResource = null;
+ }
+
+ private long getSize(File file) {
+ if (file.isDirectory()) {
+ long size = 0;
+ for (File f : file.listFiles()) {
+ size += getSize(f);
+ }
+ return size;
+ }
+
+ return file.length();
+ }
+
+ @Override
+ public long getSize(boolean checkedOnly) {
+ if (checkedOnly && !isChecked()) {
+ return 0;
+ }
+
+ if (fSize == -1 && fResource.exists()) {
+ File file = fResource.getLocation().toFile();
+ fSize = getSize(file);
+ }
+
+ return fSize;
+ }
+
+ @Override
+ public String getText() {
+ return Messages.TracePackage_TraceElement;
+ }
+
+ @Override
+ public Image getImage() {
+ return Activator.getDefault().getImageFromImageRegistry(TRACE_ICON_PATH);
+ }
+
+ /**
+ * Get the file name for this trace file or folder
+ *
+ * @return the file name for this trace file or folder
+ */
+ public String getFileName() {
+ return fFileName;
+ }
+
+ /**
+ * Set the file name for this trace file or folder
+ *
+ * @param fileName the file name for this trace file or folder
+ */
+ public void setFileName(String fileName) {
+ fFileName = fileName;
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageLabelProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageLabelProvider.java
new file mode 100644
index 0000000000..52687608df
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageLabelProvider.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A label provider for the export trace tree.
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageLabelProvider extends ColumnLabelProvider {
+
+ @Override
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ @Override
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ return ((TracePackageElement) element).getImage();
+ }
+
+ @Override
+ public String getText(Object element) {
+ return ((TracePackageElement) element).getText();
+ }
+
+ @Override
+ public Color getForeground(Object element) {
+ if (!((TracePackageElement) element).isEnabled()) {
+ return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
+ }
+ return null;
+ }
+
+ @Override
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFileElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFileElement.java
new file mode 100644
index 0000000000..1c501ed310
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFileElement.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+
+/**
+ * A trace package element representing a single supplementary file
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageSupplFileElement extends TracePackageElement {
+
+ private static final String SUPPL_FILE_ICON_PATH = "icons/obj16/thread_obj.gif"; //$NON-NLS-1$
+
+ private final IResource fResource;
+ private final String fSuppFileName;
+
+ /**
+ * Constructor used when exporting
+ *
+ * @param resource
+ * the resource representing this supplementary file in the
+ * workspace
+ * @param parent
+ * the parent element
+ */
+ public TracePackageSupplFileElement(IResource resource, TracePackageElement parent) {
+ super(parent);
+ fResource = resource;
+ fSuppFileName = null;
+ }
+
+ /**
+ * Constructor used when importing
+ *
+ * @param suppFileName
+ * the name to be used for the supplementary file in the
+ * workspace
+ * @param parent
+ * the parent element
+ */
+ public TracePackageSupplFileElement(String suppFileName, TracePackageElement parent) {
+ super(parent);
+ this.fSuppFileName = suppFileName;
+ fResource = null;
+ }
+
+ /**
+ * Get the resource corresponding to this supplementary file
+ *
+ * @return the resource corresponding to this supplementary file
+ */
+ public IResource getResource() {
+ return fResource;
+ }
+
+ @Override
+ public String getText() {
+ return fResource != null ? fResource.getName() : fSuppFileName;
+ }
+
+ @Override
+ public long getSize(boolean checkedOnly) {
+ if (checkedOnly && !isChecked()) {
+ return 0;
+ }
+
+ return fResource.getLocation().toFile().length();
+ }
+
+ @Override
+ public Image getImage() {
+ return Activator.getDefault().getImageFromImageRegistry(SUPPL_FILE_ICON_PATH);
+ }
+
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFilesElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFilesElement.java
new file mode 100644
index 0000000000..76c427b9a7
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageSupplFilesElement.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+
+/**
+ * A trace package element used for grouping supplementary file under a single
+ * subtree
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageSupplFilesElement extends TracePackageElement {
+
+ private static final String SUPPL_FILE_ICON_PATH = "icons/obj16/thread_obj.gif"; //$NON-NLS-1$
+
+ /**
+ * Construct a new TracePackageSupplFilesElement instance
+ *
+ * @param parent
+ * the parent of this element, can be set to null
+ */
+ public TracePackageSupplFilesElement(TracePackageElement parent) {
+ super(parent);
+ }
+
+ @Override
+ public String getText() {
+ return Messages.TracePackage_SupplementaryFiles;
+ }
+
+ @Override
+ public Image getImage() {
+ return Activator.getDefault().getImageFromImageRegistry(SUPPL_FILE_ICON_PATH);
+ }
+} \ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageTraceElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageTraceElement.java
new file mode 100644
index 0000000000..53fe427bb4
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/TracePackageTraceElement.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfNavigatorLabelProvider;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+
+/**
+ * An ExportTraceElement associated to a TmfTraceElement. This will be the
+ * parent of other elements (events, supplementary files, bookmarks, etc).
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageTraceElement extends TracePackageElement {
+
+ private final TmfTraceElement fTraceElement;
+ private String fImportName;
+ private String fTraceType;
+
+ /**
+ * Construct an instance associated to a TmfTraceElement. For exporting.
+ *
+ * @param parent
+ * the parent of this element, can be set to null
+ * @param traceElement
+ * the associated TmfTraceElement
+ */
+ public TracePackageTraceElement(TracePackageElement parent, TmfTraceElement traceElement) {
+ super(parent);
+ fTraceElement = traceElement;
+ fImportName = null;
+ fTraceType = null;
+ }
+
+ /**
+ * Construct an instance associated to a TmfTraceElement. For importing.
+ *
+ * @param parent
+ * the parent of this element, can be set to null
+ * @param importName
+ * the name to use to identify this trace
+ * @param traceType
+ * the trace type to set for this trace
+ */
+ public TracePackageTraceElement(TracePackageElement parent, String importName, String traceType) {
+ super(parent);
+ fImportName = importName;
+ fTraceElement = null;
+ fTraceType = traceType;
+ }
+
+ @Override
+ public String getText() {
+ return fTraceElement != null ? fTraceElement.getElementPath() : getDestinationElementPath();
+ }
+
+ /**
+ * Return the target TmfCommonProjectElement element path for a given trace
+ * package element. {@link TmfCommonProjectElement#getElementPath()}
+ *
+ * @return the element path
+ */
+ public String getDestinationElementPath() {
+ String traceName = getImportName();
+ for (TracePackageElement element : getChildren()) {
+ if (element instanceof TracePackageFilesElement) {
+ TracePackageFilesElement tracePackageFilesElement = (TracePackageFilesElement) element;
+ String fileName = tracePackageFilesElement.getFileName();
+ String parentDir = removeLastSegment(fileName);
+ return append(parentDir, traceName);
+ }
+ }
+
+ return traceName;
+ }
+
+ /**
+ * We do this outside of the Path class because we don't want it to convert
+ * \ to / on Windows in the presence of regular expressions
+ */
+ private static String removeLastSegment(String str) {
+ String ret = removeAllTrailing(str, IPath.SEPARATOR);
+ int lastIndexOf = ret.lastIndexOf(IPath.SEPARATOR);
+ if (lastIndexOf != -1) {
+ ret = ret.substring(0, lastIndexOf);
+ ret = removeAllTrailing(ret, IPath.SEPARATOR);
+ } else {
+ ret = ""; //$NON-NLS-1$
+ }
+
+ return ret;
+ }
+
+ private static String removeAllTrailing(String str, char toRemove) {
+ String ret = str;
+ while (ret.endsWith(Character.toString(toRemove))) {
+ ret = ret.substring(0, ret.length() - 1);
+ }
+ return ret;
+ }
+
+ private static String append(String path, String str) {
+ if (!path.isEmpty()) {
+ return path + IPath.SEPARATOR + str;
+ }
+
+ return str;
+ }
+
+ /**
+ * @return the associated TmfTraceElement
+ */
+ public TmfTraceElement getTraceElement() {
+ return fTraceElement;
+ }
+
+ /**
+ * Set the import name.
+ *
+ * @param importName the import name.
+ */
+ public void setImportName(String importName) {
+ fImportName = importName;
+ }
+
+ /**
+ * @return the import name
+ */
+ public String getImportName() {
+ return fImportName;
+ }
+
+ /**
+ * @return the trace type of this trace
+ */
+ public String getTraceType() {
+ return fTraceType;
+ }
+
+ /**
+ * Set the trace type of this trace.
+ *
+ * @param traceType the trace type of this trace
+ */
+ public void setTraceType(String traceType) {
+ fTraceType = traceType;
+ }
+
+ @Override
+ public Image getImage() {
+ TmfNavigatorLabelProvider tmfNavigatorLabelProvider = new TmfNavigatorLabelProvider();
+ return tmfNavigatorLabelProvider.getImage(fTraceElement);
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageHandler.java
new file mode 100644
index 0000000000..4d800f19d2
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageHandler.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for exporting a trace package
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ExportTracePackageHandler extends AbstractHandler {
+
+ private boolean fEnabled = false;
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null) {
+ return Boolean.FALSE;
+ }
+
+ ISelection currentSelection = HandlerUtil.getCurrentSelection(event);
+ IStructuredSelection sec = StructuredSelection.EMPTY;
+ List<TmfTraceElement> selectedTraces = new ArrayList<>();
+ if (currentSelection instanceof IStructuredSelection) {
+ sec = (IStructuredSelection) currentSelection;
+ Object[] selectedElements = sec.toArray();
+ for (Object selectedElement : selectedElements) {
+ if (selectedElement instanceof TmfTraceElement) {
+ TmfTraceElement tmfTraceElement = (TmfTraceElement) selectedElement;
+ selectedTraces.add(tmfTraceElement.getElementUnderTraceFolder());
+ } else if (selectedElement instanceof TmfTraceFolder) {
+ TmfTraceFolder tmfTraceFolder = (TmfTraceFolder) selectedElement;
+ selectedTraces = tmfTraceFolder.getTraces();
+ }
+ }
+ }
+
+ ExportTracePackageWizard w = new ExportTracePackageWizard(selectedTraces);
+
+ w.init(PlatformUI.getWorkbench(), sec);
+ WizardDialog dialog = new WizardDialog(window.getShell(), w);
+ dialog.open();
+ return null;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return super.isEnabled() && fEnabled;
+ }
+
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ super.setEnabled(evaluationContext);
+
+ fEnabled = true;
+
+ Object s = HandlerUtil.getVariable(evaluationContext, ISources.ACTIVE_MENU_SELECTION_NAME);
+ if (s instanceof IStructuredSelection) {
+ IStructuredSelection selection = (IStructuredSelection) s;
+ // If we have traces selected, make sure they are all from the same
+ // project, disable handler otherwise
+ Object[] selectedElements = selection.toArray();
+ TmfProjectElement firstProject = null;
+ for (Object selectedElement : selectedElements) {
+ if (selectedElement instanceof TmfTraceElement) {
+ TmfTraceElement tmfTraceElement = (TmfTraceElement) selectedElement;
+ TmfProjectElement project = tmfTraceElement.getProject();
+ if (firstProject != null && !project.equals(firstProject)) {
+ fEnabled = false;
+ }
+
+ firstProject = project;
+ }
+ }
+ }
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageSelectTraceWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageSelectTraceWizardPage.java
new file mode 100644
index 0000000000..5d6b77d091
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageSelectTraceWizardPage.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfNavigatorContentProvider;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfNavigatorLabelProvider;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * A wizard page for selecting the trace to export when no trace was previously
+ * selected.
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ExportTracePackageSelectTraceWizardPage extends WizardPage {
+
+ private static final String PAGE_NAME = "ExportTracePackageSelectTraceWizardPage"; //$NON-NLS-1$
+
+ /**
+ * Construct the select trace page
+ */
+ public ExportTracePackageSelectTraceWizardPage() {
+ super(PAGE_NAME);
+ }
+
+ private IProject fSelectedProject;
+ private Table fTraceTable;
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite projectSelectionGroup = new Composite(parent, SWT.NONE);
+ projectSelectionGroup.setLayout(new GridLayout(2, true));
+ projectSelectionGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+ projectSelectionGroup.setFont(parent.getFont());
+
+ Label projectLabel = new Label(projectSelectionGroup, SWT.NONE);
+ projectLabel.setText(Messages.ExportTracePackageSelectTraceWizardPage_ProjectSelection);
+ projectLabel.setLayoutData(new GridData());
+
+ Label configLabel = new Label(projectSelectionGroup, SWT.NONE);
+ configLabel.setText(Messages.ExportTracePackageSelectTraceWizardPage_TraceSelection);
+ configLabel.setLayoutData(new GridData());
+
+ final Table projectTable = new Table(projectSelectionGroup, SWT.SINGLE | SWT.BORDER);
+ projectTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ TableViewer projectViewer = new TableViewer(projectTable);
+ projectViewer.setContentProvider(new TmfNavigatorContentProvider() {
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return (IProject[]) inputElement;
+ }
+ });
+ projectViewer.setLabelProvider(new WorkbenchLabelProvider());
+ projectViewer.setInput(TraceUtils.getOpenedTmfProjects().toArray(new IProject[] {}));
+
+ fTraceTable = new Table(projectSelectionGroup, SWT.BORDER | SWT.CHECK);
+ fTraceTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ final TableViewer traceViewer = new TableViewer(fTraceTable);
+ traceViewer.setContentProvider(new IStructuredContentProvider() {
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof TmfTraceElement[]) {
+ return (TmfTraceElement[]) inputElement;
+ }
+ return null;
+ }
+ });
+ traceViewer.setLabelProvider(new ExportLabelProvider());
+ fTraceTable.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ getWizard().getContainer().updateButtons();
+ updateNextPageData();
+ }
+ });
+
+ projectTable.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ TableItem[] items = projectTable.getSelection();
+ fSelectedProject = (IProject) items[0].getData();
+
+ TmfProjectElement project = TmfProjectRegistry.getProject(fSelectedProject, true);
+
+ TmfTraceFolder tracesFolder = project.getTracesFolder();
+ List<TmfTraceElement> traces = tracesFolder.getTraces();
+ TmfTraceElement[] array = traces.toArray(new TmfTraceElement[] {});
+ traceViewer.setInput(array);
+ traceViewer.refresh();
+ fTraceTable.select(0);
+ fTraceTable.notifyListeners(SWT.Selection, new Event());
+ getWizard().getContainer().updateButtons();
+ }
+ });
+
+ Composite btComp = new Composite(projectSelectionGroup, SWT.NONE);
+ btComp.setLayout(new GridLayout(2, true));
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ gd.horizontalAlignment = SWT.RIGHT;
+ btComp.setLayoutData(gd);
+
+ final Button selectAll = new Button(btComp, SWT.PUSH);
+ selectAll.setText(org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.Messages.Dialog_SelectAll);
+ selectAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ TableItem[] items = fTraceTable.getItems();
+ for (TableItem item : items) {
+ item.setChecked(true);
+ }
+
+ getWizard().getContainer().updateButtons();
+ updateNextPageData();
+ }
+ });
+
+ final Button deselectAll = new Button(btComp, SWT.PUSH);
+ deselectAll.setText(org.eclipse.tracecompass.internal.tmf.ui.project.dialogs.Messages.Dialog_DeselectAll);
+ deselectAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ TableItem[] items = fTraceTable.getItems();
+ for (TableItem item : items) {
+ item.setChecked(false);
+ }
+
+ getWizard().getContainer().updateButtons();
+ updateNextPageData();
+ }
+ });
+
+ setControl(projectSelectionGroup);
+ setTitle(Messages.ExportTracePackageWizardPage_Title);
+ setMessage(Messages.ExportTracePackageSelectTraceWizardPage_ChooseTrace);
+ }
+
+ private ArrayList<TmfTraceElement> getCheckedTraces() {
+ TableItem[] items = fTraceTable.getItems();
+ ArrayList<TmfTraceElement> traces = new ArrayList<>();
+ for (TableItem item : items) {
+ if (item.getChecked()) {
+ TmfTraceElement trace = (TmfTraceElement) item.getData();
+ traces.add(trace);
+ }
+ }
+ return traces;
+ }
+
+ private void updateNextPageData() {
+ ExportTracePackageWizardPage page = (ExportTracePackageWizardPage) getWizard().getPage(ExportTracePackageWizardPage.PAGE_NAME);
+ page.setSelectedTraces(getCheckedTraces());
+ }
+
+ @Override
+ public boolean canFlipToNextPage() {
+ return getCheckedTraces().size() > 0;
+ }
+
+ private class ExportLabelProvider extends TmfNavigatorLabelProvider {
+ @Override
+ public String getText(Object element) {
+
+ if (element instanceof TmfTraceElement) {
+ TmfTraceElement folder = (TmfTraceElement) element;
+ return folder.getElementPath();
+ }
+ return super.getText(element);
+ }
+ }
+
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizard.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizard.java
new file mode 100644
index 0000000000..512ac49e6c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizard.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * Wizard for exporting a trace package
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ExportTracePackageWizard extends Wizard implements IExportWizard {
+
+ private static final String STORE_EXPORT_TRACE_WIZARD = "ExportTraceWizard"; //$NON-NLS-1$
+ private IStructuredSelection fSelection;
+ private List<TmfTraceElement> fSelectedTraces;
+ private ExportTracePackageWizardPage fPage;
+
+ /**
+ * Constructor for the export trace wizard
+ */
+ public ExportTracePackageWizard() {
+ IDialogSettings workbenchSettings = Activator.getDefault().getDialogSettings();
+ IDialogSettings section = workbenchSettings
+ .getSection(STORE_EXPORT_TRACE_WIZARD);
+ if (section == null) {
+ section = workbenchSettings.addNewSection(STORE_EXPORT_TRACE_WIZARD);
+ }
+ setDialogSettings(section);
+ fSelectedTraces = new ArrayList<>();
+ }
+
+ /**
+ * Constructor for the export trace wizard with known selected traces
+ *
+ * @param selectedTraces
+ * the selected traces
+ */
+ public ExportTracePackageWizard(List<TmfTraceElement> selectedTraces) {
+ this();
+ fSelectedTraces = selectedTraces;
+ }
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ fSelection = selection;
+
+ setNeedsProgressMonitor(true);
+ }
+
+ @Override
+ public boolean performFinish() {
+ return fPage.finish();
+ }
+
+ @Override
+ public void addPages() {
+ super.addPages();
+ fPage = new ExportTracePackageWizardPage(fSelection, fSelectedTraces);
+ if (fSelectedTraces.isEmpty()) {
+ addPage(new ExportTracePackageSelectTraceWizardPage());
+ }
+ addPage(fPage);
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizardPage.java
new file mode 100644
index 0000000000..e39508b42b
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ExportTracePackageWizardPage.java
@@ -0,0 +1,450 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageWizardPage;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageLabelProvider;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+
+/**
+ * Wizard page for the export trace package wizard
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ExportTracePackageWizardPage extends AbstractTracePackageWizardPage {
+
+ private static final int CONTENT_COL_WIDTH = 300;
+ private static final int SIZE_COL_WIDTH = 100;
+
+ private static final String ZIP_EXTENSION = ".zip"; //$NON-NLS-1$
+ private static final String TAR_EXTENSION = ".tar"; //$NON-NLS-1$
+ private static final String TAR_GZ_EXTENSION = ".tar.gz"; //$NON-NLS-1$
+ private static final String TGZ_EXTENSION = ".tgz"; //$NON-NLS-1$
+
+ private static final String ICON_PATH = "icons/wizban/export_wiz.png"; //$NON-NLS-1$
+
+ /**
+ * The page name, can be referenced from other pages
+ */
+ public static final String PAGE_NAME = "ExportTracePackageWizardPage"; //$NON-NLS-1$
+ // dialog store id constants
+ private static final String STORE_COMPRESS_CONTENTS_ID = PAGE_NAME + ".STORE_COMPRESS_CONTENTS_ID"; //$NON-NLS-1$
+ private static final String STORE_FORMAT_ID = PAGE_NAME + ".STORE_FORMAT_ID"; //$NON-NLS-1$
+
+ private Button fCompressContentsCheckbox;
+ private Button fZipFormatButton;
+ private Button fTargzFormatButton;
+ private Label fApproximateSizeLabel;
+ private List<TmfTraceElement> fSelectedTraces;
+
+ /**
+ * Constructor for the export trace package wizard page
+ *
+ * @param selection
+ * the current object selection
+ * @param selectedTraces
+ * the selected traces from the selection
+ */
+ public ExportTracePackageWizardPage(IStructuredSelection selection, List<TmfTraceElement> selectedTraces) {
+ super(PAGE_NAME, Messages.ExportTracePackageWizardPage_Title, Activator.getDefault().getImageDescripterFromPath(ICON_PATH), selection);
+ fSelectedTraces = selectedTraces;
+ }
+
+ /**
+ * Set the selected trace from the previous page to be displayed in the
+ * element viewer
+ *
+ * @param selectedTraces
+ * the selected trace
+ */
+ public void setSelectedTraces(List<TmfTraceElement> selectedTraces) {
+ if (!fSelectedTraces.containsAll(selectedTraces) || !selectedTraces.containsAll(fSelectedTraces)) {
+ fSelectedTraces = selectedTraces;
+ CheckboxTreeViewer elementViewer = getElementViewer();
+ elementViewer.setInput(createElementViewerInput());
+ elementViewer.expandToLevel(2);
+ setAllChecked(elementViewer, false, true);
+ updateApproximateSelectedSize();
+ }
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+
+ initializeDialogUnits(parent);
+
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
+
+ createElementViewer(composite);
+ createButtonsGroup(composite);
+ createFilePathGroup(composite, Messages.ExportTracePackageWizardPage_ToArchive, SWT.SAVE);
+ createOptionsGroup(composite);
+
+ restoreWidgetValues();
+ setMessage(Messages.ExportTracePackageWizardPage_ChooseContent);
+
+ updateApproximateSelectedSize();
+ updatePageCompletion();
+
+ setControl(composite);
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ updatePageCompletion();
+ } else {
+ setPageComplete(false);
+ }
+ }
+
+ /**
+ * Restore widget values to the values that they held last time this wizard
+ * was used to completion.
+ */
+ @Override
+ protected void restoreWidgetValues() {
+ super.restoreWidgetValues();
+
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ if (getFilePathCombo().getItemCount() > 0) {
+ String item = getFilePathCombo().getItem(0);
+ setFilePathValue(item);
+ }
+ fCompressContentsCheckbox.setSelection(settings.getBoolean(STORE_COMPRESS_CONTENTS_ID));
+ fZipFormatButton.setSelection(settings.getBoolean(STORE_FORMAT_ID));
+ fTargzFormatButton.setSelection(!settings.getBoolean(STORE_FORMAT_ID));
+ updateWithFilePathSelection();
+ }
+ }
+
+ @Override
+ protected void createFilePathGroup(Composite parent, String label, int fileDialogStyle) {
+ super.createFilePathGroup(parent, label, fileDialogStyle);
+
+ getFilePathCombo().addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ updatePageCompletion();
+ }
+ });
+ }
+
+ private void createOptionsGroup(Composite parent) {
+ Group optionsGroup = new Group(parent, SWT.NONE);
+ optionsGroup.setLayout(new RowLayout(SWT.VERTICAL));
+ optionsGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.GRAB_HORIZONTAL));
+ optionsGroup.setText(Messages.ExportTracePackageWizardPage_Options);
+
+ SelectionAdapter listener = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWithFilePathSelection();
+ }
+ };
+
+ fZipFormatButton = new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
+ fZipFormatButton.setText(Messages.ExportTracePackageWizardPage_SaveInZipFormat);
+ fZipFormatButton.setSelection(true);
+ fZipFormatButton.addSelectionListener(listener);
+
+ fTargzFormatButton = new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
+ fTargzFormatButton.setText(Messages.ExportTracePackageWizardPage_SaveInTarFormat);
+ fTargzFormatButton.setSelection(false);
+ fTargzFormatButton.addSelectionListener(listener);
+
+ fCompressContentsCheckbox = new Button(optionsGroup, SWT.CHECK | SWT.LEFT);
+ fCompressContentsCheckbox.setText(Messages.ExportTracePackageWizardPage_CompressContents);
+ fCompressContentsCheckbox.setSelection(true);
+ fCompressContentsCheckbox.addSelectionListener(listener);
+ }
+
+ @Override
+ protected void createElementViewer(Composite parent) {
+ super.createElementViewer(parent);
+
+ CheckboxTreeViewer elementViewer = getElementViewer();
+ elementViewer.getTree().setHeaderVisible(true);
+ // Content column
+ TreeViewerColumn column = new TreeViewerColumn(elementViewer, SWT.NONE);
+ column.getColumn().setWidth(CONTENT_COL_WIDTH);
+ column.getColumn().setText(Messages.ExportTracePackageWizardPage_ContentColumnName);
+ column.setLabelProvider(new TracePackageLabelProvider());
+
+ // Size column
+ column = new TreeViewerColumn(elementViewer, SWT.NONE);
+ column.getColumn().setWidth(SIZE_COL_WIDTH);
+ column.getColumn().setText(Messages.ExportTracePackageWizardPage_SizeColumnName);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ TracePackageElement tracePackageElement = (TracePackageElement) element;
+ long size = tracePackageElement.getSize(false);
+ if (size == 0) {
+ return null;
+ }
+ int level = 0;
+ TracePackageElement curElement = tracePackageElement.getParent();
+ while (curElement != null) {
+ curElement = curElement.getParent();
+ ++level;
+ }
+
+ return indent(getHumanReadable(size), level);
+ }
+
+ private String indent(String humanReadable, int level) {
+ StringBuilder s = new StringBuilder(humanReadable);
+ for (int i = 0; i < level; ++i) {
+ final String indentStr = " "; //$NON-NLS-1$
+ s.insert(0, indentStr);
+ }
+ return s.toString();
+ }
+ });
+
+ elementViewer.setInput(createElementViewerInput());
+ elementViewer.expandToLevel(2);
+ setAllChecked(elementViewer, false, true);
+ }
+
+ @Override
+ protected void updateApproximateSelectedSize() {
+ long checkedSize = 0;
+ TracePackageElement[] tracePackageElements = (TracePackageElement[]) getElementViewer().getInput();
+ for (TracePackageElement element : tracePackageElements) {
+ checkedSize += element.getSize(true);
+ }
+ checkedSize = Math.max(0, checkedSize);
+ fApproximateSizeLabel.setText(MessageFormat.format(Messages.ExportTracePackageWizardPage_ApproximateSizeLbl, getHumanReadable(checkedSize)));
+ }
+
+ /**
+ * Get the human readable string for a size in bytes. (KB, MB, etc).
+ *
+ * @param size
+ * the size to print in human readable,
+ * @return the human readable string
+ */
+ private static String getHumanReadable(long size) {
+ String humanSuffix[] = { Messages.ExportTracePackageWizardPage_SizeByte, Messages.ExportTracePackageWizardPage_SizeKilobyte,
+ Messages.ExportTracePackageWizardPage_SizeMegabyte, Messages.ExportTracePackageWizardPage_SizeGigabyte,
+ Messages.ExportTracePackageWizardPage_SizeTerabyte };
+ long curSize = size;
+
+ int suffixIndex = 0;
+ while (curSize >= 1024) {
+ curSize /= 1024;
+ ++suffixIndex;
+ }
+
+ return Long.toString(curSize) + " " + humanSuffix[suffixIndex]; //$NON-NLS-1$
+ }
+
+ @Override
+ protected Object createElementViewerInput() {
+ List<TracePackageTraceElement> traceElements = new ArrayList<>();
+ for (TmfTraceElement tmfTraceElement : fSelectedTraces) {
+ TracePackageTraceElement traceElement = new TracePackageTraceElement(null, tmfTraceElement);
+
+ // Trace files
+ List<TracePackageElement> children = new ArrayList<>();
+ TracePackageFilesElement filesElement = new TracePackageFilesElement(traceElement, tmfTraceElement.getResource());
+ filesElement.setChecked(true);
+ children.add(filesElement);
+
+ // Supplementary files
+ IResource[] supplementaryResources = tmfTraceElement.getSupplementaryResources();
+ List<TracePackageElement> suppFilesChildren = new ArrayList<>();
+ TracePackageSupplFilesElement suppFilesElement = new TracePackageSupplFilesElement(traceElement);
+ children.add(suppFilesElement);
+ for (IResource res : supplementaryResources) {
+ suppFilesChildren.add(new TracePackageSupplFileElement(res, suppFilesElement));
+ }
+
+ // Bookmarks
+ IFile bookmarksFile = tmfTraceElement.getBookmarksFile();
+ if (bookmarksFile != null && bookmarksFile.exists()) {
+ IMarker[] findMarkers;
+ try {
+ findMarkers = bookmarksFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
+ if (findMarkers.length > 0) {
+ children.add(new TracePackageBookmarkElement(traceElement, null));
+ }
+ } catch (CoreException e) {
+ // Should not happen since we just checked bookmarksFile.exists() but log it just in case
+ Activator.getDefault().logError("Error finding bookmarks", e); //$NON-NLS-1$
+ }
+ }
+
+ traceElements.add(traceElement);
+
+ }
+
+ return traceElements.toArray(new TracePackageTraceElement[] {});
+ }
+
+ @Override
+ protected final Composite createButtonsGroup(Composite parent) {
+ Composite buttonGroup = super.createButtonsGroup(parent);
+
+ // Add the label on the same row of the select/deselect all buttons
+ fApproximateSizeLabel = new Label(buttonGroup, SWT.RIGHT);
+ GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
+ layoutData.grabExcessHorizontalSpace = true;
+ fApproximateSizeLabel.setLayoutData(layoutData);
+
+ return buttonGroup;
+ }
+
+ /**
+ * Save widget values to Dialog settings
+ */
+ @Override
+ protected void saveWidgetValues() {
+ super.saveWidgetValues();
+
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ settings.put(STORE_COMPRESS_CONTENTS_ID, fCompressContentsCheckbox.getSelection());
+ settings.put(STORE_FORMAT_ID, fZipFormatButton.getSelection());
+ }
+ }
+
+ private String getOutputExtension() {
+ if (fZipFormatButton.getSelection()) {
+ return ZIP_EXTENSION;
+ } else if (fCompressContentsCheckbox.getSelection()) {
+ return TAR_GZ_EXTENSION;
+ } else {
+ return TAR_EXTENSION;
+ }
+ }
+
+ @Override
+ protected void updateWithFilePathSelection() {
+ String filePathValue = getFilePathValue();
+ if (filePathValue.isEmpty()) {
+ return;
+ }
+
+ filePathValue = stripKnownExtension(filePathValue);
+ filePathValue = filePathValue.concat(getOutputExtension());
+
+ setFilePathValue(filePathValue);
+ }
+
+ private static String stripKnownExtension(String str) {
+ String ret = str;
+ if (str.endsWith(TAR_GZ_EXTENSION)) {
+ ret = ret.substring(0, ret.lastIndexOf('.'));
+ }
+
+ if (ret.endsWith(ZIP_EXTENSION) || ret.endsWith(TAR_EXTENSION) || ret.endsWith(TGZ_EXTENSION)) {
+ ret = ret.substring(0, ret.lastIndexOf('.'));
+ }
+
+ return ret;
+ }
+
+ /**
+ * Finish the wizard page
+ *
+ * @return true on success
+ */
+ public boolean finish() {
+ if (!checkForOverwrite()) {
+ return false;
+ }
+
+ saveWidgetValues();
+
+ TracePackageTraceElement[] traceExportElements = (TracePackageTraceElement[]) getElementViewer().getInput();
+ boolean useCompression = fCompressContentsCheckbox.getSelection();
+ boolean useTar = fTargzFormatButton.getSelection();
+ String fileName = getFilePathValue();
+ final TracePackageExportOperation exporter = new TracePackageExportOperation(traceExportElements, useCompression, useTar, fileName);
+
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ exporter.run(monitor);
+ }
+ });
+
+ IStatus status = exporter.getStatus();
+ if (status.getSeverity() == IStatus.ERROR) {
+ handleErrorStatus(status);
+ }
+
+ } catch (InvocationTargetException e) {
+ handleError(org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
+ } catch (InterruptedException e) {
+ }
+
+ return exporter.getStatus().getSeverity() == IStatus.OK;
+ }
+
+ private boolean checkForOverwrite() {
+ File file = new File(getFilePathValue());
+ if (file.exists()) {
+ return MessageDialog.openQuestion(getContainer().getShell(), null, Messages.ExportTracePackageWizardPage_AlreadyExitst);
+ }
+ return true;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageHandler.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageHandler.java
new file mode 100644
index 0000000000..e8c96ed3f4
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageHandler.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for importing a trace package
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ImportTracePackageHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ImportTracePackageWizard w = new ImportTracePackageWizard();
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+
+ if (window == null) {
+ return Boolean.FALSE;
+ }
+
+ ISelection currentSelection = HandlerUtil.getCurrentSelection(event);
+ IStructuredSelection sec = StructuredSelection.EMPTY;
+ if (currentSelection instanceof IStructuredSelection) {
+ sec = (IStructuredSelection) currentSelection;
+ }
+
+ w.init(PlatformUI.getWorkbench(), sec);
+ WizardDialog dialog = new WizardDialog(window.getShell(), w);
+ dialog.open();
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizard.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizard.java
new file mode 100644
index 0000000000..6662a18c0c
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizard.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * Wizard for importing a trace package
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ImportTracePackageWizard extends Wizard implements IImportWizard {
+
+ private static final String STORE_IMPORT_TRACE_PKG_WIZARD = "ImportTracePackageWizard"; //$NON-NLS-1$
+ private IStructuredSelection fSelection;
+ private ImportTracePackageWizardPage fPage;
+
+ /**
+ * Constructs the import trace package wizard
+ */
+ public ImportTracePackageWizard() {
+ IDialogSettings workbenchSettings = Activator.getDefault().getDialogSettings();
+ IDialogSettings section = workbenchSettings
+ .getSection(STORE_IMPORT_TRACE_PKG_WIZARD);
+ if (section == null) {
+ section = workbenchSettings.addNewSection(STORE_IMPORT_TRACE_PKG_WIZARD);
+ }
+ setDialogSettings(section);
+ }
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ fSelection = selection;
+ setNeedsProgressMonitor(true);
+ }
+
+ @Override
+ public boolean performFinish() {
+ return fPage.finish();
+ }
+
+ @Override
+ public void addPages() {
+ super.addPages();
+ fPage = new ImportTracePackageWizardPage(fSelection);
+ addPage(fPage);
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizardPage.java
new file mode 100644
index 0000000000..561ea43ce2
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ImportTracePackageWizardPage.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageWizardPage;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Wizard page for the import trace package wizard
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ImportTracePackageWizardPage extends AbstractTracePackageWizardPage {
+
+ private static final String ICON_PATH = "icons/wizban/trace_import_wiz.png"; //$NON-NLS-1$
+ private static final String PAGE_NAME = "ImportTracePackagePage"; //$NON-NLS-1$
+ private static final String STORE_PROJECT_NAME_ID = PAGE_NAME + ".STORE_PROJECT_NAME_ID"; //$NON-NLS-1$
+
+ private String fValidatedFilePath;
+ private TmfTraceFolder fTmfTraceFolder;
+ private Text fProjectText;
+ private List<IProject> fOpenedTmfProjects;
+
+ /**
+ * Constructor for the import trace package wizard page
+ *
+ * @param selection
+ * the current object selection
+ */
+ public ImportTracePackageWizardPage(IStructuredSelection selection) {
+ super(PAGE_NAME, Messages.ImportTracePackageWizardPage_Title, Activator.getDefault().getImageDescripterFromPath(ICON_PATH), selection);
+
+ if (getSelection().getFirstElement() instanceof TmfTraceFolder) {
+ fTmfTraceFolder = (TmfTraceFolder) getSelection().getFirstElement();
+ }
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ initializeDialogUnits(parent);
+
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
+ | GridData.HORIZONTAL_ALIGN_FILL));
+ composite.setFont(parent.getFont());
+
+ createFilePathGroup(composite, Messages.ImportTracePackageWizardPage_FromArchive, SWT.OPEN);
+ createElementViewer(composite);
+ createButtonsGroup(composite);
+ if (fTmfTraceFolder == null) {
+ createProjectSelectionGroup(composite);
+ }
+
+ restoreWidgetValues();
+ setMessage(Messages.ImportTracePackageWizardPage_Message);
+ updatePageCompletion();
+
+ setControl(composite);
+ }
+
+ private void createProjectSelectionGroup(Composite parent) {
+
+ Composite projectSelectionGroup = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ projectSelectionGroup.setLayout(layout);
+ projectSelectionGroup.setLayoutData(new GridData(
+ GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+
+ Label projectLabel = new Label(projectSelectionGroup, SWT.NONE);
+ projectLabel.setText(Messages.ImportTracePackageWizardPage_Project);
+
+ fProjectText = new Text(projectSelectionGroup, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.GRAB_HORIZONTAL);
+ data.grabExcessHorizontalSpace = true;
+ fProjectText.setLayoutData(data);
+
+ fOpenedTmfProjects = TraceUtils.getOpenedTmfProjects();
+
+ // No project to import to, create a default project if it doesn't exist
+ if (fOpenedTmfProjects.isEmpty()) {
+ IProject defaultProject = ResourcesPlugin.getWorkspace().getRoot().getProject(TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME);
+ if (!defaultProject.exists()) {
+ IProject project = TmfProjectRegistry.createProject(TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME, null, null);
+ fOpenedTmfProjects.add(project);
+ }
+ }
+
+ if (!fOpenedTmfProjects.isEmpty()) {
+ selectProject(fOpenedTmfProjects.get(0));
+ }
+
+ Button button = new Button(projectSelectionGroup,
+ SWT.PUSH);
+ button.setText(Messages.ImportTracePackageWizardPage_SelectProjectButton);
+ button.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ ElementListSelectionDialog d = new ElementListSelectionDialog(getContainer().getShell(), new WorkbenchLabelProvider());
+
+ d.setBlockOnOpen(true);
+ d.setTitle(Messages.ImportTracePackageWizardPage_SelectProjectDialogTitle);
+
+ d.setElements(fOpenedTmfProjects.toArray(new IProject[] {}));
+
+ d.open();
+ if (d.getFirstResult() != null) {
+ IProject project = (IProject) d.getFirstResult();
+ selectProject(project);
+ }
+ }
+ });
+ setButtonLayoutData(button);
+ }
+
+ @Override
+ protected void restoreWidgetValues() {
+ super.restoreWidgetValues();
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null && fProjectText != null) {
+
+ // Restore last selected project
+ String projectName = settings.get(STORE_PROJECT_NAME_ID);
+ if (projectName != null && !projectName.isEmpty()) {
+ for (IProject project : fOpenedTmfProjects) {
+ if (project.getName().equals(projectName)) {
+ selectProject(project);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void saveWidgetValues() {
+ super.saveWidgetValues();
+
+ IDialogSettings settings = getDialogSettings();
+ if (settings != null) {
+ settings.put(STORE_PROJECT_NAME_ID, fTmfTraceFolder.getProject().getResource().getName());
+ }
+ }
+
+ private void selectProject(IProject project) {
+ fProjectText.setText(project.getName());
+ fTmfTraceFolder = TmfProjectRegistry.getProject(project, true).getTracesFolder();
+ updatePageCompletion();
+ }
+
+ @Override
+ protected boolean determinePageCompletion() {
+ return super.determinePageCompletion() && fTmfTraceFolder != null;
+ }
+
+ /**
+ * Create the operation that will be responsible of creating the manifest
+ * based on the file name.
+ *
+ * @param fileName the file name to generate the manifest from
+ *
+ * @return the operation that will extract the manifest
+ */
+ protected AbstractTracePackageOperation createExtractManifestOperation(String fileName) {
+ return new TracePackageExtractManifestOperation(fileName);
+ }
+
+ @Override
+ protected Object createElementViewerInput() {
+
+ final AbstractTracePackageOperation op = createExtractManifestOperation(getFilePathValue());
+
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ monitor.beginTask(Messages.ImportTracePackageWizardPage_ReadingPackage, 10);
+ op.run(monitor);
+ monitor.done();
+ }
+
+ });
+
+ IStatus status = op.getStatus();
+ if (status.getSeverity() == IStatus.ERROR) {
+ handleErrorStatus(status);
+ }
+ } catch (InvocationTargetException e1) {
+ handleError(Messages.TracePackageExtractManifestOperation_ErrorReadingManifest, e1);
+ } catch (InterruptedException e1) {
+ // Canceled
+ }
+
+ TracePackageElement[] resultElements = op.getResultElements();
+ if (resultElements == null || resultElements.length == 0) {
+ return null;
+ }
+
+ return resultElements;
+ }
+
+ @Override
+ protected void createFilePathGroup(Composite parent, String label, int fileDialogStyle) {
+ super.createFilePathGroup(parent, label, fileDialogStyle);
+
+ Combo filePathCombo = getFilePathCombo();
+ filePathCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateWithFilePathSelection();
+ }
+ });
+
+ // User can type-in path and press return to validate
+ filePathCombo.addTraverseListener(new TraverseListener() {
+ @Override
+ public void keyTraversed(TraverseEvent e) {
+ if (e.detail == SWT.TRAVERSE_RETURN) {
+ e.doit = false;
+ updateWithFilePathSelection();
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void updateWithFilePathSelection() {
+ if (!isFilePathValid()) {
+ setErrorMessage(Messages.ImportTracePackageWizardPage_ErrorFileNotFound);
+ getElementViewer().setInput(null);
+ return;
+ }
+ setErrorMessage(null);
+
+ getContainer().getShell().getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ CheckboxTreeViewer elementViewer = getElementViewer();
+ Object elementViewerInput = createElementViewerInput();
+ elementViewer.setInput(elementViewerInput);
+ if (elementViewerInput != null) {
+ elementViewer.expandToLevel(2);
+ setAllChecked(elementViewer, false, true);
+ fValidatedFilePath = getFilePathValue();
+ }
+
+ updatePageCompletion();
+ }
+ });
+ }
+
+ private boolean isFilePathValid() {
+ return new File(getFilePathValue()).exists();
+ }
+
+ /**
+ * Finish the wizard page
+ *
+ * @return true on success
+ */
+ public boolean finish() {
+ if (!checkForOverwrite()) {
+ return false;
+ }
+
+ saveWidgetValues();
+
+ Object input = getElementViewer().getInput();
+ TracePackageElement[] traceElements = (TracePackageElement[]) input;
+ final TracePackageImportOperation importOperation = new TracePackageImportOperation(fValidatedFilePath, traceElements, fTmfTraceFolder);
+
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ importOperation.run(monitor);
+ }
+ });
+
+ IStatus status = importOperation.getStatus();
+ if (status.getSeverity() == IStatus.ERROR) {
+ handleErrorStatus(status);
+ }
+
+ } catch (InvocationTargetException e) {
+ handleError(Messages.ImportTracePackageWizardPage_ErrorOperation, e);
+ } catch (InterruptedException e) {
+ }
+
+ return importOperation.getStatus().getSeverity() == IStatus.OK;
+ }
+
+ private boolean checkForOverwrite() {
+ TracePackageElement[] traceElements = (TracePackageElement[]) getElementViewer().getInput();
+ List<TracePackageTraceElement> noImportTraces = new ArrayList<>();
+ boolean noToAll = false;
+ for (TracePackageElement packageElement : traceElements) {
+ TracePackageTraceElement traceElement = (TracePackageTraceElement) packageElement;
+ if (!AbstractTracePackageOperation.isFilesChecked(traceElement)) {
+ continue;
+ }
+
+ if (noToAll) {
+ noImportTraces.add(traceElement);
+ continue;
+ }
+
+ if (traceExists(traceElement)) {
+ int returnCode = promptForOverwrite(traceElement.getDestinationElementPath());
+ // The return code is an index to a button in the dialog but the
+ // 'X' button in the window corner is not considered a button
+ // therefore it returns -1 and unfortunately, there is no
+ // constant for that.
+ if (returnCode < 0) {
+ return false;
+ }
+
+ final String[] response = new String[] { IDialogConstants.NO_TO_ALL_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.YES_LABEL };
+ if (response[returnCode].equals(IDialogConstants.YES_TO_ALL_LABEL)) {
+ break;
+ } else if (response[returnCode].equals(IDialogConstants.NO_TO_ALL_LABEL)) {
+ noToAll = true;
+ noImportTraces.add(traceElement);
+ } else if (response[returnCode].equals(IDialogConstants.NO_LABEL)) {
+ noImportTraces.add(traceElement);
+ }
+ }
+ }
+
+ // Unselect the traces that the user decided not to import
+ for (TracePackageTraceElement t : noImportTraces) {
+ for (TracePackageElement e : t.getChildren()) {
+ if (e instanceof TracePackageFilesElement) {
+ ((TracePackageFilesElement) e).setChecked(false);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean traceExists(TracePackageTraceElement traceElement) {
+ IResource traceRes = fTmfTraceFolder.getResource().findMember(traceElement.getDestinationElementPath());
+ return traceRes != null;
+ }
+
+ private int promptForOverwrite(String traceName) {
+ final MessageDialog dialog = new MessageDialog(getContainer()
+ .getShell(), null, null, MessageFormat.format(Messages.ImportTracePackageWizardPage_AlreadyExists, traceName),
+ MessageDialog.QUESTION, new String[] {
+ IDialogConstants.NO_TO_ALL_LABEL,
+ IDialogConstants.NO_LABEL,
+ IDialogConstants.YES_TO_ALL_LABEL,
+ IDialogConstants.YES_LABEL,
+ }, 3) {
+ @Override
+ protected int getShellStyle() {
+ return super.getShellStyle() | SWT.SHEET;
+ }
+ };
+ return dialog.open();
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ManifestReader.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ManifestReader.java
new file mode 100644
index 0000000000..3deb4ba1de
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/ManifestReader.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.ITracePackageConstants;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * Reads a manifest from an input stream
+ *
+ * @author Marc-Andre Laperle
+ */
+public class ManifestReader {
+
+ private static final String SCHEMA_FOLDER_NAME = "schema"; //$NON-NLS-1$
+ private static final String EXPORT_MANIFEST_SCHEMA_FILE_NAME = "export-manifest.xsd"; //$NON-NLS-1$
+ private static final TracePackageElement [] EMPTY_ARRAY = new TracePackageElement[0];
+
+ /**
+ * Validate the content of a manifest from an input stream
+ *
+ * @param input the input stream to validate from
+ * @throws IOException on error
+ */
+ public static void validateManifest(InputStream input) throws IOException
+ {
+ URL schemaFileUrl = FileLocator.find(Activator.getDefault().getBundle(), new Path(SCHEMA_FOLDER_NAME).append(EXPORT_MANIFEST_SCHEMA_FILE_NAME), null);
+ if (schemaFileUrl == null) {
+ throw new IOException(MessageFormat.format(Messages.TracePackageExtractManifestOperation_SchemaFileNotFound, EXPORT_MANIFEST_SCHEMA_FILE_NAME));
+ }
+
+ try {
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = factory.newSchema(new StreamSource(schemaFileUrl.openStream()));
+ Validator validator = schema.newValidator();
+ validator.validate(new StreamSource(input));
+ } catch (SAXException e) {
+ throw new IOException(Messages.TracePackageExtractManifestOperation_ErrorManifestNotValid, e);
+ } catch (IOException e) {
+ throw new IOException(Messages.TracePackageExtractManifestOperation_ErrorManifestNotValid, e);
+ }
+ }
+
+ /**
+ * Load package elements from a manifest (input stream)
+ *
+ * The manifest looks like this:
+ *
+ * <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ * <tmf-export>
+ * <trace name="trace2" type="org.eclipse.linuxtools.lttng2.kernel.tracetype">
+ * <file name="Traces/trace2"/> <supplementary-file name=".tracing/trace2/stateHistory.ht"/>
+ * <bookmarks>
+ * <bookmark location="4" message= "15:50:47.314 069 885, channel0_0, sys_recvmsg, fd=16, msg=0x7faada7d1ae0, flags=256" />
+ * </bookmarks>
+ * </trace>
+ * </tmf-export>
+ *
+ * See schema/export-manifest.xsd for details.
+ *
+ * @param inputStream
+ * the input stream that contains the manifest
+ * @return the loaded elements
+ * @throws IOException
+ * when an error occurs when parsing
+ * @throws SAXException
+ * when an error occurs when parsing
+ * @throws ParserConfigurationException
+ * when an error occurs when parsing
+ */
+ public static TracePackageElement[] loadElementsFromManifest(InputStream inputStream) throws IOException, SAXException, ParserConfigurationException {
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
+ Element rootElement = doc.getDocumentElement();
+ return loadElementsFromNode(rootElement);
+ }
+
+ /**
+ * Load package elements from a manifest (XML element)
+ *
+ * @param rootElement
+ * the root element to start loading from
+ * @return the loaded elements
+ */
+ public static TracePackageElement[] loadElementsFromNode(Element rootElement) {
+ List<TracePackageElement> packageElements = new ArrayList<>();
+ NodeList traceElements = rootElement.getElementsByTagName(ITracePackageConstants.TRACE_ELEMENT);
+ for (int i = 0; i < traceElements.getLength(); i++) {
+ Node traceNode = traceElements.item(i);
+ if (traceNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element traceElement = (Element) traceNode;
+ String traceName = traceElement.getAttribute(ITracePackageConstants.TRACE_NAME_ATTRIB);
+ String traceType = traceElement.getAttribute(ITracePackageConstants.TRACE_TYPE_ATTRIB);
+ TracePackageElement element = new TracePackageTraceElement(null, traceName, traceType);
+ NodeList fileElements = traceElement.getElementsByTagName(ITracePackageConstants.TRACE_FILE_ELEMENT);
+ for (int j = 0; j < fileElements.getLength(); j++) {
+ Node fileNode = fileElements.item(j);
+ if (fileNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element fileElement = (Element) fileNode;
+ String fileName = fileElement.getAttribute(ITracePackageConstants.TRACE_FILE_NAME_ATTRIB);
+ new TracePackageFilesElement(element, fileName);
+ }
+ }
+
+ // Supplementary files
+ NodeList suppFilesElements = traceElement.getElementsByTagName(ITracePackageConstants.SUPPLEMENTARY_FILE_ELEMENT);
+ if (suppFilesElements.getLength() > 0) {
+ TracePackageSupplFilesElement supplFilesElement = new TracePackageSupplFilesElement(element);
+ for (int j = 0; j < suppFilesElements.getLength(); j++) {
+ Node suppFileNode = suppFilesElements.item(j);
+ if (suppFileNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element suppFileElement = (Element) suppFileNode;
+ String fileName = suppFileElement.getAttribute(ITracePackageConstants.SUPPLEMENTARY_FILE_NAME_ATTRIB);
+ new TracePackageSupplFileElement(fileName, supplFilesElement);
+ }
+ }
+ }
+
+ // bookmarks
+ List<Map<String, String>> bookmarkAttribs = new ArrayList<>();
+ NodeList bookmarksElements = traceElement.getElementsByTagName(ITracePackageConstants.BOOKMARKS_ELEMENT);
+ for (int j = 0; j < bookmarksElements.getLength(); j++) {
+ Node bookmarksNode = bookmarksElements.item(j);
+ if (bookmarksNode.getNodeType() == Node.ELEMENT_NODE) {
+ NodeList bookmarkElements = traceElement.getElementsByTagName(ITracePackageConstants.BOOKMARK_ELEMENT);
+ for (int k = 0; k < bookmarkElements.getLength(); k++) {
+ Node bookmarkNode = bookmarkElements.item(k);
+ if (bookmarkNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element bookmarkElement = (Element) bookmarkNode;
+ NamedNodeMap attributesMap = bookmarkElement.getAttributes();
+ Map<String, String> attribs = new HashMap<>();
+ for (int l = 0; l < attributesMap.getLength(); l++) {
+ Node item = attributesMap.item(l);
+ attribs.put(item.getNodeName(), item.getNodeValue());
+ }
+ bookmarkAttribs.add(attribs);
+ }
+ }
+ }
+ }
+ if (!bookmarkAttribs.isEmpty()) {
+ new TracePackageBookmarkElement(element, bookmarkAttribs);
+ }
+
+ packageElements.add(element);
+ }
+ }
+ return packageElements.toArray(EMPTY_ARRAY);
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/Messages.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/Messages.java
new file mode 100644
index 0000000000..684a8c53c9
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/Messages.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages for the trace package export wizard
+ *
+ * @author Marc-Andre Laperle
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport.messages"; //$NON-NLS-1$
+
+ /**
+ * The message under the select trace wizard page title
+ */
+ public static String ExportTracePackageSelectTraceWizardPage_ChooseTrace;
+
+ /**
+ * The description of the project selection list
+ */
+ public static String ExportTracePackageSelectTraceWizardPage_ProjectSelection;
+
+ /**
+ * The description of the trace selection list
+ */
+ public static String ExportTracePackageSelectTraceWizardPage_TraceSelection;
+
+ /**
+ * Dialog text when target file already exists
+ */
+ public static String ExportTracePackageWizardPage_AlreadyExitst;
+
+ /**
+ * The approximate size label
+ */
+ public static String ExportTracePackageWizardPage_ApproximateSizeLbl;
+
+ /**
+ * The message under the wizard page title
+ */
+ public static String ExportTracePackageWizardPage_ChooseContent;
+
+ /**
+ * Text for the compress contents checkbox
+ */
+ public static String ExportTracePackageWizardPage_CompressContents;
+
+ /**
+ * Text for the first column (content)
+ */
+ public static String ExportTracePackageWizardPage_ContentColumnName;
+
+ /**
+ * Text for the options group
+ */
+ public static String ExportTracePackageWizardPage_Options;
+
+ /**
+ * Text for the tar format option
+ */
+ public static String ExportTracePackageWizardPage_SaveInTarFormat;
+
+ /**
+ * Text for the zip format option
+ */
+ public static String ExportTracePackageWizardPage_SaveInZipFormat;
+
+ /**
+ * Byte units
+ */
+ public static String ExportTracePackageWizardPage_SizeByte;
+
+ /**
+ * Text for the second column (size)
+ */
+ public static String ExportTracePackageWizardPage_SizeColumnName;
+
+ /**
+ * Gigabyte units
+ */
+ public static String ExportTracePackageWizardPage_SizeGigabyte;
+
+ /**
+ * Kilobyte units
+ */
+ public static String ExportTracePackageWizardPage_SizeKilobyte;
+
+ /**
+ * Megabyte units
+ */
+ public static String ExportTracePackageWizardPage_SizeMegabyte;
+
+ /**
+ * Terabyte units
+ */
+ public static String ExportTracePackageWizardPage_SizeTerabyte;
+
+ /**
+ * Title for the wizard page
+ */
+ public static String ExportTracePackageWizardPage_Title;
+
+ /**
+ * Label for the file path
+ */
+ public static String ExportTracePackageWizardPage_ToArchive;
+
+ /**
+ * Dialog text when a trace with the same name already exists
+ */
+ public static String ImportTracePackageWizardPage_AlreadyExists;
+
+ /**
+ * Title for the import page
+ */
+ public static String ImportTracePackageWizardPage_Title;
+
+ /**
+ * Text for the source archive label
+ */
+ public static String ImportTracePackageWizardPage_FromArchive;
+
+ /**
+ * Text for the reading package job
+ */
+ public static String ImportTracePackageWizardPage_ReadingPackage;
+
+ /**
+ * Message when file is not found
+ */
+ public static String ImportTracePackageWizardPage_ErrorFileNotFound;
+
+ /**
+ * Message when trace type could not be set
+ */
+ public static String ImportTracePackageWizardPage_ErrorSettingTraceType;
+
+ /**
+ * Message when the trace could not be found after importing the files
+ */
+ public static String ImportTracePackageWizardPage_ErrorFindingImportedTrace;
+
+ /**
+ * The message displayed under the title
+ */
+ public static String ImportTracePackageWizardPage_Message;
+
+ /**
+ * Generic error message for the import operation
+ */
+ public static String ImportTracePackageWizardPage_ErrorOperation;
+
+ /**
+ * Project text label
+ */
+ public static String ImportTracePackageWizardPage_Project;
+
+ /**
+ * The select project button text
+ */
+ public static String ImportTracePackageWizardPage_SelectProjectButton;
+
+ /**
+ * The select project dialog title
+ */
+ public static String ImportTracePackageWizardPage_SelectProjectDialogTitle;
+
+ /**
+ * Text for the generating package job
+ */
+ public static String TracePackageExportOperation_GeneratingPackage;
+
+ /**
+ * Text when error occurs creating a bookmark
+ */
+ public static String TracePackageImportOperation_ErrorCreatingBookmark;
+
+ /**
+ * Text for the detecting trace type job
+ */
+ public static String TracePackageImportOperation_DetectingTraceType;
+
+ /**
+ * Text when error occurs creating a bookmark file
+ */
+ public static String TracePackageImportOperation_ErrorCreatingBookmarkFile;
+
+ /**
+ * Text for the importing package job
+ */
+ public static String TracePackageImportOperation_ImportingPackage;
+
+ /**
+ * Text when error occurs when the manifest is not found in the archive
+ */
+ public static String TracePackageExtractManifestOperation_ErrorManifestNotFound;
+
+ /**
+ * Text when error occurs when the manifest is not valid
+ */
+ public static String TracePackageExtractManifestOperation_ErrorManifestNotValid;
+
+ /**
+ * Generic error message when reading the manifest
+ */
+ public static String TracePackageExtractManifestOperation_ErrorReadingManifest;
+
+ /**
+ * Error message when the file is an invalid format
+ */
+ public static String TracePackageExtractManifestOperation_InvalidFormat;
+
+ /**
+ * Error when the schema file cannot be found to validate the export
+ * manifest
+ */
+ public static String TracePackageExtractManifestOperation_SchemaFileNotFound;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExportOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExportOperation.java
new file mode 100644
index 0000000000..5170c32e9a
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExportOperation.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.ITracePackageConstants;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
+import org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileExportOperation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * An operation that exports a trace package to an archive
+ *
+ * @author Marc-Andre Laperle
+ */
+@SuppressWarnings("restriction")
+public class TracePackageExportOperation extends AbstractTracePackageOperation {
+
+ private static final String TRACE_EXPORT_TEMP_FOLDER = ".traceExport"; //$NON-NLS-1$
+
+ private final TracePackageTraceElement[] fTraceExportElements;
+ private final boolean fUseCompression;
+ private final boolean fUseTar;
+ private final Set<IResource> fResources;
+ private IFolder fExportFolder;
+
+ /**
+ * Constructs a new export operation
+ *
+ * @param traceExportElements
+ * the trace elements to be exported
+ * @param useCompression
+ * whether or not to use compression
+ * @param useTar
+ * use tar format or zip
+ * @param fileName
+ * the output file name
+ */
+ public TracePackageExportOperation(TracePackageTraceElement[] traceExportElements, boolean useCompression, boolean useTar, String fileName) {
+ super(fileName);
+ fTraceExportElements = traceExportElements;
+ fUseCompression = useCompression;
+ fUseTar = useTar;
+ fResources = new HashSet<>();
+ }
+
+ /**
+ * Run the operation. The status (result) of the operation can be obtained
+ * with {@link #getStatus}
+ *
+ * @param progressMonitor
+ * the progress monitor to use to display progress and receive
+ * requests for cancellation
+ */
+ @Override
+ public void run(IProgressMonitor progressMonitor) {
+
+ try {
+ int totalWork = getNbCheckedElements(fTraceExportElements) * 2;
+ progressMonitor.beginTask(Messages.TracePackageExportOperation_GeneratingPackage, totalWork);
+
+ fExportFolder = createExportFolder(progressMonitor);
+
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ Element createElement = doc.createElement(ITracePackageConstants.TMF_EXPORT_ELEMENT);
+ Node tmfNode = doc.appendChild(createElement);
+
+ for (TracePackageTraceElement tracePackageElement : fTraceExportElements) {
+ if (!isFilesChecked(tracePackageElement)) {
+ continue;
+ }
+
+ exportTrace(progressMonitor, tmfNode, tracePackageElement);
+ }
+
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
+ DOMSource source = new DOMSource(doc);
+ StringWriter buffer = new StringWriter();
+ StreamResult result = new StreamResult(buffer);
+ transformer.transform(source, result);
+ String content = buffer.getBuffer().toString();
+
+ ModalContext.checkCanceled(progressMonitor);
+
+ exportManifest(content);
+
+ setStatus(exportToArchive(progressMonitor, totalWork));
+
+ fExportFolder.delete(true, new SubProgressMonitor(progressMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+
+ progressMonitor.done();
+
+ } catch (InterruptedException e) {
+ setStatus(Status.CANCEL_STATUS);
+ } catch (Exception e) {
+ setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e));
+ }
+ }
+
+ private IFolder createExportFolder(IProgressMonitor monitor) throws CoreException {
+ IFolder folder = fTraceExportElements[0].getTraceElement().getProject().getResource().getFolder(TRACE_EXPORT_TEMP_FOLDER);
+ if (folder.exists()) {
+ folder.delete(true, null);
+ }
+ folder.create(IResource.FORCE | IResource.HIDDEN, true, new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+ return folder;
+ }
+
+ private void exportTrace(IProgressMonitor monitor, Node tmfNode, TracePackageTraceElement tracePackageElement) throws InterruptedException, CoreException {
+ TmfTraceElement traceElement = tracePackageElement.getTraceElement();
+ Element traceXmlElement = tmfNode.getOwnerDocument().createElement(ITracePackageConstants.TRACE_ELEMENT);
+ traceXmlElement.setAttribute(ITracePackageConstants.TRACE_NAME_ATTRIB, traceElement.getResource().getName());
+ traceXmlElement.setAttribute(ITracePackageConstants.TRACE_TYPE_ATTRIB, traceElement.getTraceType());
+ Node traceNode = tmfNode.appendChild(traceXmlElement);
+
+ for (TracePackageElement element : tracePackageElement.getChildren()) {
+ ModalContext.checkCanceled(monitor);
+ if (!element.isChecked()) {
+ continue;
+ }
+
+ if (element instanceof TracePackageSupplFilesElement) {
+ exportSupplementaryFiles(monitor, traceNode, traceElement, (TracePackageSupplFilesElement) element);
+ } else if (element instanceof TracePackageBookmarkElement) {
+ exportBookmarks(monitor, traceNode, (TracePackageBookmarkElement) element);
+ } else if (element instanceof TracePackageFilesElement) {
+ exportTraceFiles(monitor, traceNode, (TracePackageFilesElement) element);
+ }
+
+ monitor.worked(1);
+ }
+ }
+
+ private void exportSupplementaryFiles(IProgressMonitor monitor, Node traceNode, TmfTraceElement traceElement, TracePackageSupplFilesElement element) throws InterruptedException, CoreException {
+ Document doc = traceNode.getOwnerDocument();
+ if (element.getChildren().length > 0) {
+
+ IPath projectPath = traceElement.getProject().getPath();
+
+ for (TracePackageElement child : element.getChildren()) {
+ TracePackageSupplFileElement supplFile = (TracePackageSupplFileElement) child;
+ ModalContext.checkCanceled(monitor);
+ IResource res = supplFile.getResource();
+ // project/.tracing/A/B/statistics.ht -> .tracing/A/B/statistics.ht
+ IPath relativeToExportFolder = res.getFullPath().makeRelativeTo(projectPath);
+
+ // project/.traceExport/.tracing/A/B
+ IFolder folder = fExportFolder.getFolder(relativeToExportFolder.removeLastSegments(1));
+ TraceUtils.createFolder(folder, new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+
+ res.refreshLocal(0, new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+ createExportResource(folder, res);
+ Element suppFileElement = doc.createElement(ITracePackageConstants.SUPPLEMENTARY_FILE_ELEMENT);
+
+ suppFileElement.setAttribute(ITracePackageConstants.SUPPLEMENTARY_FILE_NAME_ATTRIB, relativeToExportFolder.toString());
+ traceNode.appendChild(suppFileElement);
+ }
+
+ IFolder suppFilesFolder = fExportFolder.getFolder(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
+ fResources.add(suppFilesFolder);
+ }
+ }
+
+ private void exportTraceFiles(IProgressMonitor monitor, Node traceNode, TracePackageFilesElement element) throws CoreException {
+ Document doc = traceNode.getOwnerDocument();
+ TmfTraceElement traceElement = ((TracePackageTraceElement) element.getParent()).getTraceElement();
+ IResource resource = traceElement.getResource();
+ IPath traceFolderPath = traceElement.getProject().getTracesFolder().getPath();
+
+ // project/Traces/A/B/Kernel -> A/B/Kernel
+ IPath relativeToExportFolder = resource.getFullPath().makeRelativeTo(traceFolderPath);
+
+ // project/.traceExport/A/B
+ IFolder folder = fExportFolder.getFolder(relativeToExportFolder.removeLastSegments(1));
+ TraceUtils.createFolder(folder, new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+
+ createExportResource(folder, resource);
+ Element fileElement = doc.createElement(ITracePackageConstants.TRACE_FILE_ELEMENT);
+
+ fileElement.setAttribute(ITracePackageConstants.TRACE_FILE_NAME_ATTRIB, relativeToExportFolder.toString());
+ traceNode.appendChild(fileElement);
+
+ // Always export the top-most folder containing the trace or the trace itself
+ IResource exportedResource = fExportFolder.findMember(relativeToExportFolder.segment(0));
+ fResources.add(exportedResource);
+ }
+
+ /**
+ * Creates a linked resource in the specified folder
+ *
+ * @param exportFolder the folder that will contain the linked resource
+ * @param res the resource to export
+ * @throws CoreException when createLink fails
+ * @return the created linked resource
+ */
+ private static IResource createExportResource(IFolder exportFolder, IResource res) throws CoreException {
+ IResource ret = null;
+ // Note: The resources cannot be HIDDEN or else they are ignored by ArchiveFileExportOperation
+ if (res instanceof IFolder) {
+ IFolder folder = exportFolder.getFolder(res.getName());
+ folder.createLink(res.getLocationURI(), IResource.NONE, null);
+ ret = folder;
+ } else if (res instanceof IFile) {
+ IFile file = exportFolder.getFile(res.getName());
+ file.createLink(res.getLocationURI(), IResource.NONE, null);
+ ret = file;
+ }
+ return ret;
+ }
+
+ private static void exportBookmarks(IProgressMonitor monitor, Node traceNode, TracePackageBookmarkElement element) throws CoreException, InterruptedException {
+ Document doc = traceNode.getOwnerDocument();
+ IFile bookmarksFile = ((TracePackageTraceElement) element.getParent()).getTraceElement().getBookmarksFile();
+ if (bookmarksFile != null && bookmarksFile.exists()) {
+ IMarker[] findMarkers = bookmarksFile.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO);
+ if (findMarkers.length > 0) {
+ Element bookmarksXmlElement = doc.createElement(ITracePackageConstants.BOOKMARKS_ELEMENT);
+ Node bookmarksNode = traceNode.appendChild(bookmarksXmlElement);
+
+ for (IMarker marker : findMarkers) {
+ ModalContext.checkCanceled(monitor);
+
+ Element singleBookmarkXmlElement = doc.createElement(ITracePackageConstants.BOOKMARK_ELEMENT);
+ for (String key : marker.getAttributes().keySet()) {
+ singleBookmarkXmlElement.setAttribute(key, marker.getAttribute(key).toString());
+ }
+
+ bookmarksNode.appendChild(singleBookmarkXmlElement);
+ }
+ }
+ }
+ }
+
+ private void exportManifest(String content) throws CoreException {
+ IFile file = fExportFolder.getFile(ITracePackageConstants.MANIFEST_FILENAME);
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes());
+ if (file.exists()) {
+ file.setContents(inputStream, IResource.FORCE, null);
+ } else {
+ file.create(inputStream, IResource.FORCE | IResource.HIDDEN, null);
+ }
+ fResources.add(file);
+ }
+
+ private IStatus exportToArchive(IProgressMonitor monitor, int totalWork) throws InvocationTargetException, InterruptedException {
+ ArchiveFileExportOperation op = new ArchiveFileExportOperation(new ArrayList<>(fResources), getFileName());
+ op.setCreateLeadupStructure(false);
+ op.setUseCompression(fUseCompression);
+ op.setUseTarFormat(fUseTar);
+ op.run(new SubProgressMonitor(monitor, totalWork / 2, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+
+ return op.getStatus();
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExtractManifestOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExtractManifestOperation.java
new file mode 100644
index 0000000000..b31e01fc41
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageExtractManifestOperation.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.ITracePackageConstants;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
+
+/**
+ * An operation that extracts information from the manifest located in an
+ * archive
+ *
+ * @author Marc-Andre Laperle
+ */
+public class TracePackageExtractManifestOperation extends AbstractTracePackageOperation {
+
+ /**
+ * Constructs a new import operation for reading the manifest
+ *
+ * @param fileName
+ * the output file name
+ */
+ public TracePackageExtractManifestOperation(String fileName) {
+ super(fileName);
+ }
+
+ /**
+ * Run extract the manifest operation. The status (result) of the operation
+ * can be obtained with {@link #getStatus}
+ *
+ * @param progressMonitor
+ * the progress monitor to use to display progress and receive
+ * requests for cancellation
+ */
+ @Override
+ public void run(IProgressMonitor progressMonitor) {
+ TracePackageElement[] elements = null;
+ try {
+ progressMonitor.worked(1);
+ ArchiveFile archiveFile = getSpecifiedArchiveFile();
+ progressMonitor.worked(1);
+ if (archiveFile == null) {
+ setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.TracePackageExtractManifestOperation_InvalidFormat));
+ return;
+ }
+
+ Enumeration<?> entries = archiveFile.entries();
+
+ boolean found = false;
+ while (entries.hasMoreElements()) {
+ ModalContext.checkCanceled(progressMonitor);
+
+ ArchiveEntry entry = (ArchiveEntry) entries.nextElement();
+ IPath p = new Path(entry.getName());
+ //Remove project name
+ p = p.removeFirstSegments(1);
+
+ if (entry.getName().endsWith(ITracePackageConstants.MANIFEST_FILENAME)) {
+ found = true;
+ InputStream inputStream = archiveFile.getInputStream(entry);
+ ManifestReader.validateManifest(inputStream);
+
+ inputStream = archiveFile.getInputStream(entry);
+ elements = ManifestReader.loadElementsFromManifest(inputStream);
+ break;
+ }
+
+ progressMonitor.worked(1);
+ }
+
+ if (found) {
+ setStatus(Status.OK_STATUS);
+ }
+ else {
+ elements = generateElementsFromArchive();
+ if (elements.length > 0) {
+ setStatus(Status.OK_STATUS);
+ } else {
+ setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.TracePackageExtractManifestOperation_ErrorManifestNotFound, ITracePackageConstants.MANIFEST_FILENAME)));
+ }
+ }
+
+ setResultElements(elements);
+
+ } catch (InterruptedException e) {
+ setStatus(Status.CANCEL_STATUS);
+ } catch (Exception e) {
+ setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.TracePackageExtractManifestOperation_ErrorReadingManifest, e));
+ }
+ }
+
+ private TracePackageElement[] generateElementsFromArchive() {
+ ArchiveFile archiveFile = getSpecifiedArchiveFile();
+ Enumeration<?> entries = archiveFile.entries();
+ Set<String> traceFileNames = new HashSet<>();
+ while (entries.hasMoreElements()) {
+ ArchiveEntry entry = (ArchiveEntry) entries.nextElement();
+ String entryName = entry.getName();
+ IPath fullArchivePath = new Path(entryName);
+ if (!fullArchivePath.hasTrailingSeparator() && fullArchivePath.segmentCount() > 0) {
+ traceFileNames.add(fullArchivePath.segment(0));
+ }
+ }
+
+ List<TracePackageElement> packageElements = new ArrayList<>();
+ for (String traceFileName : traceFileNames) {
+ TracePackageTraceElement traceElement = new TracePackageTraceElement(null, traceFileName, null);
+ new TracePackageFilesElement(traceElement, traceFileName);
+ packageElements.add(traceElement);
+ }
+
+ return packageElements.toArray(new TracePackageElement[] {});
+ }
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java
new file mode 100644
index 0000000000..0a9a863a1a
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java
@@ -0,0 +1,493 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2015 Ericsson
+ *
+ * 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:
+ * Marc-Andre Laperle - Initial API and implementation
+ * Patrick Tasse - Add support for source location
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.importexport;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFileElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageSupplFilesElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
+import org.eclipse.tracecompass.tmf.ui.editors.TmfEventsEditor;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.internal.wizards.datatransfer.TarException;
+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+
+/**
+ * An operation that imports a trace package from an archive
+ *
+ * @author Marc-Andre Laperle
+ */
+@SuppressWarnings("restriction")
+public class TracePackageImportOperation extends AbstractTracePackageOperation implements IOverwriteQuery {
+
+ private final TracePackageElement[] fImportTraceElements;
+ private final TmfTraceFolder fTmfTraceFolder;
+
+ /**
+ * Constructs a new import operation
+ *
+ * @param importTraceElements
+ * the trace element to be imported
+ * @param fileName
+ * the output file name
+ * @param tmfTraceFolder
+ * the destination folder
+ */
+ public TracePackageImportOperation(String fileName, TracePackageElement[] importTraceElements, TmfTraceFolder tmfTraceFolder) {
+ super(fileName);
+ fImportTraceElements = importTraceElements;
+ fTmfTraceFolder = tmfTraceFolder;
+ }
+
+ private class ImportProvider implements IImportStructureProvider {
+
+ private Exception fException;
+
+ @Override
+ public List getChildren(Object element) {
+ return null;
+ }
+
+ @Override
+ public InputStream getContents(Object element) {
+ InputStream inputStream = null;
+ // We can add throws
+ try {
+ inputStream = ((ArchiveProviderElement) element).getContents();
+ } catch (IOException e) {
+ fException = e;
+ } catch (TarException e) {
+ fException = e;
+ }
+ return inputStream;
+ }
+
+ @Override
+ public String getFullPath(Object element) {
+ return ((ArchiveProviderElement) element).getFullPath();
+ }
+
+ @Override
+ public String getLabel(Object element) {
+ return ((ArchiveProviderElement) element).getLabel();
+ }
+
+ @Override
+ public boolean isFolder(Object element) {
+ return ((ArchiveProviderElement) element).isFolder();
+ }
+
+ public Exception getException() {
+ return fException;
+ }
+ }
+
+ private class ArchiveProviderElement {
+
+ private final String fPath;
+ private final String fLabel;
+
+ private ArchiveFile fArchiveFile;
+ private ArchiveEntry fEntry;
+
+ public ArchiveProviderElement(String destinationPath, String label, ArchiveFile archiveFile, ArchiveEntry entry) {
+ fPath = destinationPath;
+ fLabel = label;
+ this.fArchiveFile = archiveFile;
+ this.fEntry = entry;
+ }
+
+ public InputStream getContents() throws TarException, IOException {
+ return fArchiveFile.getInputStream(fEntry);
+ }
+
+ public String getFullPath() {
+ return fPath;
+ }
+
+ public String getLabel() {
+ return fLabel;
+ }
+
+ public boolean isFolder() {
+ return false;
+ }
+ }
+
+ /**
+ * Run the operation. The status (result) of the operation can be obtained
+ * with {@link #getStatus}
+ *
+ * @param progressMonitor
+ * the progress monitor to use to display progress and receive
+ * requests for cancellation
+ */
+ @Override
+ public void run(IProgressMonitor progressMonitor) {
+ int totalWork = getNbCheckedElements(fImportTraceElements) * 2;
+ progressMonitor.beginTask(Messages.TracePackageImportOperation_ImportingPackage, totalWork);
+ doRun(progressMonitor);
+ progressMonitor.done();
+ }
+
+ private void doRun(IProgressMonitor progressMonitor) {
+ try {
+ setStatus(deleteExistingTraces(progressMonitor));
+ if (getStatus().getSeverity() != IStatus.OK) {
+ return;
+ }
+
+ TracePackageFilesElement traceFilesElement = null;
+ for (TracePackageElement packageElement : fImportTraceElements) {
+ TracePackageTraceElement traceElement = (TracePackageTraceElement) packageElement;
+ if (!isFilesChecked(packageElement)) {
+ continue;
+ }
+
+ TracePackageElement[] children = traceElement.getChildren();
+ for (TracePackageElement element : children) {
+ ModalContext.checkCanceled(progressMonitor);
+
+ if (element instanceof TracePackageFilesElement) {
+ traceFilesElement = (TracePackageFilesElement) element;
+ setStatus(importTraceFiles(traceFilesElement, traceElement, progressMonitor));
+
+ } else if (element instanceof TracePackageSupplFilesElement) {
+ TracePackageSupplFilesElement suppFilesElement = (TracePackageSupplFilesElement) element;
+ setStatus(importSupplFiles(suppFilesElement, traceElement, progressMonitor));
+ }
+
+ if (getStatus().getSeverity() != IStatus.OK) {
+ return;
+ }
+ }
+ }
+
+ } catch (InterruptedException e) {
+ setStatus(Status.CANCEL_STATUS);
+ }
+ }
+
+ /**
+ * Returns whether or not the Files element is checked under the given trace
+ * package element
+ *
+ * @param tracePackageElement
+ * the trace package element
+ * @return whether or not the Files element is checked under the given trace
+ * package element
+ */
+ public static boolean isFilesChecked(TracePackageElement tracePackageElement) {
+ for (TracePackageElement element : tracePackageElement.getChildren()) {
+ if (element instanceof TracePackageFilesElement) {
+ return element.isChecked();
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return the matching TmfTraceElement for a given trace element.
+ */
+ private TmfTraceElement getMatchingTraceElement(TracePackageTraceElement tracePackageElement) {
+ IPath tracePath = fTmfTraceFolder.getPath().append(tracePackageElement.getDestinationElementPath());
+ List<TmfTraceElement> traces = fTmfTraceFolder.getTraces();
+ for (TmfTraceElement t : traces) {
+ if (t.getPath().equals(tracePath)) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+
+ private IStatus deleteExistingTraces(IProgressMonitor progressMonitor) {
+ for (TracePackageElement packageElement : fImportTraceElements) {
+ TracePackageTraceElement traceElement = (TracePackageTraceElement) packageElement;
+ if (!isFilesChecked(traceElement)) {
+ continue;
+ }
+
+ TmfTraceElement existingTrace = getMatchingTraceElement(traceElement);
+ if (existingTrace != null) {
+ try {
+ existingTrace.delete(new SubProgressMonitor(progressMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+ } catch (CoreException e) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
+ }
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private void importBookmarks(IResource traceRes, TracePackageTraceElement traceElement, IProgressMonitor monitor) {
+ for (TracePackageElement o : traceElement.getChildren()) {
+ if (o instanceof TracePackageBookmarkElement && o.isChecked()) {
+
+ // Get element
+ IFile bookmarksFile = null;
+ TmfTraceElement tmfTraceElement = getMatchingTraceElement(traceElement);
+ if (tmfTraceElement != null) {
+ try {
+ bookmarksFile = tmfTraceElement.createBookmarksFile();
+
+ // Make sure that if a bookmark is double-clicked first
+ // before opening the trace, it opens the right editor
+
+ // Get the editor id from the extension point
+ String traceEditorId = tmfTraceElement.getEditorId();
+ final String editorId = (traceEditorId != null) ? traceEditorId : TmfEventsEditor.ID;
+ IDE.setDefaultEditor(bookmarksFile, editorId);
+
+ } catch (CoreException e) {
+ Activator.getDefault().logError(MessageFormat.format(Messages.TracePackageImportOperation_ErrorCreatingBookmarkFile, traceRes.getName()), e);
+ }
+ }
+
+ if (bookmarksFile == null) {
+ break;
+ }
+
+ TracePackageBookmarkElement bookmarkElement = (TracePackageBookmarkElement) o;
+
+ List<Map<String, String>> bookmarks = bookmarkElement.getBookmarks();
+ for (Map<String, String> attrs : bookmarks) {
+ IMarker createMarker = null;
+ try {
+ createMarker = bookmarksFile.createMarker(IMarker.BOOKMARK);
+ } catch (CoreException e) {
+ Activator.getDefault().logError(MessageFormat.format(Messages.TracePackageImportOperation_ErrorCreatingBookmark, traceRes.getName()), e);
+ }
+ if (createMarker != null && createMarker.exists()) {
+ try {
+ for (Entry<String, String> entry : attrs.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ if (key.equals(IMarker.LOCATION)) {
+ createMarker.setAttribute(IMarker.LOCATION, Integer.valueOf(value).intValue());
+ } else {
+ createMarker.setAttribute(key, value);
+ }
+ }
+ } catch (CoreException e) {
+ Activator.getDefault().logError(MessageFormat.format(Messages.TracePackageImportOperation_ErrorCreatingBookmark, traceRes.getName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ monitor.worked(1);
+ }
+
+ private IStatus importTraceFiles(TracePackageFilesElement traceFilesElement, TracePackageTraceElement traceElement, IProgressMonitor monitor) {
+ List<Pair<String, String>> fileNameAndLabelPairs = new ArrayList<>();
+
+ String sourceName = checkNotNull(traceFilesElement.getFileName());
+ String destinationName = checkNotNull(traceElement.getImportName());
+
+ fileNameAndLabelPairs.add(new Pair<>(sourceName, destinationName));
+
+ IPath containerPath = fTmfTraceFolder.getPath();
+ IStatus status = importFiles(getSpecifiedArchiveFile(), fileNameAndLabelPairs, containerPath, Path.EMPTY, monitor);
+ if (getStatus().getSeverity() != IStatus.OK) {
+ return status;
+ }
+
+ // We need to set the trace type before importing the supplementary files so we do it here
+ IResource traceRes = fTmfTraceFolder.getResource().findMember(traceElement.getDestinationElementPath());
+ if (traceRes == null || !traceRes.exists()) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.ImportTracePackageWizardPage_ErrorFindingImportedTrace, destinationName));
+ }
+
+ TraceTypeHelper traceType = null;
+ String traceTypeStr = traceElement.getTraceType();
+ if (traceTypeStr != null) {
+ traceType = TmfTraceType.getTraceType(traceTypeStr);
+ if (traceType == null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.ImportTracePackageWizardPage_ErrorSettingTraceType, traceElement.getTraceType(), destinationName));
+ }
+ } else {
+ try {
+ monitor.subTask(MessageFormat.format(Messages.TracePackageImportOperation_DetectingTraceType, destinationName));
+ traceType = TmfTraceTypeUIUtils.selectTraceType(traceRes.getLocation().toOSString(), null, null);
+ } catch (TmfTraceImportException e) {
+ // Could not figure out the type
+ }
+ }
+
+ if (traceType != null) {
+ try {
+ TmfTraceTypeUIUtils.setTraceType(traceRes, traceType);
+ } catch (CoreException e) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.ImportTracePackageWizardPage_ErrorSettingTraceType, traceElement.getTraceType(), destinationName), e);
+ }
+ }
+
+ importBookmarks(traceRes, traceElement, monitor);
+
+ try {
+ URI uri = new File(getFileName()).toURI();
+ IPath entryPath = new Path(traceFilesElement.getFileName());
+ if (traceRes instanceof IFolder) {
+ entryPath = entryPath.addTrailingSeparator();
+ }
+ String sourceLocation = URIUtil.toUnencodedString(URIUtil.toJarURI(uri, entryPath));
+ traceRes.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+ } catch (CoreException e) {
+ }
+
+ return status;
+ }
+
+ private IStatus importSupplFiles(TracePackageSupplFilesElement suppFilesElement, TracePackageTraceElement traceElement, IProgressMonitor monitor) {
+ List<Pair<String, String>> fileNameAndLabelPairs = new ArrayList<>();
+ for (TracePackageElement child : suppFilesElement.getChildren()) {
+ if (child.isChecked()) {
+ TracePackageSupplFileElement supplFile = (TracePackageSupplFileElement) child;
+ fileNameAndLabelPairs.add(new Pair<>(checkNotNull(supplFile.getText()), checkNotNull(new Path(supplFile.getText()).lastSegment())));
+ }
+ }
+
+ if (!fileNameAndLabelPairs.isEmpty()) {
+ TmfTraceElement existingTrace = getMatchingTraceElement(traceElement);
+ if (existingTrace != null) {
+ ArchiveFile archiveFile = getSpecifiedArchiveFile();
+ existingTrace.refreshSupplementaryFolder();
+ // Project/Traces/A/B -> A/B
+ IPath traceFolderRelativePath = fTmfTraceFolder.getPath().makeRelativeTo(fTmfTraceFolder.getProject().getTracesFolder().getPath());
+ // Project/.tracing/A/B/
+ IFolder traceSupplementaryFolder = fTmfTraceFolder.getTraceSupplementaryFolder(traceFolderRelativePath.toString());
+ IPath destinationContainerPath = traceSupplementaryFolder.getFullPath();
+ // Remove the .tracing segment at the beginnin so that a file in folder .tracing/A/B/ imports destinationContainerPath/A/B/
+ Path baseSourcePath = new Path(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
+ return importFiles(archiveFile, fileNameAndLabelPairs, destinationContainerPath, baseSourcePath, monitor);
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private IStatus importFiles(ArchiveFile archiveFile, List<Pair<String, String>> fileNameAndLabelPairs, IPath destinationContainerPath, IPath baseSourcePath, IProgressMonitor monitor) {
+ List<ArchiveProviderElement> objects = new ArrayList<>();
+ Enumeration<?> entries = archiveFile.entries();
+ while (entries.hasMoreElements()) {
+ ArchiveEntry entry = (ArchiveEntry) entries.nextElement();
+ String entryName = entry.getName();
+ IPath fullArchivePath = new Path(entryName);
+ if (fullArchivePath.hasTrailingSeparator()) {
+ // We only care about file entries as the folders will get created by the ImportOperation
+ continue;
+ }
+
+ for (Pair<String, String> fileNameAndLabel : fileNameAndLabelPairs) {
+
+ // Examples: Traces/aaa/kernel/ .tracing/aaa/testtexttrace.txt/statistics.ht
+ IPath searchedArchivePath = new Path(fileNameAndLabel.getFirst());
+
+ // Check if this archive entry matches the searched file name at this archive location
+ boolean fileMatch = entryName.equalsIgnoreCase(searchedArchivePath.toString());
+ // For example Traces/aaa/kernel/metadata matches Traces/aaa/kernel/
+ boolean folderMatch = entryName.startsWith(searchedArchivePath + "/"); //$NON-NLS-1$
+
+ if (fileMatch || folderMatch) {
+ // .tracing/aaa/testtexttrace.txt/statistics.ht -> aaa/testtexttrace.txt/statistics.ht
+ IPath destinationPath = fullArchivePath.makeRelativeTo(baseSourcePath);
+
+ // metadata statistics.ht
+ // We don't use the label when the entry is a folder match because the labels for individual files
+ // under the folder are not specified in the manifest so just use the last segment.
+ String resourceLabel = folderMatch ? fullArchivePath.lastSegment() : fileNameAndLabel.getSecond();
+
+ ArchiveProviderElement pe = new ArchiveProviderElement(destinationPath.toString(), resourceLabel, archiveFile, entry);
+ objects.add(pe);
+ break;
+ }
+ }
+ }
+
+ ImportProvider provider = new ImportProvider();
+
+ ImportOperation operation = new ImportOperation(destinationContainerPath,
+ null, provider, this,
+ objects);
+ operation.setCreateContainerStructure(true);
+ operation.setOverwriteResources(true);
+
+ try {
+ operation.run(new SubProgressMonitor(monitor, fileNameAndLabelPairs.size(), SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+ archiveFile.close();
+ } catch (InvocationTargetException e) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
+ } catch (InterruptedException e) {
+ return Status.CANCEL_STATUS;
+ } catch (IOException e) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, e);
+ }
+
+ if (provider.getException() != null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.Messages.TracePackage_ErrorOperation, provider.getException());
+ }
+
+ return operation.getStatus();
+ }
+
+ @Override
+ public String queryOverwrite(String pathString) {
+ // We always overwrite once we reach this point
+ return null;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/messages.properties
new file mode 100644
index 0000000000..375a6f2363
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/messages.properties
@@ -0,0 +1,53 @@
+###############################################################################
+# Copyright (c) 2013, 2014 Ericsson
+#
+# 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:
+# Marc-Andre Laperle - Initial API and implementation
+###############################################################################
+
+ExportTracePackageSelectTraceWizardPage_ChooseTrace=Choose traces to export
+ExportTracePackageSelectTraceWizardPage_ProjectSelection=Project
+ExportTracePackageSelectTraceWizardPage_TraceSelection=Traces
+ExportTracePackageWizardPage_AlreadyExitst = Target file already exists. Would you like to overwrite it?
+ExportTracePackageWizardPage_ApproximateSizeLbl=Approximate uncompressed size: {0}
+ExportTracePackageWizardPage_ChooseContent=Choose the content to export
+ExportTracePackageWizardPage_CompressContents=Co&mpress the contents of the file
+ExportTracePackageWizardPage_ContentColumnName=Content
+ExportTracePackageWizardPage_Options=Options
+ExportTracePackageWizardPage_SaveInTarFormat=Sa&ve in tar format
+ExportTracePackageWizardPage_SaveInZipFormat=Save in &zip format
+ExportTracePackageWizardPage_SizeByte=B
+ExportTracePackageWizardPage_SizeColumnName=Size
+ExportTracePackageWizardPage_SizeGigabyte=GB
+ExportTracePackageWizardPage_SizeKilobyte=KB
+ExportTracePackageWizardPage_SizeMegabyte=MB
+ExportTracePackageWizardPage_SizeTerabyte=TB
+ExportTracePackageWizardPage_Title=Export trace package
+ExportTracePackageWizardPage_ToArchive=To &archive file:
+ImportTracePackageWizardPage_AlreadyExists=A trace with the name ''{0}'' already exists. Would you like to overwrite it?
+ImportTracePackageWizardPage_ErrorFileNotFound=File does not exist
+ImportTracePackageWizardPage_ErrorOperation=Error occurred during import trace operation
+ImportTracePackageWizardPage_ErrorSettingTraceType=Error setting the type {0} for the trace {1}
+ImportTracePackageWizardPage_ErrorFindingImportedTrace=Could not find the imported trace {0} in the workspace
+ImportTracePackageWizardPage_FromArchive=From &archive file:
+ImportTracePackageWizardPage_Message=Choose the content to import
+ImportTracePackageWizardPage_Project=Into project:
+ImportTracePackageWizardPage_ReadingPackage=Reading package
+ImportTracePackageWizardPage_SelectProjectButton=Select
+ImportTracePackageWizardPage_SelectProjectDialogTitle=Select project
+ImportTracePackageWizardPage_Title=Import trace package
+TracePackageExportOperation_GeneratingPackage=Generating package
+TracePackageExtractManifestOperation_ErrorManifestNotFound=The required manifest file {0} could not be found.
+TracePackageExtractManifestOperation_ErrorManifestNotValid=The manifest file is not valid.
+TracePackageExtractManifestOperation_ErrorReadingManifest=An error occurred when reading the manifest
+TracePackageExtractManifestOperation_InvalidFormat=The selected file is not a supported file format
+TracePackageExtractManifestOperation_SchemaFileNotFound=The schema file {0} could not be found.
+TracePackageImportOperation_ErrorCreatingBookmark=Error creating bookmark for the trace {0}
+TracePackageImportOperation_ErrorCreatingBookmarkFile=Error creating bookmark file for the trace {0}
+TracePackageImportOperation_ImportingPackage=Importing package
+TracePackageImportOperation_DetectingTraceType=Detecting trace type for ''{0}''
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/messages.properties b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/messages.properties
new file mode 100644
index 0000000000..217ed38302
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/messages.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2013, 2014 Ericsson
+#
+# 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:
+# Marc-Andre Laperle - Initial API and implementation
+###############################################################################
+
+TracePackage_Bookmarks=Bookmarks
+TracePackage_Browse=B&rowse...
+TracePackage_DeselectAll=Deselect All
+TracePackage_ErrorOperation=Error occurred during trace package operation
+TracePackage_ErrorMultipleProblems=Multiple problems. Click Details for more information.
+TracePackage_FileDialogTitle=Choose Archive File
+TracePackage_InternalErrorTitle=Internal error
+TracePackage_SelectAll=Select All
+TracePackage_SupplementaryFiles=Supplementary files
+TracePackage_TraceElement=Trace \ No newline at end of file

Back to the top