tmf: Support importing archives from directories and archives (nested
authorMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Wed, 1 Apr 2015 04:52:54 +0000 (00:52 -0400)
committerMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Thu, 2 Apr 2015 19:16:33 +0000 (15:16 -0400)
archives)

This features complements the existing import wizard so that the
archives present in the selected source (directory or archive) get
extracted automatically.

Change-Id: Ia30ca927c4634e092e674b8d36b1d3846d4061b6
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/44965
Reviewed-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java

index 27ea2cf474a948d6671b32d2cdd8dd9bffcaf9ff..a82e52af98daf290c9275dc8de612406af8e41bd 100644 (file)
@@ -15,6 +15,7 @@
  *   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
  *******************************************************************************/
 
 package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
@@ -28,13 +29,16 @@ 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;
@@ -84,11 +88,13 @@ 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;
@@ -783,22 +789,30 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     }
 
     private TraceFileSystemElement getFileSystemTree() {
+        Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> rootObjectAndProvider = getRootObjectAndProvider(getSourceFile());
+        if (rootObjectAndProvider == null) {
+            return null;
+        }
+        return selectFiles(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond());
+    }
+
+    private Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> getRootObjectAndProvider(File sourceFile) {
+        if (sourceFile == null) {
+            return null;
+        }
+
         IFileSystemObject rootElement = null;
         FileSystemObjectImportStructureProvider importStructureProvider = null;
 
         // Import from directory
-        if (isImportFromDirectory()) {
+        if (!isArchiveFile(sourceFile)) {
             importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
-            File sourceDirectory = getSourceDirectory();
-            if (sourceDirectory == null) {
-                return null;
-            }
-            rootElement = importStructureProvider.getIFileSystemObject(sourceDirectory);
+            rootElement = importStructureProvider.getIFileSystemObject(sourceFile);
         } else {
             // Import from archive
             FileSystemObjectLeveledImportStructureProvider leveledImportStructureProvider = null;
-            String archivePath = getSourceArchiveFile() != null ? getSourceArchiveFile().getAbsolutePath() : ""; //$NON-NLS-1$
-            if (ArchiveFileManipulations.isTarFile(archivePath)) {
+            String archivePath = sourceFile.getAbsolutePath();
+            if (isTarFile(archivePath)) {
                 if (ensureTarSourceIsValid(archivePath)) {
                     // We close the file when we dispose the import provider,
                     // see disposeSelectionGroupRoot
@@ -823,7 +837,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             return null;
         }
 
-        return selectFiles(rootElement, importStructureProvider);
+        return new Pair<>(rootElement, importStructureProvider);
     }
 
     /**
@@ -968,11 +982,28 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         return null;
     }
 
+    private static boolean isTarFile(String fileName) {
+        TarFile specifiedTarSourceFile = getSpecifiedTarSourceFile(fileName);
+        if (specifiedTarSourceFile != null) {
+            try {
+                specifiedTarSourceFile.close();
+                return true;
+            } catch (IOException e) {
+            }
+        }
+        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) {
@@ -989,13 +1020,13 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             @Override
             public void run() {
                 // Create the root element from the supplied file system object
-                results[0] = createRootElement(rootFileSystemObject, structureProvider);
+                results[0] = createRootTraceFileElement(rootFileSystemObject, structureProvider);
             }
         });
         return results[0];
     }
 
-    private static TraceFileSystemElement createRootElement(IFileSystemObject element,
+    private static TraceFileSystemElement createRootTraceFileElement(IFileSystemObject element,
             FileSystemObjectImportStructureProvider provider) {
         boolean isContainer = provider.isFolder(element);
         String elementLabel = provider.getLabel(element);
@@ -1107,7 +1138,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
     @Override
     public boolean validateSourceGroup() {
 
-        File source = isImportFromDirectory() ? getSourceDirectory() : getSourceArchiveFile();
+        File source = getSourceFile();
         if (source == null) {
             setMessage(Messages.ImportTraceWizard_SelectTraceSourceEmpty);
             setErrorMessage(null);
@@ -1150,10 +1181,19 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         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);
+    }
+
     @Override
     protected void restoreWidgetValues() {
         super.restoreWidgetValues();
@@ -1367,6 +1407,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         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;
@@ -1384,21 +1425,20 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
         }
 
         public void run(IProgressMonitor progressMonitor) {
-            String currentPath = null;
             try {
 
-                final ArrayList<TraceFileSystemElement> fileSystemElements = new ArrayList<>();
+                final List<TraceFileSystemElement> selectedFileSystemElements = new LinkedList<>();
                 IElementFilter passThroughFilter = new IElementFilter() {
 
                     @Override
                     public void filterElements(Collection elements, IProgressMonitor monitor) {
-                        fileSystemElements.addAll(elements);
+                        selectedFileSystemElements.addAll(elements);
                     }
 
                     @Override
                     public void filterElements(Object[] elements, IProgressMonitor monitor) {
                         for (int i = 0; i < elements.length; i++) {
-                            fileSystemElements.add((TraceFileSystemElement) elements[i]);
+                            selectedFileSystemElements.add((TraceFileSystemElement) elements[i]);
                         }
                     }
                 };
@@ -1411,83 +1451,59 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 // Check if operation was cancelled.
                 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);
-                    }
+                // 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.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();
+                    destTempFolder.delete(true, monitor);
                 }
+                SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+                destTempFolder.create(IResource.HIDDEN, true, monitor);
 
-                // Map to remember already imported directory traces
-                final Map<String, TraceFileSystemElement> directoryTraces = new HashMap<>();
-                while (fileSystemElementsIter.hasNext()) {
-                    ModalContext.checkCanceled(progressMonitor);
-                    currentPath = null;
-                    TraceFileSystemElement element = fileSystemElementsIter.next();
-                    IFileSystemObject fileSystemObject = element.getFileSystemObject();
-                    String resourcePath = element.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString());
-                    element.setDestinationContainerPath(computeDestinationContainerPath(new Path(resourcePath)));
-
-                    currentPath = 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)));
-                        currentPath = 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)));
-                                    currentPath = 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);
-                                }
-                            }
-                        }
-                    }
+
+                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());
                 }
 
-                if (destTempFolder != null && destTempFolder.exists()) {
+                /* 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);
                 }
 
@@ -1496,23 +1512,183 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 setStatus(Status.CANCEL_STATUS);
             } catch (Exception e) {
                 String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$
-                        (currentPath != null ? currentPath : ""); //$NON-NLS-1$
+                        (fCurrentPath != null ? fCurrentPath : ""); //$NON-NLS-1$
                 Activator.getDefault().logError(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,
+        /**
+         * 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<>();
-            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++) {
@@ -1522,11 +1698,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 subList.add(element);
             }
 
-            // Find a sensible root element
-            TraceFileSystemElement root = subList.get(0);
-            while (root.getParent() != null) {
-                root = (TraceFileSystemElement) root.getParent();
-            }
+            TraceFileSystemElement root = getRootElement(subList.get(0));
 
             ImportProvider fileSystemStructureProvider = new ImportProvider();
 
@@ -1547,24 +1719,14 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             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));
+        private TraceFileSystemElement getRootElement(TraceFileSystemElement element) {
+            TraceFileSystemElement root = element;
+            while (root.getParent() != null) {
+                root = (TraceFileSystemElement) root.getParent();
             }
-            return extractedElementsIter;
+            return root;
         }
 
         /**
@@ -1609,12 +1771,22 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             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 {
@@ -1950,7 +2122,12 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
                 }
             }
             if (sourceLocation == null) {
-                sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.toURI());
+                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;
         }
@@ -1996,9 +2173,17 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         @Override
         public String getSourceLocation() {
-            URI uri = new File(fArchivePath).toURI();
+            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());
-            return URIUtil.toUnencodedString(URIUtil.toJarURI(uri, entryPath));
+
+            URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath);
+            return URIUtil.toUnencodedString(jarURI);
         }
 
         @Override
@@ -2042,9 +2227,17 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
 
         @Override
         public String getSourceLocation() {
-            URI uri = new File(fArchivePath).toURI();
+            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());
-            return URIUtil.toUnencodedString(URIUtil.toJarURI(uri, entryPath));
+
+            URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath);
+            return URIUtil.toUnencodedString(jarURI);
         }
 
         @Override
This page took 0.052711 seconds and 5 git commands to generate.