ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / internal / tmf / ui / project / wizards / importtrace / ImportTraceWizardPage.java
index 20b02602b96fd7d27e9bf0bee0dae16a9dd794b8..4abb69d572d26143acfead0c37aea320da4cb80f 100644 (file)
 package org.eclipse.linuxtools.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.List;
 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.IFolder;
@@ -47,6 +52,7 @@ import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.core.runtime.URIUtil;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.layout.PixelConverter;
 import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.jface.operation.ModalContext;
 import org.eclipse.jface.viewers.CheckStateChangedEvent;
@@ -68,14 +74,14 @@ import org.eclipse.linuxtools.tmf.ui.project.model.TmfTracesFolder;
 import org.eclipse.osgi.util.NLS;
 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.FocusListener;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
 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;
@@ -83,14 +89,21 @@ 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.ui.IWorkbench;
 import org.eclipse.ui.dialogs.FileSystemElement;
 import org.eclipse.ui.dialogs.IOverwriteQuery;
 import org.eclipse.ui.dialogs.WizardResourceImportPage;
 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;
@@ -100,17 +113,17 @@ 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.
+ * 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.
+ * 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
@@ -122,12 +135,41 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     // ------------------------------------------------------------------------
     // Constants
     // ------------------------------------------------------------------------
-    private static final String IMPORT_WIZARD_PAGE = "ImportTraceWizardPage"; //$NON-NLS-1$
-    private static final String IMPORT_WIZARD_ROOT_DIRECTORY_ID = IMPORT_WIZARD_PAGE + ".import_root_directory_id"; //$NON-NLS-1$
-    private static final String IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID = IMPORT_WIZARD_PAGE + ".import_unrecognized_traces_id"; //$NON-NLS-1$
-    private static final String IMPORT_WIZARD_PRESERVE_FOLDERS_ID = IMPORT_WIZARD_PAGE + ".import_preserve_folders_id"; //$NON-NLS-1$
+    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$
     private static final String SEPARATOR = ":"; //$NON-NLS-1$
-    private static final String AUTO_DETECT = Messages.ImportTraceWizard_AutoDetection;
+
+    // constant from WizardArchiveFileResourceImportPage1
+    private static final String[] FILE_IMPORT_MASK = { "*.jar;*.zip;*.tar;*.tar.gz;*.tgz", "*.*" }; //$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
@@ -150,6 +192,18 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     // 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. */
@@ -164,6 +218,10 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
      */
     private ResourceTreeAndListGroup fSelectionGroup;
 
+    // Keep trace of the selection root so that we can dispose its related
+    // resources
+    private TraceFileSystemElement fSelectionGroupRoot;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -178,47 +236,6 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
      */
     protected ImportTraceWizardPage(String name, IStructuredSelection selection) {
         super(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);
-
-    }
-
-    /**
-     * Constructor
-     *
-     * @param workbench
-     *            The workbench reference.
-     * @param selection
-     *            The current selection
-     */
-    public ImportTraceWizardPage(IWorkbench workbench, IStructuredSelection selection) {
-        this(IMPORT_WIZARD_PAGE, selection);
         setTitle(Messages.ImportTraceWizard_FileSystemTitle);
         setDescription(Messages.ImportTraceWizard_ImportTrace);
 
@@ -241,8 +258,8 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             }
         }
 
-         //  If no tracing project was selected or trace folder doesn't exist use
-         //  default tracing project
+        // 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());
@@ -259,13 +276,52 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         }
     }
 
+    /**
+     * 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) {
-        createDirectorySelectionGroup(parent);
+        createSourceSelectionGroup(parent);
         createFileSelectionGroup(parent);
         createTraceTypeGroup(parent);
         validateSourceGroup();
@@ -304,7 +360,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                     if (element.isPopulated()) {
                         return getChildren(element).length > 0;
                     }
-                    //If we have not populated then wait until asked
+                    // If we have not populated then wait until asked
                     return true;
                 }
                 return false;
@@ -317,58 +373,97 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     // ------------------------------------------------------------------------
 
     /**
-     * creates the directory selection group.
+     * creates the source selection group.
      *
      * @param parent
      *            the parent composite
      */
-    protected void createDirectorySelectionGroup(Composite parent) {
+    protected void createSourceSelectionGroup(Composite parent) {
 
-        Composite directoryContainerGroup = new Composite(parent, SWT.NONE);
+        Composite sourceGroup = new Composite(parent, SWT.NONE);
         GridLayout layout = new GridLayout();
         layout.numColumns = 3;
-        directoryContainerGroup.setLayout(layout);
-        directoryContainerGroup.setFont(parent.getFont());
-        directoryContainerGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-
-        // Label ("Trace directory:")
-        Label groupLabel = new Label(directoryContainerGroup, SWT.NONE);
-        groupLabel.setText(Messages.ImportTraceWizard_DirectoryLocation);
-        groupLabel.setFont(parent.getFont());
-
-        // Directory name entry field
-        directoryNameField = new Combo(directoryContainerGroup, SWT.BORDER);
-        GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
-        data.widthHint = SIZING_TEXT_FIELD_WIDTH;
-        directoryNameField.setLayoutData(data);
-        directoryNameField.setFont(parent.getFont());
-
-        directoryNameField.addSelectionListener(new SelectionAdapter() {
+        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) {
-                updateFromSourceField();
+                directoryRadioSelected();
             }
         });
 
-        directoryNameField.addKeyListener(new KeyListener() {
+        fImportFromArchiveRadio.addSelectionListener(new SelectionAdapter() {
             @Override
-            public void keyPressed(KeyEvent e) {
-                if (e.character == SWT.CR) { // Windows...
-                    entryChanged = false;
-                    updateFromSourceField();
-                }
-            }
-
-            @Override
-            public void keyReleased(KeyEvent e) {
+            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);
 
-        directoryNameField.addFocusListener(new FocusListener() {
+        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 focusGained(FocusEvent e) {
-                // Do nothing when getting focus
+            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
@@ -377,22 +472,108 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                     updateFromSourceField();
                 }
             }
-        });
+        };
 
-        directoryNameField.addModifyListener(new ModifyListener() {
+        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);
 
-        // Browse button
-        directoryBrowseButton = new Button(directoryContainerGroup, SWT.PUSH);
-        directoryBrowseButton.setText(Messages.ImportTraceWizard_BrowseButton);
-        directoryBrowseButton.addListener(SWT.Selection, this);
-        directoryBrowseButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-        directoryBrowseButton.setFont(parent.getFont());
-        setButtonLayoutData(directoryBrowseButton);
+        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);
+            }
+        }
     }
 
     // ------------------------------------------------------------------------
@@ -449,14 +630,65 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             }
             // If it is valid then proceed to populate
             setErrorMessage(null);
-            setSourceName(selectedDirectory);
+            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()) {
@@ -466,6 +698,15 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         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) {
@@ -477,13 +718,37 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     }
 
     private void updateFromSourceField() {
-        setSourceName(directoryNameField.getText());
+        setSourcePath(getSourceField().getText());
         updateWidgetEnablements();
     }
 
-    private void setSourceName(String path) {
+    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 = directoryNameField.getItems();
+            String[] currentItems = sourceField.getItems();
             int selectionIndex = -1;
             for (int i = 0; i < currentItems.length; i++) {
                 if (currentItems[i].equals(path)) {
@@ -495,32 +760,231 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 String[] newItems = new String[oldLength + 1];
                 System.arraycopy(currentItems, 0, newItems, 0, oldLength);
                 newItems[oldLength] = path;
-                directoryNameField.setItems(newItems);
+                sourceField.setItems(newItems);
                 selectionIndex = oldLength;
             }
-            directoryNameField.select(selectionIndex);
+            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() {
+        IFileSystemObject rootElement = null;
+        FileSystemObjectImportStructureProvider importStructureProvider = null;
+
+        // Import from directory
+        if (isImportFromDirectory()) {
+            importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
+            File sourceDirectory = getSourceDirectory();
+            if (sourceDirectory == null) {
+                return null;
+            }
+            rootElement = importStructureProvider.getIFileSystemObject(sourceDirectory);
+        } else {
+            // Import from archive
+            FileSystemObjectLeveledImportStructureProvider leveledImportStructureProvider = null;
+            String archivePath = getSourceArchiveFile() != null ? getSourceArchiveFile().getAbsolutePath() : ""; //$NON-NLS-1$
+            if (ArchiveFileManipulations.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
+                @SuppressWarnings("resource")
+                ZipFile zipFile = getSpecifiedZipSourceFile(archivePath);
+                leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new ZipLeveledStructureProvider(zipFile), archivePath);
+            }
+            if (leveledImportStructureProvider == null) {
+                return null;
+            }
+            rootElement = leveledImportStructureProvider.getRoot();
+            importStructureProvider = leveledImportStructureProvider;
+        }
+
+        if (rootElement == null) {
+            return null;
+        }
+
+        return selectFiles(rootElement, importStructureProvider);
+    }
+
+    /**
+     * An import provider that makes use of the IFileSystemObject abstraction
+     * instead of using plain file system objects (File, TarEntry, ZipEntry)
+     */
+    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);
+            }
+
+            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();
         }
-        resetSelection();
     }
 
-    // ------------------------------------------------------------------------
-    // File Selection Group (forked WizardFileSystemResourceImportPage1)
-    // ------------------------------------------------------------------------
-    private void resetSelection() {
-        TraceFileSystemElement root = getFileSystemTree();
-        fSelectionGroup.setRoot(root);
+    @SuppressWarnings("resource")
+    private boolean ensureZipSourceIsValid(String archivePath) {
+        ZipFile specifiedFile = getSpecifiedZipSourceFile(archivePath);
+        if (specifiedFile == null) {
+            return false;
+        }
+        return ArchiveFileManipulations.closeZipFile(specifiedFile, getShell());
     }
 
-    private TraceFileSystemElement getFileSystemTree() {
-        File sourceDirectory = getSourceDirectory();
-        if (sourceDirectory == null) {
+    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 TarFile getSpecifiedTarSourceFile(String fileName) {
+        if (fileName.length() == 0) {
             return null;
         }
-        return selectFiles(sourceDirectory, FileSystemStructureProvider.INSTANCE);
+
+        try {
+            return new TarFile(fileName);
+        } catch (TarException e) {
+            // ignore
+        } catch (IOException e) {
+            // ignore
+        }
+
+        return null;
     }
 
-    private TraceFileSystemElement selectFiles(final Object rootFileSystemObject,
-            final IImportStructureProvider structureProvider) {
+    private TraceFileSystemElement selectFiles(final IFileSystemObject rootFileSystemObject,
+            final FileSystemObjectImportStructureProvider structureProvider) {
         final TraceFileSystemElement[] results = new TraceFileSystemElement[1];
         BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
             @Override
@@ -532,22 +996,26 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         return results[0];
     }
 
-    private static TraceFileSystemElement createRootElement(Object fileSystemObject,
-            IImportStructureProvider provider) {
-
-        boolean isContainer = provider.isFolder(fileSystemObject);
-        String elementLabel = provider.getLabel(fileSystemObject);
+    private static TraceFileSystemElement createRootElement(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);//$NON-NLS-1$
-        dummyParent.setFileSystemObject(((File)fileSystemObject).getParentFile());
+        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);
-        result.setFileSystemObject(fileSystemObject);
+                elementLabel, dummyParent, isContainer, provider);
+        result.setFileSystemObject(element);
 
-        //Get the files for the element so as to build the first level
+        // Get the files for the element so as to build the first level
         result.getFiles();
 
         return dummyParent;
@@ -577,9 +1045,9 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         fTraceTypes.setLayoutData(data);
         fTraceTypes.setFont(parent.getFont());
 
-        String[] availableTraceTypes = TmfTraceType.getInstance().getAvailableTraceTypes();
+        String[] availableTraceTypes = TmfTraceType.getAvailableTraceTypes();
         String[] traceTypeList = new String[availableTraceTypes.length + 1];
-        traceTypeList[0] = AUTO_DETECT;
+        traceTypeList[0] = TRACE_TYPE_AUTO_DETECT;
         for (int i = 0; i < availableTraceTypes.length; i++) {
             traceTypeList[i + 1] = availableTraceTypes[i];
         }
@@ -588,7 +1056,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             @Override
             public void widgetSelected(SelectionEvent e) {
                 updateWidgetEnablements();
-                boolean enabled = fTraceTypes.getText().equals(AUTO_DETECT);
+                boolean enabled = fTraceTypes.getText().equals(TRACE_TYPE_AUTO_DETECT);
                 fImportUnrecognizedButton.setEnabled(enabled);
             }
         });
@@ -640,18 +1108,27 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     @Override
     public boolean validateSourceGroup() {
 
-        File sourceDirectory = getSourceDirectory();
-        if (sourceDirectory == null) {
+        File source = isImportFromDirectory() ? getSourceDirectory() : getSourceArchiveFile();
+        if (source == null) {
             setMessage(Messages.ImportTraceWizard_SelectTraceSourceEmpty);
+            setErrorMessage(null);
             return false;
         }
 
-        if (sourceConflictsWithDestination(new Path(sourceDirectory.getPath()))) {
+        if (sourceConflictsWithDestination(new Path(source.getPath()))) {
             setMessage(null);
             setErrorMessage(getSourceConflictMessage());
             return false;
         }
 
+        if (!isImportFromDirectory()) {
+            if (!ensureTarSourceIsValid(source.getAbsolutePath()) && !ensureZipSourceIsValid(source.getAbsolutePath())) {
+                setMessage(null);
+                setErrorMessage(Messages.ImportTraceWizard_BadArchiveFormat);
+                return false;
+            }
+        }
+
         if (fSelectionGroup.getCheckedElementCount() == 0) {
             setMessage(null);
             setErrorMessage(Messages.ImportTraceWizard_SelectTraceNoneSelected);
@@ -676,30 +1153,57 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         return true;
     }
 
+    private boolean isImportFromDirectory() {
+        return fImportFromDirectoryRadio != null && fImportFromDirectoryRadio.getSelection();
+    }
+
     @Override
     protected void restoreWidgetValues() {
         super.restoreWidgetValues();
 
         IDialogSettings settings = getDialogSettings();
         boolean value;
-        if (settings.get(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID) == null) {
-            value = true;
-        } else {
-            value = settings.getBoolean(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID);
+        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);
         }
-        fImportUnrecognizedButton.setSelection(value);
 
-        if (settings.get(IMPORT_WIZARD_PRESERVE_FOLDERS_ID) == null) {
+        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(IMPORT_WIZARD_PRESERVE_FOLDERS_ID);
+            value = settings.getBoolean(getPageStoreKey(IMPORT_WIZARD_IMPORT_FROM_DIRECTORY_ID));
         }
-        fPreserveFolderStructureButton.setSelection(value);
 
-        String[] directoryNames = settings.getArray(IMPORT_WIZARD_ROOT_DIRECTORY_ID);
-        if ((directoryNames != null) && (directoryNames.length != 0)) {
-            for (int i = 0; i < directoryNames.length; i++) {
-                directoryNameField.add(directoryNames[i]);
+        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();
             }
         }
     }
@@ -708,20 +1212,47 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     protected void saveWidgetValues() {
         // Persist dialog settings
         IDialogSettings settings = getDialogSettings();
-        settings.put(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID, fImportUnrecognizedButton.getSelection());
-        settings.put(IMPORT_WIZARD_PRESERVE_FOLDERS_ID, fPreserveFolderStructureButton.getSelection());
+        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]);
+            }
+        }
+    }
 
-        // update directory names history
-        String[] directoryNames = settings.getArray(IMPORT_WIZARD_ROOT_DIRECTORY_ID);
+    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[] = directoryNameField.getItems();
+        String items[] = combo.getItems();
         for (int i = 0; i < items.length; i++) {
             directoryNames = addToHistory(directoryNames, items[i]);
         }
-        settings.put(IMPORT_WIZARD_ROOT_DIRECTORY_ID, directoryNames);
+        settings.put(key, directoryNames);
     }
 
     // ------------------------------------------------------------------------
@@ -734,22 +1265,25 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
      * @return <code>true</code> if successful else <code>false</code>
      */
     public boolean finish() {
-        String traceTypeName = fTraceTypes.getText();
+        String traceTypeName = getImportTraceTypeId();
         String traceId = null;
-        if (!AUTO_DETECT.equals(traceTypeName)) {
+        if (!TRACE_TYPE_AUTO_DETECT.equals(traceTypeName)) {
             String tokens[] = traceTypeName.split(SEPARATOR, 2);
             if (tokens.length < 2) {
                 return false;
             }
-            traceId = TmfTraceType.getInstance().getTraceTypeId(tokens[0], tokens[1]);
+            traceId = TmfTraceType.getTraceTypeId(tokens[0], tokens[1]);
         }
 
         // Save dialog settings
         saveWidgetValues();
 
-        IPath baseSourceContainerPath = new Path(getSourceDirectory().getAbsolutePath());
-        final TraceValidateAndImportOperation operation = new TraceValidateAndImportOperation(traceId, baseSourceContainerPath, getContainerFullPath(),
-                fImportUnrecognizedButton.getSelection(), fOverwriteExistingResourcesCheckbox.getSelection(), fCreateLinksInWorkspaceButton.getSelection(), fPreserveFolderStructureButton.getSelection());
+        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 {
@@ -766,25 +1300,67 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportTraceWizard_ImportProblem, e);
         } catch (InterruptedException e) {
             status = Status.CANCEL_STATUS;
-        } finally {
-            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);
+        }
+        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$
                 }
-                return false;
+                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
@@ -795,21 +1371,21 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         private String fTraceType;
         private IPath fDestinationContainerPath;
         private IPath fBaseSourceContainerPath;
-        private boolean fImportUnrecognizedTraces;
-        private boolean fLink;
-        private boolean fPreserveFolderStructure;
+        private boolean fImportFromArchive;
+        private int fImportOptionFlags;
         private ImportConfirmation fConfirmationMode = ImportConfirmation.SKIP;
 
-        private TraceValidateAndImportOperation(String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean doImport, boolean overwrite, boolean link, boolean preserveFolderStructure) {
+        private TraceValidateAndImportOperation(String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean importFromArchive, int importOptionFlags) {
             fTraceType = traceId;
             fBaseSourceContainerPath = baseSourceContainerPath;
             fDestinationContainerPath = destinationContainerPath;
-            fImportUnrecognizedTraces = doImport;
-            if (overwrite) {
+            fImportOptionFlags = importOptionFlags;
+            fImportFromArchive = importFromArchive;
+
+            boolean overwriteExistingResources = (importOptionFlags & OPTION_OVERWRITE_EXISTING_RESOURCES) != 0;
+            if (overwriteExistingResources) {
                 fConfirmationMode = ImportConfirmation.OVERWRITE_ALL;
             }
-            fLink = link;
-            fPreserveFolderStructure = preserveFolderStructure;
         }
 
         public void run(IProgressMonitor progressMonitor) {
@@ -824,15 +1400,17 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                     public void filterElements(Collection elements, IProgressMonitor monitor) {
                         fileSystemElements.addAll(elements);
                     }
+
                     @Override
                     public void filterElements(Object[] elements, IProgressMonitor monitor) {
                         for (int i = 0; i < elements.length; i++) {
-                            fileSystemElements.add((TraceFileSystemElement)elements[i]);
+                            fileSystemElements.add((TraceFileSystemElement) elements[i]);
                         }
                     }
                 };
 
-                // List fileSystemElements will be filled using the passThroughFilter
+                // List fileSystemElements will be filled using the
+                // passThroughFilter
                 SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 1);
                 fSelectionGroup.getAllCheckedListItems(passThroughFilter, subMonitor);
 
@@ -840,14 +1418,37 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 ModalContext.checkCanceled(subMonitor);
 
                 Iterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.iterator();
+                IFolder destTempFolder = null;
                 subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size());
+                if (fImportFromArchive) {
+                    // When importing from archive, we first extract the
+                    // *selected* files to a temporary folder then create a new
+                    // Iterator<TraceFileSystemElement> that points to the
+                    // extracted files. This way, the import operator can
+                    // continue as it normally would.
+
+                    subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size() * 2);
+                    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);
+
+                    fileSystemElementsIter = extractSelectedFiles(fileSystemElementsIter, destTempFolder, subMonitor);
+                    // We need to update the source container path because the
+                    // "preserve folder structure" option would create the
+                    // wrong folders otherwise.
+                    fBaseSourceContainerPath = destTempFolder.getLocation();
+                }
 
                 while (fileSystemElementsIter.hasNext()) {
                     ModalContext.checkCanceled(progressMonitor);
                     currentPath = null;
                     TraceFileSystemElement element = fileSystemElementsIter.next();
-                    File fileResource = (File) element.getFileSystemObject();
-                    String resourcePath = fileResource.getAbsolutePath();
+                    IFileSystemObject fileSystemObject = element.getFileSystemObject();
+                    String resourcePath = element.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
                     element.setDestinationContainerPath(computeDestinationContainerPath(new Path(resourcePath)));
 
                     currentPath = resourcePath;
@@ -860,9 +1461,8 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                             }
                         }
                     } else {
-                        TraceFileSystemElement parentElement = (TraceFileSystemElement)element.getParent();
-                        File parentFile = (File) parentElement.getFileSystemObject();
-                        String parentPath = parentFile.getAbsolutePath();
+                        TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
+                        String parentPath = parentElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
                         parentElement.setDestinationContainerPath(computeDestinationContainerPath(new Path(parentPath)));
                         currentPath = parentPath;
                         if (!folderElements.containsKey(parentPath)) {
@@ -870,13 +1470,18 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                                 folderElements.put(parentPath, parentElement);
                                 validateAndImportTrace(parentElement, sub);
                             } else {
-                                if (fileResource.exists()) {
+                                if (fileSystemObject.exists()) {
                                     validateAndImportTrace(element, sub);
                                 }
                             }
                         }
                     }
                 }
+
+                if (destTempFolder != null && destTempFolder.exists()) {
+                    destTempFolder.delete(true, progressMonitor);
+                }
+
                 setStatus(Status.OK_STATUS);
             } catch (InterruptedException e) {
                 setStatus(Status.CANCEL_STATUS);
@@ -884,20 +1489,107 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$
                         (currentPath != null ? currentPath : ""); //$NON-NLS-1$
                 Activator.getDefault().logError(errorMessage, e);
-                setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage , e));
+                setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage, e));
+            }
+        }
+
+        private Iterator<TraceFileSystemElement> extractSelectedFiles(Iterator<TraceFileSystemElement> fileSystemElementsIter, IFolder tempFolder, IProgressMonitor progressMonitor) throws InterruptedException,
+                InvocationTargetException {
+            List<TraceFileSystemElement> subList = new ArrayList<>();
+            Map<IPath, String> sourceLocationMap = new HashMap<>();
+            // Collect all the elements
+            while (fileSystemElementsIter.hasNext()) {
+                ModalContext.checkCanceled(progressMonitor);
+                TraceFileSystemElement element = fileSystemElementsIter.next();
+                sourceLocationMap.put(new Path(element.getFileSystemObject().getName()).removeTrailingSeparator(), element.getSourceLocation());
+                TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
+                sourceLocationMap.put(new Path(parentElement.getFileSystemObject().getName()).removeTrailingSeparator(), parentElement.getSourceLocation());
+                if (element.isDirectory()) {
+                    Object[] array = element.getFiles().getChildren();
+                    for (int i = 0; i < array.length; i++) {
+                        subList.add((TraceFileSystemElement) array[i]);
+                    }
+                }
+                subList.add(element);
+            }
+
+            // Find a sensible root element
+            TraceFileSystemElement root = subList.get(0);
+            while (root.getParent() != null) {
+                root = (TraceFileSystemElement) root.getParent();
+            }
+
+            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));
+
+            // Create the new import provider and root element based on the
+            // extracted temp folder
+            FileSystemObjectImportStructureProvider importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
+            IFileSystemObject rootElement = importStructureProvider.getIFileSystemObject(new File(tempFolder.getLocation().toOSString()));
+            TraceFileSystemElement createRootElement = createRootElement(rootElement, importStructureProvider);
+            List<TraceFileSystemElement> list = new ArrayList<>();
+            getAllChildren(list, createRootElement);
+            Iterator<TraceFileSystemElement> extractedElementsIter = list.iterator();
+            IPath tempPath = new Path(tempFolder.getLocation().toOSString());
+            for (TraceFileSystemElement element : list) {
+                IPath path = new Path(((File) element.getFileSystemObject().getRawFileSystemObject()).getAbsolutePath()).makeRelativeTo(tempPath);
+                element.setSourceLocation(sourceLocationMap.get(path));
+                TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
+                IPath parentPath = new Path(((File) parentElement.getFileSystemObject().getRawFileSystemObject()).getAbsolutePath()).makeRelativeTo(tempPath);
+                parentElement.setSourceLocation(sourceLocationMap.get(parentPath));
+            }
+            return extractedElementsIter;
+        }
+
+        /**
+         * 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.
+            // 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 (fPreserveFolderStructure) {
+            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
+                    // Use resourcePath directory if fBaseSourceContainerPath
+                    // points to a directory trace
                     sourceContainerPath = resourcePath;
                 }
                 // /home/user/bar/foo, /home/user -> bar/foo
@@ -910,8 +1602,8 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         private void validateAndImportTrace(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor)
                 throws TmfTraceImportException, CoreException, InvocationTargetException, InterruptedException {
-            File file = (File) fileSystemElement.getFileSystemObject();
-            String path = file.getAbsolutePath();
+            String parentContainerPath = fBaseSourceContainerPath.toOSString();
+            String path = fileSystemElement.getFileSystemObject().getAbsolutePath(parentContainerPath);
             TraceTypeHelper traceTypeHelper = null;
 
             if (fTraceType == null) {
@@ -922,17 +1614,17 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                     // the trace did not match any trace type
                 }
                 if (traceTypeHelper == null) {
-                    if (fImportUnrecognizedTraces) {
+                    if ((fImportOptionFlags & OPTION_IMPORT_UNRECOGNIZED_TRACES) != 0) {
                         importResource(fileSystemElement, monitor);
                     }
                     return;
                 }
             } else {
-                boolean isDirectoryTraceType = TmfTraceType.getInstance().isDirectoryTraceType(fTraceType);
+                boolean isDirectoryTraceType = TmfTraceType.isDirectoryTraceType(fTraceType);
                 if (fileSystemElement.isDirectory() != isDirectoryTraceType) {
                     return;
                 }
-                traceTypeHelper = TmfTraceType.getInstance().getTraceType(fTraceType);
+                traceTypeHelper = TmfTraceType.getTraceType(fTraceType);
 
                 if (traceTypeHelper == null) {
                     // Trace type not found
@@ -998,12 +1690,13 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
             IPath containerPath = fileSystemElement.getDestinationContainerPath();
             IPath tracePath = containerPath.addTrailingSeparator().append(fileSystemElement.getLabel());
-            if (fileSystemElement.isDirectory() && (!fLink)) {
+            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]);
+                    subList.add((TraceFileSystemElement) array[i]);
                 }
                 parentFolder = fileSystemElement;
 
@@ -1011,7 +1704,6 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 subList.add(fileSystemElement);
             }
 
-
             ImportProvider fileSystemStructureProvider = new ImportProvider();
 
             IOverwriteQuery myQueryImpl = new IOverwriteQuery() {
@@ -1021,42 +1713,28 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 }
             };
 
-            monitor.setTaskName(Messages.ImportTraceWizard_ImportOperationTaskName + " " + ((File)fileSystemElement.getFileSystemObject()).getAbsolutePath()); //$NON-NLS-1$
+            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(fLink);
+            operation.setCreateLinks(createLinksInWorkspace);
             operation.setVirtualFolders(false);
 
             operation.run(new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
-
-            File file = (File) fileSystemElement.getFileSystemObject();
-            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());
-            }
-
+            String sourceLocation = fileSystemElement.getSourceLocation();
             IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(tracePath);
-            resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+            if (sourceLocation != null) {
+                resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
+            }
 
             return resource;
         }
 
-        private boolean isDirectoryTrace(FileSystemElement fileSystemElement) {
-            File file = (File) fileSystemElement.getFileSystemObject();
-            String path = file.getAbsolutePath();
-            if (TmfTraceType.getInstance().isDirectoryTrace(path)) {
+        private boolean isDirectoryTrace(TraceFileSystemElement fileSystemElement) {
+            String path = fileSystemElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
+            if (TmfTraceType.isDirectoryTrace(path)) {
                 return true;
             }
             return false;
@@ -1068,8 +1746,8 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             // handle rename
             if (getExistingTrace(tracePath) != null) {
                 if ((fConfirmationMode == ImportConfirmation.RENAME_ALL) ||
-                    (fConfirmationMode == ImportConfirmation.OVERWRITE_ALL) ||
-                    (fConfirmationMode == ImportConfirmation.SKIP_ALL)) {
+                        (fConfirmationMode == ImportConfirmation.OVERWRITE_ALL) ||
+                        (fConfirmationMode == ImportConfirmation.SKIP_ALL)) {
                     return fConfirmationMode;
                 }
 
@@ -1088,12 +1766,12 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             final MessageDialog dialog = new MessageDialog(getContainer()
                     .getShell(), 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(),
+                            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() {
@@ -1117,7 +1795,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
          */
         private IPath getInitialDestinationPath(TraceFileSystemElement fileSystemElement) {
             IPath traceFolderPath = fileSystemElement.getDestinationContainerPath();
-            return traceFolderPath.append(((File)fileSystemElement.getFileSystemObject()).getName());
+            return traceFolderPath.append(fileSystemElement.getFileSystemObject().getLabel());
         }
 
         private void rename(TraceFileSystemElement fileSystemElement) {
@@ -1127,7 +1805,8 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 return;
             }
 
-            // Not using IFolder on purpose to leave the door open to import directly into an IProject
+            // 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) {
@@ -1176,17 +1855,21 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     }
 
     /**
-     * The <code>TraceFileSystemElement</code> is a <code>FileSystemElement</code> that knows
-     * if it has been populated or not.
+     * 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) {
+        public TraceFileSystemElement(String name, FileSystemElement parent, boolean isDirectory, FileSystemObjectImportStructureProvider provider) {
             super(name, parent, isDirectory);
+            fProvider = provider;
         }
 
         public void setDestinationContainerPath(IPath destinationContainerPath) {
@@ -1203,7 +1886,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         @Override
         public AdaptableList getFiles() {
-            if(!fIsPopulated) {
+            if (!fIsPopulated) {
                 populateElementChildren();
             }
             return super.getFiles();
@@ -1211,7 +1894,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         @Override
         public AdaptableList getFolders() {
-            if(!fIsPopulated) {
+            if (!fIsPopulated) {
                 populateElementChildren();
             }
             return super.getFolders();
@@ -1219,6 +1902,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         /**
          * Sets the label for the trace to be used when importing at trace.
+         *
          * @param name
          *            the label for the trace
          */
@@ -1233,13 +1917,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
          */
         public String getLabel() {
             if (fLabel == null) {
-                //Get the name - if it is empty then return the path as it is a file root
-                File file = (File) getFileSystemObject();
-                String name = file.getName();
-                if (name.length() == 0) {
-                    return file.getPath();
-                }
-                return name;
+                return getFileSystemObject().getLabel();
             }
             return fLabel;
         }
@@ -1254,62 +1932,257 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         }
 
         /**
-         * Populates the children of the specified parent <code>FileSystemElement</code>
+         * Populates the children of the specified parent
+         * <code>FileSystemElement</code>
          */
         private void populateElementChildren() {
-            FileSystemStructureProvider provider = FileSystemStructureProvider.INSTANCE;
-            List<File> allchildren = provider.getChildren(this.getFileSystemObject());
-            File child = null;
+            List<IFileSystemObject> allchildren = fProvider.getChildren(this.getFileSystemObject());
+            Object child = null;
             TraceFileSystemElement newelement = null;
-            Iterator<File> iter = allchildren.iterator();
-            while(iter.hasNext()) {
+            Iterator<IFileSystemObject> iter = allchildren.iterator();
+            while (iter.hasNext()) {
                 child = iter.next();
-                newelement = new TraceFileSystemElement(provider.getLabel(child), this, provider.isFolder(child));
+                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;
+        }
     }
 
-    private class ImportProvider implements IImportStructureProvider {
+    /**
+     * This interface abstracts the differences between different kinds of
+     * FileSystemObjects such as File, TarEntry and ZipEntry. 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) {
+                sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.toURI());
+            }
+            return sourceLocation;
+        }
+
+        @Override
+        public Object getRawFileSystemObject() {
+            return fFileSystemObject;
+        }
+    }
+
+    /**
+     * The "Tar" implementation of an IFileSystemObject
+     */
+    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() {
+            URI uri = new File(fArchivePath).toURI();
+            IPath entryPath = new Path(fFileSystemObject.getName());
+            return URIUtil.toUnencodedString(URIUtil.toJarURI(uri, entryPath));
+        }
+
+        @Override
+        public Object getRawFileSystemObject() {
+            return fFileSystemObject;
+        }
+    }
 
-        private FileSystemStructureProvider provider = FileSystemStructureProvider.INSTANCE;
+    /**
+     * 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() {
+            URI uri = new File(fArchivePath).toURI();
+            IPath entryPath = new Path(fFileSystemObject.getName());
+            return URIUtil.toUnencodedString(URIUtil.toJarURI(uri, entryPath));
+        }
+
+        @Override
+        public Object getRawFileSystemObject() {
+            return fFileSystemObject;
+        }
+    }
+
+    private class ImportProvider implements IImportStructureProvider {
 
         ImportProvider() {
         }
 
         @Override
         public String getLabel(Object element) {
-            TraceFileSystemElement resource = (TraceFileSystemElement)element;
+            TraceFileSystemElement resource = (TraceFileSystemElement) element;
             return resource.getLabel();
         }
 
         @Override
         public List getChildren(Object element) {
-            TraceFileSystemElement resource = (TraceFileSystemElement)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]);
-                    }
+            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 provider.getContents(resource.getFileSystemObject());
+            TraceFileSystemElement resource = (TraceFileSystemElement) element;
+            return resource.getProvider().getContents(resource.getFileSystemObject());
         }
 
         @Override
         public String getFullPath(Object element) {
-            TraceFileSystemElement resource = (TraceFileSystemElement)element;
-            return provider.getFullPath(resource.getFileSystemObject());
+            TraceFileSystemElement resource = (TraceFileSystemElement) element;
+            return resource.getProvider().getFullPath(resource.getFileSystemObject());
         }
 
         @Override
         public boolean isFolder(Object element) {
-            TraceFileSystemElement resource = (TraceFileSystemElement)element;
+            TraceFileSystemElement resource = (TraceFileSystemElement) element;
             return resource.isDirectory();
         }
     }
@@ -1340,7 +2213,9 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         /**
          * Private constructor
-         * @param name the name of state
+         *
+         * @param name
+         *            the name of state
          */
         private ImportConfirmation(String name) {
             fInName = name;
This page took 0.047806 seconds and 5 git commands to generate.