tmf: Use Apache Common Compress for importing from archive
authorMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Wed, 5 Oct 2016 22:22:43 +0000 (18:22 -0400)
committerMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Fri, 14 Oct 2016 19:34:23 +0000 (15:34 -0400)
By using Apache Common Compress instead of the Eclipse classes,
it will allow us to support more formats and have move stability.
We will be able to handle tars with PaxHeaders, XZ and BZip
compression for example.

Change-Id: I2693da15eb38a57b477734f1a0931c30585f2192
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/82567
Reviewed-by: Hudson CI
18 files changed:
rcp/org.eclipse.tracecompass.rcp/feature.xml
rcp/org.eclipse.tracecompass.rcp/pom.xml
tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ArchiveUtil.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectImportStructureProvider.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/SafePathZipLeveledStructureProvider.java [deleted file]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarEntry.java [deleted file]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarException.java [deleted file]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarFile.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarFileSystemObject.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarInputStream.java [deleted file]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarLeveledStructureProvider.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceValidateAndImportOperation.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipFileSystemObject.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipLeveledStructureProvider.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/AbstractTracePackageOperation.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/tracepkg/importexport/TracePackageImportOperation.java

index 00b43c4a2f11024f0aff9aaf10e6067c96260e6e..2a048ef6f5477cceb900d9eda2e0aa6a27a6ec2f 100644 (file)
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.apache.commons.compress"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
index fcd527c7964b0306c4f3c70956a8ea525049ada3..2f4f3f821a8d1473a5eafd903592c35072a657fd 100644 (file)
@@ -36,6 +36,7 @@
             </goals>
             <configuration>
               <excludes>
+                <plugin id="org.apache.commons.compress"/>
                 <plugin id="org.apache.xerces"/>
                 <plugin id="org.apache.xml.resolver"/>
                 <plugin id="org.apache.xml.serializer"/>
index 6c964c0b44982c25bb405d4ebc03131cba42c26c..0b46129d753adb13475e849e1bcd6393d75780dd 100644 (file)
@@ -24,7 +24,8 @@ Require-Bundle: org.eclipse.core.expressions,
  org.swtchart,
  com.ibm.icu,
  org.eclipse.linuxtools.dataviewers.piechart,
- org.eclipse.tracecompass.segmentstore.core
+ org.eclipse.tracecompass.segmentstore.core,
+ org.apache.commons.compress
 Export-Package: org.eclipse.tracecompass.internal.tmf.ui;x-friends:="org.eclipse.tracecompass.tmf.ui.tests,org.eclipse.tracecompass.tmf.ctf.ui.tests",
  org.eclipse.tracecompass.internal.tmf.ui.commands;x-internal:=true,
  org.eclipse.tracecompass.internal.tmf.ui.dialogs;x-internal:=true,
index 559dad9e968712fac67743a2749ae8be99e5df5b..e1ff0fa611ce38a157afa587ccfee4066df2bd19 100644 (file)
@@ -14,22 +14,19 @@ package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
 
+import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceCoreUtils;
 import org.eclipse.tracecompass.tmf.core.util.Pair;
-import org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileManipulations;
 import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
 
 /**
  * Various utilities for dealing with archives in the context of importing
  * traces.
  */
-@SuppressWarnings({"restriction" })
 public class ArchiveUtil {
 
     /**
@@ -42,7 +39,21 @@ public class ArchiveUtil {
      */
     public static boolean isArchiveFile(File sourceFile) {
         String absolutePath = sourceFile.getAbsolutePath();
-        return isTarFile(absolutePath) || ArchiveFileManipulations.isZipFile(absolutePath) || isGzipFile(absolutePath);
+        return isTarFile(absolutePath) || isZipFile(absolutePath) || isGzipFile(absolutePath);
+    }
+
+    private static boolean isZipFile(String fileName) {
+        ZipFile specifiedZipSourceFile = getSpecifiedZipSourceFile(fileName);
+        if (specifiedZipSourceFile != null) {
+            try {
+                specifiedZipSourceFile.close();
+                return true;
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+
+        return false;
     }
 
     private static boolean isTarFile(String fileName) {
@@ -73,10 +84,13 @@ public class ArchiveUtil {
             return null;
         }
 
+        File file = new File(fileName);
+        if (file.isDirectory()) {
+            return null;
+        }
+
         try {
-            return new ZipFile(fileName);
-        } catch (ZipException e) {
-            // ignore
+            return new ZipFile(file);
         } catch (IOException e) {
             // ignore
         }
@@ -96,20 +110,29 @@ public class ArchiveUtil {
 
         try {
             return new TarFile(fileName);
-        } catch (TarException | IOException e) {
+        } catch (IOException e) {
             // ignore
         }
 
         return null;
     }
 
-    @SuppressWarnings("resource")
-    static boolean ensureZipSourceIsValid(String archivePath, Shell shell) {
+    static boolean ensureZipSourceIsValid(String archivePath) {
         ZipFile specifiedFile = getSpecifiedZipSourceFile(archivePath);
         if (specifiedFile == null) {
             return false;
         }
-        return ArchiveFileManipulations.closeZipFile(specifiedFile, shell);
+        return closeZipFile(specifiedFile);
+    }
+
+    static boolean closeZipFile(ZipFile file) {
+        try {
+            file.close();
+        } catch (IOException e) {
+            return false;
+        }
+
+        return true;
     }
 
     static boolean ensureTarSourceIsValid(String archivePath) {
@@ -169,11 +192,11 @@ public class ArchiveUtil {
                     TarFile tarFile = getSpecifiedTarSourceFile(archivePath);
                     leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new TarLeveledStructureProvider(tarFile), archivePath);
                 }
-            } else if (ensureZipSourceIsValid(archivePath, shell)) {
+            } else if (ensureZipSourceIsValid(archivePath)) {
                 // We close the file when we dispose the import provider, see
                 // disposeSelectionGroupRoot
                 ZipFile zipFile = getSpecifiedZipSourceFile(archivePath);
-                leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new SafePathZipLeveledStructureProvider(zipFile), archivePath);
+                leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new ZipLeveledStructureProvider(zipFile), archivePath);
             } else if (ensureGzipSourceIsValid(archivePath)) {
                 // We close the file when we dispose the import provider, see
                 // disposeSelectionGroupRoot
index 02ddad60e96474dfcbafe86f7c8abd92d312b5dd..3a33240b40f95b8c4546f5ce69a9c335f5bff993 100644 (file)
@@ -15,15 +15,15 @@ package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
 import java.io.File;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.List;
-import java.util.zip.ZipEntry;
 
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
 
 /**
  * An import provider that makes use of the IFileSystemObject abstraction
- * instead of using plain file system objects (File, TarEntry, ZipEntry, etc)
+ * instead of using plain file system objects (File, TarArchiveEntry, ZipArchiveEntry, etc)
  */
 public class FileSystemObjectImportStructureProvider implements IImportStructureProvider {
 
@@ -43,23 +43,6 @@ public class FileSystemObjectImportStructureProvider implements IImportStructure
         fArchivePath = archivePath;
     }
 
-    /**
-     * This orders by files first then the folders. Then by lexical order.
-     */
-    private final class FileObjectPathComparator implements Comparator<IFileSystemObject> {
-        @Override
-        public int compare(IFileSystemObject o1, IFileSystemObject o2) {
-            if (o1.isDirectory() != o2.isDirectory()) {
-                if (o1.isDirectory()) {
-                    return 1;
-                }
-                return -1;
-            }
-
-            return o1.getName().compareToIgnoreCase(o2.getName());
-        }
-    }
-
     @Override
     public List<IFileSystemObject> getChildren(Object element) {
         @SuppressWarnings("rawtypes")
@@ -69,7 +52,6 @@ public class FileSystemObjectImportStructureProvider implements IImportStructure
             adapted.add(getIFileSystemObject(o));
         }
 
-        adapted.sort(new FileObjectPathComparator());
         return adapted;
     }
 
@@ -87,10 +69,10 @@ public class FileSystemObjectImportStructureProvider implements IImportStructure
 
         if (o instanceof File) {
             return new FileFileSystemObject((File) o);
-        } else if (o instanceof TarEntry) {
-            return new TarFileSystemObject((TarEntry) o, fArchivePath);
-        } else if (o instanceof ZipEntry) {
-            return new ZipFileSystemObject((ZipEntry) o, fArchivePath);
+        } else if (o instanceof TarArchiveEntry) {
+            return new TarFileSystemObject((TarArchiveEntry) o, fArchivePath);
+        } else if (o instanceof ZipArchiveEntry) {
+            return new ZipFileSystemObject((ZipArchiveEntry) o, fArchivePath);
         } else if (o instanceof GzipEntry) {
             return new GzipFileSystemObject((GzipEntry) o, fArchivePath);
         }
index 9ee72e6339aa4878119e67a6244958c928315d8a..00278eec886727f1c96f0ec79afff4a55e97912d 100644 (file)
@@ -943,7 +943,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage {
             return false;
         }
 
-        if (!isImportFromDirectory() && !ArchiveUtil.ensureTarSourceIsValid(source.getAbsolutePath()) && !ArchiveUtil.ensureZipSourceIsValid(source.getAbsolutePath(), getContainer().getShell())
+        if (!isImportFromDirectory() && !ArchiveUtil.ensureTarSourceIsValid(source.getAbsolutePath()) && !ArchiveUtil.ensureZipSourceIsValid(source.getAbsolutePath())
                 && !ArchiveUtil.ensureGzipSourceIsValid(source.getAbsolutePath())) {
             setMessage(null);
             setErrorMessage(Messages.ImportTraceWizard_BadArchiveFormat);
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/SafePathZipLeveledStructureProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/SafePathZipLeveledStructureProvider.java
deleted file mode 100644 (file)
index fcb6fe6..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Ericsson
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
-
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.eclipse.ui.internal.wizards.datatransfer.ZipLeveledStructureProvider;
-
-/**
- * A Zip structure provider that makes sure to return safe paths. For example,
- * if a Zip entry contains a ':' and is extracted on Windows, it will be changed
- * to a '_'
- */
-@SuppressWarnings("restriction")
-public class SafePathZipLeveledStructureProvider extends ZipLeveledStructureProvider {
-
-    /**
-     * Creates a provider which will operate on the passed Zip file.
-     *
-     * @param sourceFile
-     *            The source file to create the provider around
-     */
-    public SafePathZipLeveledStructureProvider(ZipFile sourceFile) {
-        super(sourceFile);
-    }
-
-    @Override
-    public String getFullPath(Object element) {
-        String name = ((ZipEntry) element).getName();
-        return ArchiveUtil.toValidNamesPath(name).toOSString();
-    }
-
-    @Override
-    public String getLabel(Object element) {
-        if (element.equals(getRoot())) {
-            return ((ZipEntry) element).getName();
-        }
-        String name = ((ZipEntry) element).getName();
-        return stripPath(ArchiveUtil.toValidNamesPath(name).lastSegment());
-    }
-
-    /**
-     * Strip the leading directories from the path. Copied from
-     * {@link ZipLeveledStructureProvider}
-     */
-    private String stripPath(String path) {
-        String strippedPath = path;
-        String pathOrig = new String(strippedPath);
-        for (int i = 0; i < getStrip(); i++) {
-            int firstSep = strippedPath.indexOf('/');
-            // If the first character was a separator we must strip to the next
-            // separator as well
-            if (firstSep == 0) {
-                strippedPath = strippedPath.substring(1);
-                firstSep = strippedPath.indexOf('/');
-            }
-            // No separator was present so we're in a higher directory right
-            // now
-            if (firstSep == -1) {
-                return pathOrig;
-            }
-            strippedPath = strippedPath.substring(firstSep);
-        }
-        return strippedPath;
-    }
-}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarEntry.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarEntry.java
deleted file mode 100644 (file)
index 7fb5a58..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace Compass to work around bug 501379
- *******************************************************************************/
-package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
-
-/**
- * Representation of a file in a tar archive.
- */
-public class TarEntry implements Cloneable
-{
-       private String name;
-       private long mode, time, size;
-       private int type;
-       int filepos;
-
-       /**
-        * Entry type for normal files.
-        */
-       public static final int FILE = '0';
-
-       /**
-        * Entry type for directories.
-        */
-       public static final int DIRECTORY = '5';
-
-       /**
-        * Create a new TarEntry for a file of the given name at the
-        * given position in the file.
-        *
-        * @param name filename
-        * @param pos position in the file in bytes
-        */
-       TarEntry(String name, int pos) {
-               this.name = name;
-               mode = 0644;
-               type = FILE;
-               filepos = pos;
-               time = System.currentTimeMillis() / 1000;
-       }
-
-       /**
-        * Create a new TarEntry for a file of the given name.
-        *
-        * @param name filename
-        */
-       public TarEntry(String name) {
-               this(name, -1);
-       }
-
-       /**
-        * Returns the type of this file, one of FILE, LINK, SYM_LINK,
-        * CHAR_DEVICE, BLOCK_DEVICE, DIRECTORY or FIFO.
-        *
-        * @return file type
-        */
-       public int getFileType() {
-               return type;
-       }
-
-       /**
-        * Returns the mode of the file in UNIX permissions format.
-        *
-        * @return file mode
-        */
-       public long getMode() {
-               return mode;
-       }
-
-       /**
-        * Returns the name of the file.
-        *
-        * @return filename
-        */
-       public String getName() {
-               return name;
-       }
-
-       /**
-        * Returns the size of the file in bytes.
-        *
-        * @return filesize
-        */
-       public long getSize() {
-               return size;
-       }
-
-       /**
-        * Returns the modification time of the file in seconds since January
-        * 1st 1970.
-        *
-        * @return time
-        */
-       public long getTime() {
-               return time;
-       }
-
-       /**
-        * Sets the type of the file, one of FILE, LINK, SYMLINK, CHAR_DEVICE,
-        * BLOCK_DEVICE, or DIRECTORY.
-        *
-        * @param type the file type
-        */
-       public void setFileType(int type) {
-               this.type = type;
-       }
-
-       /**
-        * Sets the mode of the file in UNIX permissions format.
-        *
-        * @param mode the mode
-        */
-       public void setMode(long mode) {
-               this.mode = mode;
-       }
-
-       /**
-        * Sets the size of the file in bytes.
-        *
-        * @param size the file size
-        */
-       public void setSize(long size) {
-               this.size = size;
-       }
-
-       /**
-        * Sets the modification time of the file in seconds since January
-        * 1st 1970.
-        *
-        * @param time the modification time
-        */
-       public void setTime(long time) {
-               this.time = time;
-       }
-}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarException.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarException.java
deleted file mode 100644 (file)
index f67d409..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace Compass to work around bug 501379
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
-
-/**
- * Exception generated upon encountering corrupted tar files.
- */
-public class TarException extends Exception {
-       /**
-        * Generated serial version UID for this class.
-        */
-       private static final long serialVersionUID = 2886671254518853528L;
-
-    /**
-     * Constructs a TarException without a detail string.
-     */
-    public TarException() {
-       super();
-    }
-
-       /**
-     * Constructs a TarException with the specified detail string.
-     *
-     * @param s the detail string
-     */
-    public TarException(String s) {
-       super(s);
-    }
-
-    /**
-     * Constructs a TarException with the specified detail string.
-     *
-     * @param s the detail string
-     * @param cause the cause
-     */
-    public TarException(String s, Throwable cause) {
-       super(s, cause);
-    }
-}
index 028473adb77d8122cb7da326e143a547b9bcb21b..101581d379f199e15c0aa52e9381bdb45478f0b9 100644 (file)
@@ -19,7 +19,10 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Enumeration;
-import java.util.zip.GZIPInputStream;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
 
 
 /**
@@ -28,141 +31,150 @@ import java.util.zip.GZIPInputStream;
  * archive.
  */
 public class TarFile {
-       private File file;
-       private TarInputStream entryEnumerationStream;
-       private TarEntry curEntry;
-       private TarInputStream entryStream;
+    private File file;
+    private TarArchiveInputStream entryEnumerationStream;
+    private TarArchiveEntry curEntry;
+    private TarArchiveInputStream entryStream;
 
-       private InputStream internalEntryStream;
+    private InputStream internalEntryStream;
     // This field is just to prevent try with resources error and keep the code
     // similar to the original
     private InputStream fInputStream;
 
-       /**
-        * Create a new TarFile for the given file.
-        *
-        * @param file the file
-        * @throws TarException on Tar error (bad format, etc)
-        * @throws IOException on i/o error
-        */
-       public TarFile(File file) throws TarException, IOException {
-               this.file = file;
-
-               fInputStream = new FileInputStream(file);
-               // First, check if it's a GZIPInputStream.
-               try {
-                       fInputStream = new GZIPInputStream(fInputStream);
-               } catch(IOException e) {
-                       //If it is not compressed we close
-                       //the old one and recreate
-                       fInputStream.close();
-                       fInputStream = new FileInputStream(file);
-               }
-               try {
-                       entryEnumerationStream = new TarInputStream(fInputStream);
-               } catch (TarException | IOException ex) {
-                       fInputStream.close();
-                       throw ex;
-               }
-               curEntry = entryEnumerationStream.getNextEntry();
-       }
-
-       /**
-        * Close the tar file input stream.
-        *
-        * @throws IOException if the file cannot be successfully closed
-        */
-       public void close() throws IOException {
-               if (entryEnumerationStream != null) {
+    /**
+     * Create a new TarFile for the given file.
+     *
+     * @param file the file
+     * @throws IOException on i/o error (bad format, etc)
+     */
+    public TarFile(File file) throws IOException {
+        this.file = file;
+
+        fInputStream = new FileInputStream(file);
+        // First, check if it's a GZIPInputStream.
+        try {
+            fInputStream = new GzipCompressorInputStream(fInputStream);
+        } catch (IOException e) {
+            //If it is not compressed we close
+            //the old one and recreate
+            fInputStream.close();
+            fInputStream = new FileInputStream(file);
+        }
+        entryEnumerationStream = new TarArchiveInputStream(fInputStream);
+        try {
+            curEntry = (TarArchiveEntry) entryEnumerationStream.getNextEntry();
+        } catch (IOException e) {
+            fInputStream.close();
+            throw e;
+        }
+    }
+
+    /**
+     * Close the tar file input stream.
+     *
+     * @throws IOException if the file cannot be successfully closed
+     */
+    public void close() throws IOException {
+        if (entryEnumerationStream != null) {
             entryEnumerationStream.close();
         }
-               if (internalEntryStream != null) {
+        if (internalEntryStream != null) {
             internalEntryStream.close();
         }
-       }
-
-       /**
-        * Create a new TarFile for the given path name.
-        *
-        * @param filename the file name to create the TarFile from
-     * @throws TarException on Tar error (bad format, etc)
-     * @throws IOException on i/o error
-        */
-       public TarFile(String filename) throws TarException, IOException {
-               this(new File(filename));
-       }
-
-       /**
-        * Returns an enumeration cataloguing the tar archive.
-        *
-        * @return enumeration of all files in the archive
-        */
-       public Enumeration<TarEntry> entries() {
-               return new Enumeration<TarEntry>() {
-                       @Override
-                       public boolean hasMoreElements() {
-                               return (curEntry != null);
-                       }
-
-                       @Override
-                       public TarEntry nextElement() {
-                               TarEntry oldEntry = curEntry;
-                               try {
-                                       curEntry = entryEnumerationStream.getNextEntry();
-                               } catch(TarException e) {
-                                       curEntry = null;
-                               } catch(IOException e) {
-                                       curEntry = null;
-                               }
-                               return oldEntry;
-                       }
-               };
-       }
-
-       /**
-        * Returns a new InputStream for the given file in the tar archive.
-        *
-        * @param entry the entry to get the InputStream from
-        * @return an input stream for the given file
-     * @throws TarException on Tar error (bad format, etc)
-     * @throws IOException on i/o error
-        */
-       public InputStream getInputStream(TarEntry entry) throws TarException, IOException {
-               if(entryStream == null || !entryStream.skipToEntry(entry)) {
-                       if (internalEntryStream != null) {
-                               internalEntryStream.close();
-                       }
-                       internalEntryStream = new FileInputStream(file);
-                       // First, check if it's a GZIPInputStream.
-                       try {
-                               internalEntryStream = new GZIPInputStream(internalEntryStream);
-                       } catch(IOException e) {
-                               //If it is not compressed we close
-                               //the old one and recreate
-                               internalEntryStream.close();
-                               internalEntryStream = new FileInputStream(file);
-                       }
-                       entryStream = new TarInputStream(internalEntryStream, entry) {
-                               @Override
-                               public void close() {
-                                       // Ignore close() since we want to reuse the stream.
-                               }
-                       };
-               }
-               return entryStream;
-       }
-
-       /**
-        * Returns the path name of the file this archive represents.
-        *
-        * @return path
-        */
-       public String getName() {
-               return file.getPath();
-       }
-
-       @Override
-       protected void finalize() throws Throwable {
-               close();
-       }
+    }
+
+    /**
+     * Create a new TarFile for the given path name.
+     *
+     * @param filename the file name to create the TarFile from
+     * @throws IOException on i/o error (bad format, etc)
+     */
+    public TarFile(String filename) throws IOException {
+        this(new File(filename));
+    }
+
+    /**
+     * Returns an enumeration cataloguing the tar archive.
+     *
+     * @return enumeration of all files in the archive
+     */
+    public Enumeration<TarArchiveEntry> entries() {
+        return new Enumeration<TarArchiveEntry>() {
+            @Override
+            public boolean hasMoreElements() {
+                return (curEntry != null);
+            }
+
+            @Override
+            public TarArchiveEntry nextElement() {
+                TarArchiveEntry oldEntry = curEntry;
+                try {
+                    curEntry = (TarArchiveEntry) entryEnumerationStream.getNextEntry();
+                } catch(IOException e) {
+                    curEntry = null;
+                }
+                return oldEntry;
+            }
+        };
+    }
+
+    /**
+     * Returns a new InputStream for the given file in the tar archive.
+     *
+     * @param entry the entry to get the InputStream from
+     * @return an input stream for the given file
+     * @throws IOException on i/o error (bad format, etc)
+     */
+    public InputStream getInputStream(TarArchiveEntry entry) throws IOException {
+        if(entryStream == null || !skipToEntry(entryStream, entry)) {
+            if (internalEntryStream != null) {
+                internalEntryStream.close();
+            }
+            internalEntryStream = new FileInputStream(file);
+            // First, check if it's a GzipCompressorInputStream.
+            try {
+                internalEntryStream = new GzipCompressorInputStream(internalEntryStream);
+            } catch(IOException e) {
+                //If it is not compressed we close
+                //the old one and recreate
+                internalEntryStream.close();
+                internalEntryStream = new FileInputStream(file);
+            }
+            entryStream = new TarArchiveInputStream(internalEntryStream) {
+                @Override
+                public void close() {
+                    // Ignore close() since we want to reuse the stream.
+                }
+            };
+            skipToEntry(entryStream, entry);
+        }
+        return entryStream;
+    }
+
+    private static boolean skipToEntry(TarArchiveInputStream entryStream, TarArchiveEntry entry) throws IOException {
+        TarArchiveEntry e = entryStream.getNextTarEntry();
+        while (e != null) {
+            if (e.equals(entry)) {
+                return true;
+            }
+
+            e = entryStream.getNextTarEntry();
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the path name of the file this archive represents.
+     *
+     * @return path
+     */
+    public String getName() {
+        return file.getPath();
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        close();
+    }
 }
index 93db412f194618363b767ed0372680dc710e5fd2..e93ab02a1c56f8368c1ff89d1b9d6b72fc1fbf8b 100644 (file)
@@ -16,6 +16,7 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.URIUtil;
@@ -26,10 +27,10 @@ import org.eclipse.core.runtime.URIUtil;
  */
 class TarFileSystemObject implements IFileSystemObject {
 
-    private TarEntry fFileSystemObject;
+    private TarArchiveEntry fFileSystemObject;
     private String fArchivePath;
 
-    TarFileSystemObject(TarEntry fileSystemObject, String archivePath) {
+    TarFileSystemObject(TarArchiveEntry fileSystemObject, String archivePath) {
         fFileSystemObject = fileSystemObject;
         fArchivePath = archivePath;
     }
@@ -71,6 +72,6 @@ class TarFileSystemObject implements IFileSystemObject {
 
     @Override
     public boolean isDirectory() {
-        return fFileSystemObject.getFileType() == TarEntry.DIRECTORY;
+        return fFileSystemObject.isDirectory();
     }
 }
\ No newline at end of file
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarInputStream.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarInputStream.java
deleted file mode 100644 (file)
index 06b6347..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace Compass to work around bug 501379
- *******************************************************************************/
-package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
-
-/**
- * Input stream for reading files in ustar format (tar) compatible
- * with the specification in IEEE Std 1003.1-2001.  Also supports
- * long filenames encoded using the GNU @LongLink extension.
- */
-@SuppressWarnings("restriction")
-public class TarInputStream extends FilterInputStream
-{
-       private int nextEntry = 0;
-       private int nextEOF = 0;
-       private int filepos = 0;
-       private long bytesread = 0;
-       private TarEntry firstEntry = null;
-       private String longLinkName = null;
-
-       /**
-        * Creates a new tar input stream on the given input stream.
-        *
-        * @param in input stream
-     * @throws TarException on Tar error (bad format, etc)
-     * @throws IOException on i/o error
-        */
-       public TarInputStream(InputStream in) throws TarException, IOException {
-               super(in);
-
-               // Read in the first TarEntry to make sure
-               // the input is a valid tar file stream.
-               firstEntry = getNextEntry();
-       }
-
-       /**
-        * Create a new tar input stream, skipping ahead to the given entry
-        * in the file.
-        *
-        * @param in input stream
-        * @param entry skips to this entry in the file
-        * @throws TarException
-        * @throws IOException
-        */
-       TarInputStream(InputStream in, TarEntry entry) throws TarException, IOException {
-               super(in);
-               skipToEntry(entry);
-       }
-
-       /**
-        *  The checksum of a tar file header is simply the sum of the bytes in
-        *  the header.
-        *
-        * @param header
-        * @return checksum
-        */
-       private static long headerChecksum(byte[] header) {
-               long sum = 0;
-               for(int i = 0; i < 512; i++) {
-                       sum += header[i] & 0xff;
-               }
-               return sum;
-       }
-
-       /**
-        * Skips ahead to the position of the given entry in the file.
-        *
-        * @param entry
-        * @returns false if the entry has already been passed
-        * @throws TarException
-        * @throws IOException
-        */
-       boolean skipToEntry(TarEntry entry) throws TarException, IOException {
-               long bytestoskip = entry.filepos - bytesread;
-               if(bytestoskip < 0) {
-                       return false;
-               }
-               while(bytestoskip > 0) {
-                       long ret = in.skip(bytestoskip);
-                       if(ret < 0) {
-                               throw new IOException("early end of stream"); //$NON-NLS-1$
-                       }
-                       bytestoskip -= ret;
-                       bytesread += ret;
-               }
-               filepos = entry.filepos;
-               nextEntry = 0;
-               nextEOF = 0;
-               // Read next header to seek to file data.
-               getNextEntry();
-               return true;
-       }
-
-       /**
-        * Returns true if the header checksum is correct.
-        *
-        * @param header
-        * @return true if this header has a valid checksum
-        */
-       private static boolean isValidTarHeader(byte[] header) {
-               long fileChecksum, calculatedChecksum;
-               int pos, i;
-
-               pos = 148;
-               StringBuffer checksumString = new StringBuffer();
-               for(i = 0; i < 8; i++) {
-                       if(header[pos + i] == ' ') {
-                               continue;
-                       }
-                       if(header[pos + i] == 0 || !Character.isDigit((char) header[pos + i])) {
-                               break;
-                       }
-                       checksumString.append((char) header[pos + i]);
-               }
-               if(checksumString.length() == 0) {
-                       return false;
-               }
-               if(checksumString.charAt(0) != '0') {
-                       checksumString.insert(0, '0');
-               }
-               try {
-                       fileChecksum = Long.decode(checksumString.toString()).longValue();
-               } catch(NumberFormatException exception) {
-                       //This is not valid if it cannot be parsed
-                       return false;
-               }
-
-               // Blank out the checksum.
-               for(i = 0; i < 8; i++) {
-                       header[pos + i] = ' ';
-               }
-               calculatedChecksum = headerChecksum(header);
-
-               return (fileChecksum == calculatedChecksum);
-       }
-
-       /**
-        * Returns the next entry in the tar file.  Does not handle
-        * GNU @LongLink extensions.
-        *
-        * @return the next entry in the tar file
-        * @throws TarException
-        * @throws IOException
-        */
-       TarEntry getNextEntryInternal() throws TarException, IOException {
-               byte[] header = new byte[512];
-               int pos = 0;
-               int i;
-
-               if(firstEntry != null) {
-                       TarEntry entryReturn = firstEntry;
-                       firstEntry = null;
-                       return entryReturn;
-               }
-
-               while(nextEntry > 0) {
-                       long ret = in.skip(nextEntry);
-                       if(ret < 0) {
-                               throw new IOException("early end of stream"); //$NON-NLS-1$
-                       }
-                       nextEntry -= ret;
-                       bytesread += ret;
-               }
-
-               int bytestoread = 512;
-               while(bytestoread > 0) {
-                       int ret = super.read(header, 512 - bytestoread, bytestoread);
-                       if( ret < 0 ) {
-                               throw new IOException("early end of stream"); //$NON-NLS-1$
-                       }
-                       bytestoread -= ret;
-                       bytesread += ret;
-               }
-
-               // If we have a header of all zeros, this marks the end of the file.
-               if(headerChecksum(header) == 0) {
-                       // We are at the end of the file.
-                       if(filepos > 0) {
-                               return null;
-                       }
-
-                       // Invalid stream.
-                       throw new TarException("not in tar format"); //$NON-NLS-1$
-               }
-
-               // Validate checksum.
-               if(!isValidTarHeader(header)) {
-                       throw new TarException("not in tar format"); //$NON-NLS-1$
-               }
-
-               while (pos < 100 && header[pos] != 0) {
-                       pos++;
-               }
-               String name = new String(header, 0, pos, "UTF8"); //$NON-NLS-1$
-               // Prepend the prefix here.
-               pos = 345;
-               if(header[pos] != 0) {
-                       while (pos < 500 && header[pos] != 0) {
-                               pos++;
-                       }
-                       String prefix = new String(header, 345, pos - 345, "UTF8"); //$NON-NLS-1$
-                       name = prefix + "/" + name; //$NON-NLS-1$
-               }
-
-               TarEntry entry;
-               if(longLinkName != null) {
-                       entry = new TarEntry(longLinkName, filepos);
-                       longLinkName = null;
-               } else {
-                       entry = new TarEntry(name, filepos);
-               }
-               if(header[156] != 0) {
-                       entry.setFileType(header[156]);
-               }
-
-               pos = 100;
-               StringBuffer mode = new StringBuffer();
-               for(i = 0; i < 8; i++) {
-                       if(header[pos + i] == 0) {
-                               break;
-                       }
-                       if(header[pos + i] == ' ') {
-                               continue;
-                       }
-                       mode.append((char) header[pos + i]);
-               }
-               if(mode.length() > 0 && mode.charAt(0) != '0') {
-                       mode.insert(0, '0');
-               }
-               try {
-                       long fileMode = Long.decode(mode.toString()).longValue();
-                       entry.setMode(fileMode);
-               } catch(NumberFormatException nfe) {
-                       throw new TarException(DataTransferMessages.TarImport_invalid_tar_format, nfe);
-               }
-
-               pos = 100 + 24;
-               StringBuffer size = new StringBuffer();
-               for(i = 0; i < 12; i++) {
-                       if(header[pos + i] == 0) {
-                               break;
-                       }
-                       if(header[pos + i] == ' ') {
-                               continue;
-                       }
-                       size.append((char) header[pos + i]);
-               }
-               if(size.charAt(0) != '0') {
-                       size.insert(0, '0');
-               }
-               int fileSize;
-               try {
-                       fileSize = Integer.decode(size.toString()).intValue();
-               } catch(NumberFormatException nfe) {
-                       throw new TarException(DataTransferMessages.TarImport_invalid_tar_format, nfe);
-               }
-
-               entry.setSize(fileSize);
-               nextEOF = fileSize;
-               if(fileSize % 512 > 0) {
-                       nextEntry = fileSize + (512 - (fileSize % 512));
-               } else {
-                       nextEntry = fileSize;
-               }
-               filepos += (nextEntry + 512);
-               return entry;
-       }
-
-       /**
-        * Moves ahead to the next file in the tar archive and returns
-        * a TarEntry object describing it.
-        *
-        * @return the next entry in the tar file
-     * @throws TarException on Tar error (bad format, etc)
-     * @throws IOException on i/o errors
-        */
-       public TarEntry getNextEntry() throws TarException, IOException {
-               TarEntry entry = getNextEntryInternal();
-
-               if(entry != null && entry.getName().equals("././@LongLink")) { //$NON-NLS-1$
-                       // This is a GNU extension for doing long filenames.
-                       // We get a file called ././@LongLink which just contains
-                       // the real pathname.
-                       byte[] longNameData = new byte[(int) entry.getSize()];
-                       int nbytesread = 0;
-                       while (nbytesread < longNameData.length) {
-                               int cur = read(longNameData, nbytesread, longNameData.length - nbytesread);
-                               if (cur < 0) {
-                                       throw new IOException("early end of stream"); //$NON-NLS-1$
-                               }
-                               nbytesread += cur;
-                       }
-
-                       int pos = 0;
-                       while (pos < longNameData.length && longNameData[pos] != 0) {
-                               pos++;
-                       }
-                       longLinkName = new String(longNameData, 0, pos, "UTF8"); //$NON-NLS-1$
-                       return getNextEntryInternal();
-               }
-               return entry;
-       }
-
-       @Override
-       public int read(byte[] b, int off, int len) throws IOException {
-           int lenToRead = len;
-               if(nextEOF == 0) {
-                       return -1;
-               }
-               if(lenToRead > nextEOF) {
-                   lenToRead = nextEOF;
-               }
-               int size = super.read(b, off, lenToRead);
-               nextEntry -= size;
-               nextEOF -= size;
-               bytesread += size;
-               return size;
-       }
-
-       @Override
-       public int read() throws IOException {
-               byte[] data = new byte[1];
-               int size = read(data, 0, 1);
-               if (size < 0) {
-                       return size;
-               }
-               return data[0];
-       }
-}
index 685657865291bffc05283d4f5f6498492636ab38..4ecdad54f03c730f82d5b01de8b6eb743fd30770 100644 (file)
@@ -11,6 +11,7 @@
  *     IImportStructureProvider to ILeveledImportStructureProvider
  *     Mickael Istria (Red Hat Inc.) - Bug 486901
  *     Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace Compass to work around bug 501379
+ *     Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Adapted to use Apache Common Compress
  *******************************************************************************/
 package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
 
@@ -22,6 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.eclipse.core.resources.ResourceAttributes;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
@@ -39,11 +41,11 @@ public class TarLeveledStructureProvider implements
         ILeveledImportStructureProvider {
     private TarFile tarFile;
 
-    private TarEntry root = new TarEntry("/");//$NON-NLS-1$
+    private TarArchiveEntry root = new TarArchiveEntry("/", true);//$NON-NLS-1$
 
-    private Map<TarEntry, List<TarEntry>> children;
+    private Map<TarArchiveEntry, List<TarArchiveEntry>> children;
 
-    private Map<IPath, TarEntry> directoryEntryCache = new HashMap<>();
+    private Map<IPath, TarArchiveEntry> directoryEntryCache = new HashMap<>();
 
     private int stripLevel;
 
@@ -57,35 +59,36 @@ public class TarLeveledStructureProvider implements
     public TarLeveledStructureProvider(TarFile sourceFile) {
         super();
         tarFile = sourceFile;
-        root.setFileType(TarEntry.DIRECTORY);
     }
 
     /**
      * Creates a new container tar entry with the specified name, iff it has
      * not already been created. If the parent of the given element does not
      * already exist it will be recursively created as well.
-     * @param pathname The path representing the container
+     * @param pathName The path representing the container
      * @return The element represented by this pathname (it may have already existed)
      */
-    protected TarEntry createContainer(IPath pathname) {
-        TarEntry existingEntry = directoryEntryCache.get(pathname);
+    protected TarArchiveEntry createContainer(IPath pathName) {
+        IPath newPathName = pathName;
+        TarArchiveEntry existingEntry = directoryEntryCache.get(newPathName);
         if (existingEntry != null) {
             return existingEntry;
         }
 
-        TarEntry parent;
-        if (pathname.segmentCount() == 1) {
+        TarArchiveEntry parent;
+        if (newPathName.segmentCount() == 1) {
             parent = root;
         } else {
-            parent = createContainer(pathname.removeLastSegments(1));
+            parent = createContainer(newPathName.removeLastSegments(1));
         }
-        TarEntry newEntry = new TarEntry(pathname.toString());
-        newEntry.setFileType(TarEntry.DIRECTORY);
-        directoryEntryCache.put(pathname, newEntry);
-        List<TarEntry> childList = new ArrayList<>();
+        // Add trailing / so that the entry knows it's a folder
+        newPathName = newPathName.addTrailingSeparator();
+        TarArchiveEntry newEntry = new TarArchiveEntry(newPathName.toString());
+        directoryEntryCache.put(newPathName, newEntry);
+        List<TarArchiveEntry> childList = new ArrayList<>();
         children.put(newEntry, childList);
 
-        List<TarEntry> parentChildList = children.get(parent);
+        List<TarArchiveEntry> parentChildList = children.get(parent);
         NonNullUtils.checkNotNull(parentChildList).add(newEntry);
         return newEntry;
     }
@@ -94,9 +97,9 @@ public class TarLeveledStructureProvider implements
      * Creates a new tar file entry with the specified name.
      * @param entry the entry to create the file for
      */
-    protected void createFile(TarEntry entry) {
+    protected void createFile(TarArchiveEntry entry) {
         IPath pathname = new Path(entry.getName());
-        TarEntry parent;
+        TarArchiveEntry parent;
         if (pathname.segmentCount() == 1) {
             parent = root;
         } else {
@@ -104,7 +107,7 @@ public class TarLeveledStructureProvider implements
                     .removeLastSegments(1));
         }
 
-        List<TarEntry> childList = children.get(parent);
+        List<TarArchiveEntry> childList = children.get(parent);
         NonNullUtils.checkNotNull(childList).add(entry);
     }
 
@@ -120,10 +123,7 @@ public class TarLeveledStructureProvider implements
     @Override
     public InputStream getContents(Object element) {
         try {
-            return tarFile.getInputStream((TarEntry) element);
-        } catch (TarException e) {
-            IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e);
-            return null;
+            return tarFile.getInputStream((TarArchiveEntry) element);
         } catch (IOException e) {
             IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e);
             return null;
@@ -138,7 +138,7 @@ public class TarLeveledStructureProvider implements
      */
     public ResourceAttributes getResourceAttributes(Object element) {
         ResourceAttributes attributes = new ResourceAttributes();
-        TarEntry entry = (TarEntry) element;
+        TarArchiveEntry entry = (TarArchiveEntry) element;
         attributes.setExecutable((entry.getMode() & 0100) != 0);
         attributes.setReadOnly((entry.getMode() & 0200) == 0);
         return attributes;
@@ -146,24 +146,24 @@ public class TarLeveledStructureProvider implements
 
     @Override
     public String getFullPath(Object element) {
-        String name = stripPath(((TarEntry) element).getName());
+        String name = stripPath(((TarArchiveEntry) element).getName());
         return ArchiveUtil.toValidNamesPath(name).toOSString();
     }
 
     @Override
     public String getLabel(Object element) {
         if (element.equals(root)) {
-            return ((TarEntry) element).getName();
+            return ((TarArchiveEntry) element).getName();
         }
 
-        String name = ((TarEntry) element).getName();
+        String name = ((TarArchiveEntry) element).getName();
         return stripPath(ArchiveUtil.toValidNamesPath(name).lastSegment());
     }
 
     /**
      * Returns the entry that this importer uses as the root sentinel.
      *
-     * @return TarEntry entry
+     * @return TarArchiveEntry entry
      */
     @Override
     public Object getRoot() {
@@ -199,12 +199,12 @@ public class TarLeveledStructureProvider implements
         children = new HashMap<>(1000);
 
         children.put(root, new ArrayList<>());
-        Enumeration<TarEntry> entries = tarFile.entries();
+        Enumeration<TarArchiveEntry> entries = tarFile.entries();
         while (entries.hasMoreElements()) {
-            TarEntry entry = entries.nextElement();
+            TarArchiveEntry entry = entries.nextElement();
             IPath path = new Path(entry.getName()).addTrailingSeparator();
 
-            if (entry.getFileType() == TarEntry.DIRECTORY) {
+            if (entry.isDirectory()) {
                 createContainer(path);
             } else
             {
@@ -221,7 +221,7 @@ public class TarLeveledStructureProvider implements
 
     @Override
     public boolean isFolder(Object element) {
-        return (((TarEntry) element).getFileType() == TarEntry.DIRECTORY);
+        return (((TarArchiveEntry) element).isDirectory());
     }
 
     /*
index 93b1ee9d67cd97558b07342cdf010648c30535f9..6a90871db160b94382506aaaed8dcd85635cfd73 100644 (file)
@@ -17,6 +17,7 @@ import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -133,6 +134,51 @@ public class TraceValidateAndImportOperation extends TmfWorkspaceModifyOperation
         fSelectedFileSystemElements = traceFileSystemElements;
     }
 
+    /**
+     * This orders by files first then the folders. Then by lexical order.
+     * This comparator handles full paths.
+     * Example of ordering:
+     *
+     * /trace.txt
+     * /folderA/trace.txt
+     * /folderA/folderB/trace.txt
+     * /folderZ/trace.txt
+     */
+    private final class FileObjectPathComparator implements Comparator<TraceFileSystemElement> {
+        @Override
+        public int compare(TraceFileSystemElement e1, TraceFileSystemElement e2) {
+            IFileSystemObject o1 = e1.getFileSystemObject();
+            IFileSystemObject o2 = e2.getFileSystemObject();
+            IPath p1 = new Path(e1.getProvider().getFullPath(o1));
+            IPath p2 = new Path(e2.getProvider().getFullPath(o2));
+            int segmentCount1 = p1.segmentCount();
+            int segmentCount2 = p2.segmentCount();
+
+            int commonParentSegmentCount = Math.min(segmentCount1, segmentCount2) - 1;
+            // Compare parents that are common (in terms of segment number).
+            // If one of them is different, we do not need to worry about any
+            // children, we already know in which order they are going to be.
+            for (int i = 0; i < commonParentSegmentCount; i++) {
+                int compare = p1.segment(i).compareToIgnoreCase(p2.segment(i));
+                if (compare != 0) {
+                    return compare;
+                }
+            }
+
+            // At this point, we know all the common parent folders are the same.
+            // Either:
+            // - One of them is shorter which means it should be processed first because files are processed before sub-folders.
+            // or
+            // - They are the same level so only the name matters.
+            if (segmentCount1 != segmentCount2) {
+                return Integer.compare(segmentCount1, segmentCount2);
+            }
+
+            //
+            return o1.getName().compareToIgnoreCase(o2.getName());
+        }
+    }
+
     @Override
     protected void execute(IProgressMonitor progressMonitor) throws CoreException, InvocationTargetException, InterruptedException {
         try {
@@ -246,6 +292,10 @@ public class TraceValidateAndImportOperation extends TmfWorkspaceModifyOperation
     private void importFileSystemElements(IProgressMonitor monitor, List<TraceFileSystemElement> fileSystemElements)
             throws InterruptedException, TmfTraceImportException, CoreException, InvocationTargetException {
         SubMonitor subMonitor = SubMonitor.convert(monitor, fileSystemElements.size());
+        // Sort the elements in a sensible order to make it more predictable to
+        // the user when there can be name clashes. Otherwise, the order can
+        // seem pretty random depending on the OS/Filesystem.
+        fileSystemElements.sort(new FileObjectPathComparator());
 
         ListIterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.listIterator();
 
index d0204f8cdafbaa87dec6ce6ef4d3d67c7cbd0d94..2f6822d31d7cc3c5c9a4b98e545ba2777cff84db 100644 (file)
@@ -15,8 +15,8 @@ package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
-import java.util.zip.ZipEntry;
 
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.URIUtil;
@@ -26,10 +26,10 @@ import org.eclipse.core.runtime.URIUtil;
  */
 class ZipFileSystemObject implements IFileSystemObject {
 
-    private ZipEntry fFileSystemObject;
+    private ZipArchiveEntry fFileSystemObject;
     private String fArchivePath;
 
-    ZipFileSystemObject(ZipEntry fileSystemObject, String archivePath) {
+    ZipFileSystemObject(ZipArchiveEntry fileSystemObject, String archivePath) {
         fFileSystemObject = fileSystemObject;
         fArchivePath = archivePath;
     }
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipLeveledStructureProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipLeveledStructureProvider.java
new file mode 100644 (file)
index 0000000..1e2bba9
--- /dev/null
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Red Hat, Inc - Was ZipFileStructureProvider, performed changes from
+ *     IImportStructureProvider to ILeveledImportStructureProvider
+ *     Mickael Istria (Red Hat Inc.) - Bug 486901
+ *     Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace
+ *     Compass to use Apache Common Compress and fix bug 501664
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
+import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider;
+
+/**
+ * This class provides information regarding the context structure and content
+ * of specified zip file entry objects.
+ *
+ * This structure provider also makes sure to return safe paths. For example,
+ * if a Zip entry contains a ':' and is extracted on Windows, it will be changed
+ * to a '_'
+ */
+@SuppressWarnings("restriction")
+public class ZipLeveledStructureProvider implements
+        ILeveledImportStructureProvider {
+    private ZipFile zipFile;
+
+    private ZipArchiveEntry root = new ZipArchiveEntry("/");//$NON-NLS-1$
+
+    private Map<ZipArchiveEntry, List<ZipArchiveEntry>> children;
+
+    private Map<IPath, ZipArchiveEntry> directoryEntryCache = new HashMap<>();
+
+    private int stripLevel;
+
+    /**
+     * Creates a <code>ZipFileStructureProvider</code>, which will operate on
+     * the passed zip file.
+     *
+     * @param sourceFile
+     *            The source file to create the ZipLeveledStructureProvider
+     *            around
+     */
+    public ZipLeveledStructureProvider(ZipFile sourceFile) {
+        super();
+        zipFile = sourceFile;
+        stripLevel = 0;
+    }
+
+    /**
+     * Creates a new container zip entry with the specified name, iff it has
+     * not already been created. If the parent of the given element does not
+     * already exist it will be recursively created as well.
+     * @param pathname The path representing the container
+     * @return The element represented by this pathname (it may have already existed)
+     */
+    protected ZipArchiveEntry createContainer(IPath pathname) {
+        ZipArchiveEntry existingEntry = directoryEntryCache.get(pathname);
+        if (existingEntry != null) {
+            return existingEntry;
+        }
+
+        ZipArchiveEntry parent;
+        if (pathname.segmentCount() == 0) {
+            return null;
+        } else if (pathname.segmentCount() == 1) {
+            parent = root;
+        } else {
+            parent = createContainer(pathname.removeLastSegments(1));
+        }
+        ZipArchiveEntry newEntry = new ZipArchiveEntry(pathname.toString());
+        directoryEntryCache.put(pathname, newEntry);
+        List<ZipArchiveEntry> childList = new ArrayList<>();
+        children.put(newEntry, childList);
+
+        List<ZipArchiveEntry> parentChildList = children.get(parent);
+        NonNullUtils.checkNotNull(parentChildList).add(newEntry);
+        return newEntry;
+    }
+
+    /**
+     * Creates a new file zip entry with the specified name.
+     * @param entry the entry to create the file for
+     */
+    protected void createFile(ZipArchiveEntry entry) {
+        IPath pathname = new Path(entry.getName());
+        ZipArchiveEntry parent;
+        if (pathname.segmentCount() == 1) {
+            parent = root;
+        } else {
+            parent = directoryEntryCache.get(pathname
+                    .removeLastSegments(1));
+        }
+
+        @Nullable List<ZipArchiveEntry> childList = children.get(parent);
+        NonNullUtils.checkNotNull(childList).add(entry);
+    }
+
+    @Override
+    public List getChildren(Object element) {
+        if (children == null) {
+            initialize();
+        }
+
+        return (children.get(element));
+    }
+
+    @Override
+    public InputStream getContents(Object element) {
+        try {
+            return zipFile.getInputStream((ZipArchiveEntry) element);
+        } catch (IOException e) {
+            IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e);
+            return null;
+        }
+    }
+
+    /*
+     * Strip the leading directories from the path
+     */
+    private String stripPath(String path) {
+        String strippedPath = path;
+        String pathOrig = strippedPath;
+        for (int i = 0; i < stripLevel; i++) {
+            int firstSep = strippedPath.indexOf('/');
+            // If the first character was a separator we must strip to the next
+            // separator as well
+            if (firstSep == 0) {
+                strippedPath = strippedPath.substring(1);
+                firstSep = strippedPath.indexOf('/');
+            }
+            // No separator was present so we're in a higher directory right
+            // now
+            if (firstSep == -1) {
+                return pathOrig;
+            }
+            strippedPath = strippedPath.substring(firstSep);
+        }
+        return strippedPath;
+    }
+
+    @Override
+    public String getFullPath(Object element) {
+        String name = ((ZipArchiveEntry) element).getName();
+        return ArchiveUtil.toValidNamesPath(name).toOSString();
+    }
+
+    @Override
+    public String getLabel(Object element) {
+        if (element.equals(getRoot())) {
+            return ((ZipArchiveEntry) element).getName();
+        }
+        String name = ((ZipArchiveEntry) element).getName();
+        return stripPath(ArchiveUtil.toValidNamesPath(name).lastSegment());
+    }
+
+    /**
+     * Returns the entry that this importer uses as the root sentinel.
+     *
+     * @return ZipArchiveEntry
+     */
+    @Override
+    public Object getRoot() {
+        return root;
+    }
+
+    /**
+     * Returns the zip file that this provider provides structure for.
+     *
+     * @return The zip file
+     */
+    public ZipFile getZipFile() {
+        return zipFile;
+    }
+
+
+    @Override
+    public boolean closeArchive(){
+        try {
+            getZipFile().close();
+        } catch (IOException e) {
+            IDEWorkbenchPlugin.log(DataTransferMessages.ZipImport_couldNotClose
+                    + getZipFile(), e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Initializes this object's children table based on the contents of the
+     * specified source file.
+     */
+    protected void initialize() {
+        children = new HashMap<>(1000);
+
+        children.put(root, new ArrayList<>());
+        Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
+        while (entries.hasMoreElements()) {
+            ZipArchiveEntry entry = entries.nextElement();
+            IPath path = new Path(entry.getName()).addTrailingSeparator();
+
+            if (entry.isDirectory()) {
+                createContainer(path);
+            } else
+            {
+                // Ensure the container structure for all levels above this is initialized
+                // Once we hit a higher-level container that's already added we need go no further
+                int pathSegmentCount = path.segmentCount();
+                if (pathSegmentCount > 1) {
+                    createContainer(path.uptoSegment(pathSegmentCount - 1));
+                }
+                createFile(entry);
+            }
+        }
+    }
+
+    @Override
+    public boolean isFolder(Object element) {
+        return ((ZipArchiveEntry) element).isDirectory();
+    }
+
+    @Override
+    public void setStrip(int level) {
+        stripLevel = level;
+    }
+
+    @Override
+    public int getStrip() {
+        return stripLevel;
+    }
+}
index baace2bb96a388be8525e4e348f1752321bffe6c..756e422d9e5585d2835a2011c2187cd658ef2527 100644 (file)
 
 package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Enumeration;
 import java.util.Vector;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
 
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.TarEntry;
-import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.TarException;
 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.TarFile;
 
 /**
@@ -120,15 +120,20 @@ public abstract class AbstractTracePackageOperation {
             return null;
         }
 
+        File file = new File(fFileName);
+        if (file.isDirectory()) {
+            return null;
+        }
+
         try {
-            return new ZipArchiveFile(new ZipFile(fFileName));
+            return new ZipArchiveFile(new ZipFile(file));
         } catch (IOException e) {
             // ignore
         }
 
         try {
-            return new TarArchiveFile(new TarFile(fFileName));
-        } catch (TarException | IOException e) {
+            return new TarArchiveFile(new TarFile(file));
+        } catch (IOException e) {
             // ignore
         }
 
@@ -176,7 +181,7 @@ public abstract class AbstractTracePackageOperation {
     }
 
     /**
-     * Common interface between ZipEntry and TarEntry
+     * Common interface between ZipArchiveEntry and TarArchiveEntry
      */
     protected interface ArchiveEntry {
         /**
@@ -211,10 +216,9 @@ public abstract class AbstractTracePackageOperation {
          * @param entry
          *            the given file
          * @return an input stream for the given file
-         * @throws TarException
          * @throws IOException
          */
-        InputStream getInputStream(ArchiveEntry entry) throws TarException, IOException;
+        InputStream getInputStream(ArchiveEntry entry) throws IOException;
     }
 
     /**
@@ -238,7 +242,7 @@ public abstract class AbstractTracePackageOperation {
         public Enumeration<@NonNull ? extends ArchiveEntry> entries() {
             Vector<@NonNull ArchiveEntry> v = new Vector<>();
             for (Enumeration<?> e = fTarFile.entries(); e.hasMoreElements();) {
-                v.add(new TarArchiveEntry((TarEntry) e.nextElement()));
+                v.add(new TarArchiveEntryAdapter((TarArchiveEntry) e.nextElement()));
             }
 
             return v.elements();
@@ -250,24 +254,24 @@ public abstract class AbstractTracePackageOperation {
         }
 
         @Override
-        public InputStream getInputStream(ArchiveEntry entry) throws TarException, IOException {
-            return fTarFile.getInputStream(((TarArchiveEntry) entry).getTarEntry());
+        public InputStream getInputStream(ArchiveEntry entry) throws IOException {
+            return fTarFile.getInputStream(((TarArchiveEntryAdapter) entry).getTarEntry());
         }
     }
 
     /**
-     * Adapter for TarEntry to ArchiveEntry
+     * Adapter for TarArchiveEntry to ArchiveEntry
      */
-    protected class TarArchiveEntry implements ArchiveEntry {
-        private TarEntry fTarEntry;
+    protected class TarArchiveEntryAdapter implements ArchiveEntry {
+        private TarArchiveEntry fTarEntry;
 
         /**
-         * Constructs a TarArchiveEntry for a TarEntry
+         * Constructs a TarArchiveEntry for a TarArchiveEntry
          *
          * @param tarEntry
-         *            the TarEntry
+         *            the TarArchiveEntry
          */
-        public TarArchiveEntry(TarEntry tarEntry) {
+        public TarArchiveEntryAdapter(TarArchiveEntry tarEntry) {
             this.fTarEntry = tarEntry;
         }
 
@@ -277,11 +281,11 @@ public abstract class AbstractTracePackageOperation {
         }
 
         /**
-         * Get the corresponding TarEntry
+         * Get the corresponding TarArchiveEntry
          *
-         * @return the corresponding TarEntry
+         * @return the corresponding TarArchiveEntry
          */
-        public TarEntry getTarEntry() {
+        public TarArchiveEntry getTarEntry() {
             return fTarEntry;
         }
 
@@ -294,17 +298,17 @@ public abstract class AbstractTracePackageOperation {
     /**
      * Adapter for ArchiveEntry to ArchiveEntry
      */
-    protected class ZipAchiveEntry implements ArchiveEntry {
+    protected class ZipAchiveEntryAdapter implements ArchiveEntry {
 
-        private ZipEntry fZipEntry;
+        private ZipArchiveEntry fZipEntry;
 
         /**
-         * Constructs a ZipAchiveEntry for a ZipEntry
+         * Constructs a ZipAchiveEntryAdapter for a ZipArchiveEntry
          *
          * @param zipEntry
-         *            the ZipEntry
+         *            the ZipArchiveEntry
          */
-        public ZipAchiveEntry(ZipEntry zipEntry) {
+        public ZipAchiveEntryAdapter(ZipArchiveEntry zipEntry) {
             this.fZipEntry = zipEntry;
         }
 
@@ -314,11 +318,11 @@ public abstract class AbstractTracePackageOperation {
         }
 
         /**
-         * Get the corresponding ZipEntry
+         * Get the corresponding ZipArchiveEntry
          *
-         * @return the corresponding ZipEntry
+         * @return the corresponding ZipArchiveEntry
          */
-        public ZipEntry getZipEntry() {
+        public ZipArchiveEntry getZipEntry() {
             return fZipEntry;
         }
 
@@ -348,8 +352,8 @@ public abstract class AbstractTracePackageOperation {
         @Override
         public Enumeration<@NonNull ? extends ArchiveEntry> entries() {
             Vector<@NonNull ArchiveEntry> v = new Vector<>();
-            for (Enumeration<?> e = fZipFile.entries(); e.hasMoreElements();) {
-                v.add(new ZipAchiveEntry((ZipEntry) e.nextElement()));
+            for (Enumeration<ZipArchiveEntry> e = fZipFile.getEntries(); e.hasMoreElements();) {
+                v.add(new ZipAchiveEntryAdapter(e.nextElement()));
             }
 
             return v.elements();
@@ -361,8 +365,8 @@ public abstract class AbstractTracePackageOperation {
         }
 
         @Override
-        public InputStream getInputStream(ArchiveEntry entry) throws TarException, IOException {
-            return fZipFile.getInputStream(((ZipAchiveEntry) entry).getZipEntry());
+        public InputStream getInputStream(ArchiveEntry entry) throws IOException {
+            return fZipFile.getInputStream(((ZipAchiveEntryAdapter) entry).getZipEntry());
         }
     }
 
index 8f5cad157606e026bc01bfa075f055ffe438cc3e..acf6229f462dbed318140a079408027f67399102 100644 (file)
@@ -42,7 +42,6 @@ import org.eclipse.core.runtime.URIUtil;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jface.operation.ModalContext;
 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
-import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.TarException;
 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.AbstractTracePackageOperation;
 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageBookmarkElement;
 import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
@@ -107,8 +106,6 @@ public class TracePackageImportOperation extends AbstractTracePackageOperation i
                 inputStream = ((ArchiveProviderElement) element).getContents();
             } catch (IOException e) {
                 fException = e;
-            } catch (TarException e) {
-                fException = e;
             }
             return inputStream;
         }
@@ -148,7 +145,7 @@ public class TracePackageImportOperation extends AbstractTracePackageOperation i
             this.fEntry = entry;
         }
 
-        public InputStream getContents() throws TarException, IOException {
+        public InputStream getContents() throws IOException {
             return fArchiveFile.getInputStream(fEntry);
         }
 
This page took 0.051681 seconds and 5 git commands to generate.