--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc-Andre Laperle - Initial API and implementation. Inspired from TarEntry.
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+/**
+ * GZip entry
+ */
+public class GzipEntry {
+ private static final String ROOT_DIR = "/"; //$NON-NLS-1$
+ private final String fName;
+ private final long fMode;
+ private final long fTime;
+ private final int fType;
+
+ /**
+ * Entry type for normal files. This is the only valid type for Gzip
+ * entries.
+ */
+ public static final int FILE = '0';
+
+ /**
+ * Entry type for directories. This doesn't really exist in a Gzip but it's
+ * useful to represent the root of the archive.
+ */
+ public static final int DIRECTORY = '5';
+
+ /**
+ * Create a new Root GzipEntry
+ */
+ public GzipEntry() {
+ fName = ROOT_DIR;
+ fMode = 0644;
+ fType = DIRECTORY;
+ fTime = System.currentTimeMillis() / 1000;
+ }
+
+ /**
+ * Create a new GzipEntry for a file of the given name at the given position
+ * in the file.
+ *
+ * @param name
+ * filename
+ */
+ public GzipEntry(String name) {
+ fName = name;
+ fMode = 0644;
+ fType = FILE;
+ fTime = System.currentTimeMillis() / 1000;
+ }
+
+ /**
+ * Returns the type of this file, can only be FILE for a real Gzip entry.
+ * DIRECTORY can be specified to represent a "dummy root" in the archive.
+ *
+ * @return file type
+ */
+ public int getFileType() {
+ return fType;
+ }
+
+ /**
+ * Returns the mode of the file in UNIX permissions format.
+ *
+ * @return file mode
+ */
+ public long getMode() {
+ return fMode;
+ }
+
+ /**
+ * Returns the name of the file.
+ *
+ * @return filename
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Returns the modification time of the file in seconds since January 1st
+ * 1970.
+ *
+ * @return time
+ */
+ public long getTime() {
+ return fTime;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc-Andre Laperle - Initial API and implementation.
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * Wrapper for a Gzipped file
+ */
+public class GzipFile implements AutoCloseable {
+
+ private static final String GZIP_EXTENSION = ".gz"; //$NON-NLS-1$
+
+ private final File fFile;
+ private final GzipEntry fEntry;
+ private GzipEntry fCurEntry;
+ private boolean fIsClosed = false;
+
+ private final InputStream fInternalEntryStream;
+
+ /**
+ * Create a new GzipFile for the given file.
+ *
+ * @param source the source file
+ * @throws IOException
+ * File not found and such
+ */
+ public GzipFile(File source) throws IOException {
+ fFile = source;
+
+ InputStream in = new FileInputStream(source);
+ // Check if it's a GZIPInputStream.
+ fInternalEntryStream = new GZIPInputStream(in);
+ String name = source.getName();
+ fEntry = new GzipEntry(name.substring(0, name.lastIndexOf(GZIP_EXTENSION)));
+ fCurEntry = fEntry;
+ }
+
+ /**
+ * Close the tar file input stream.
+ *
+ * @throws IOException if the file cannot be successfully closed
+ */
+ @Override
+ public void close() throws IOException {
+ if (fInternalEntryStream != null && !fIsClosed) {
+ fInternalEntryStream.close();
+ fIsClosed = true;
+
+ }
+ }
+
+ /**
+ * Create a new GzipFile for the given path name.
+ *
+ * @param filename
+ * the filename of the gzip file
+ * @throws IOException
+ * if the file cannot be opened
+ */
+ public GzipFile(String filename) throws IOException {
+ this(new File(filename));
+ }
+
+ /**
+ * Returns an enumeration cataloguing the tar archive.
+ *
+ * @return enumeration of all files in the archive
+ */
+ public Enumeration<GzipEntry> entries() {
+ return new Enumeration<GzipEntry>() {
+ @Override
+ public boolean hasMoreElements() {
+ return (fCurEntry != null);
+ }
+
+ @Override
+ public GzipEntry nextElement() {
+ GzipEntry oldEntry = fCurEntry;
+ fCurEntry = null;
+ return oldEntry;
+ }
+ };
+ }
+
+ /**
+ * Returns a new InputStream for the given file in the tar archive.
+ *
+ * @param entry
+ * the GzipEntry
+ * @return an input stream for the given file
+ */
+ public InputStream getInputStream(GzipEntry entry) {
+ if (entry != fEntry) {
+ throw new IllegalArgumentException();
+ }
+ return fInternalEntryStream;
+ }
+
+ /**
+ * Returns the path name of the file this archive represents.
+ *
+ * @return path
+ */
+ public String getName() {
+ return fFile.getPath();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ close();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc-Andre Laperle - Initial API and implementation.
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
+import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider;
+
+/**
+ * Leveled Structure provider for Gzip file
+ */
+@SuppressWarnings("restriction")
+public class GzipLeveledStructureProvider implements ILeveledImportStructureProvider {
+
+ private final GzipFile fFile;
+ private final GzipEntry root = new GzipEntry();
+ private final GzipEntry fEntry;
+
+ /**
+ * Creates a <code>GzipFileStructureProvider</code>, which will operate on
+ * the passed Gzip file.
+ *
+ * @param sourceFile
+ * the source GzipFile
+ */
+ public GzipLeveledStructureProvider(GzipFile sourceFile) {
+ super();
+
+ fFile = sourceFile;
+ fEntry = sourceFile.entries().nextElement();
+ }
+
+ @Override
+ public List getChildren(Object element) {
+ ArrayList<Object> children = new ArrayList<>();
+ if (element == root) {
+ children.add(fEntry);
+ }
+ return children;
+ }
+
+ @Override
+ public InputStream getContents(Object element) {
+ return fFile.getInputStream((GzipEntry) element);
+ }
+
+ @Override
+ public String getFullPath(Object element) {
+ return ((GzipEntry) element).getName();
+ }
+
+ @Override
+ public String getLabel(Object element) {
+ if (element != root && element != fEntry) {
+ throw new IllegalArgumentException();
+ }
+ return ((GzipEntry) element).getName();
+ }
+
+ /**
+ * Returns the entry that this importer uses as the root sentinel.
+ *
+ * @return GzipEntry entry
+ */
+ @Override
+ public GzipEntry getRoot() {
+ return root;
+ }
+
+ @Override
+ public boolean closeArchive() {
+ try {
+ fFile.close();
+ } catch (IOException e) {
+ Activator.getDefault().logError(DataTransferMessages.ZipImport_couldNotClose
+ + fFile.getName(), e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isFolder(Object element) {
+ return ((GzipEntry) element).getFileType() == GzipEntry.DIRECTORY;
+ }
+
+ @Override
+ public void setStrip(int level) {
+ // Do nothing
+ }
+
+ @Override
+ public int getStrip() {
+ return 0;
+ }
+}
* Bernd Hufmann - Re-design of trace selection and trace validation
* Marc-Andre Laperle - Preserve folder structure on import
* Marc-Andre Laperle - Extract archives during import
+ * Marc-Andre Laperle - Add support for Gzip (non-Tar)
*******************************************************************************/
package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
private static final String IMPORT_WIZARD_IMPORT_FROM_DIRECTORY_ID = ".import_from_directory"; //$NON-NLS-1$
// constant from WizardArchiveFileResourceImportPage1
- private static final String[] FILE_IMPORT_MASK = { "*.jar;*.zip;*.tar;*.tar.gz;*.tgz", "*.*" }; //$NON-NLS-1$ //$NON-NLS-2$
+ private static final String[] FILE_IMPORT_MASK = { "*.jar;*.zip;*.tar;*.tar.gz;*.tgz;*.gz", "*.*" }; //$NON-NLS-1$ //$NON-NLS-2$
private static final String TRACE_IMPORT_TEMP_FOLDER = ".traceImport"; //$NON-NLS-1$
/**
return selectFiles(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond());
}
+ @SuppressWarnings("resource")
private Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> getRootObjectAndProvider(File sourceFile) {
if (sourceFile == null) {
return null;
} else if (ensureZipSourceIsValid(archivePath)) {
// We close the file when we dispose the import provider, see
// disposeSelectionGroupRoot
- @SuppressWarnings("resource")
ZipFile zipFile = getSpecifiedZipSourceFile(archivePath);
leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new ZipLeveledStructureProvider(zipFile), archivePath);
+ } else if (ensureGzipSourceIsValid(archivePath)) {
+ // We close the file when we dispose the import provider, see
+ // disposeSelectionGroupRoot
+ GzipFile zipFile = null;
+ try {
+ zipFile = new GzipFile(archivePath);
+ } catch (IOException e) {
+ }
+ leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new GzipLeveledStructureProvider(zipFile), archivePath);
}
if (leveledImportStructureProvider == null) {
return null;
/**
* An import provider that makes use of the IFileSystemObject abstraction
- * instead of using plain file system objects (File, TarEntry, ZipEntry)
+ * instead of using plain file system objects (File, TarEntry, ZipEntry, etc)
*/
private static class FileSystemObjectImportStructureProvider implements IImportStructureProvider {
return new TarFileSystemObject((TarEntry) o, fArchivePath);
} else if (o instanceof ZipEntry) {
return new ZipFileSystemObject((ZipEntry) o, fArchivePath);
+ } else if (o instanceof GzipEntry) {
+ return new GzipFileSystemObject((GzipEntry) o, fArchivePath);
}
throw new IllegalArgumentException("Object type not handled"); //$NON-NLS-1$
return null;
}
+ private static boolean ensureGzipSourceIsValid(String archivePath) {
+ return isGzipFile(archivePath);
+ }
+
private TraceFileSystemElement selectFiles(final IFileSystemObject rootFileSystemObject,
final FileSystemObjectImportStructureProvider structureProvider) {
final TraceFileSystemElement[] results = new TraceFileSystemElement[1];
return false;
}
- if (!isImportFromDirectory() && !ensureTarSourceIsValid(source.getAbsolutePath()) && !ensureZipSourceIsValid(source.getAbsolutePath())) {
+ if (!isImportFromDirectory() && !ensureTarSourceIsValid(source.getAbsolutePath()) && !ensureZipSourceIsValid(source.getAbsolutePath()) && !ensureGzipSourceIsValid(source.getAbsolutePath())) {
setMessage(null);
setErrorMessage(Messages.ImportTraceWizard_BadArchiveFormat);
return false;
private static boolean isArchiveFile(File sourceFile) {
String absolutePath = sourceFile.getAbsolutePath();
- return isTarFile(absolutePath) || ArchiveFileManipulations.isZipFile(absolutePath);
+ return isTarFile(absolutePath) || ArchiveFileManipulations.isZipFile(absolutePath) || isGzipFile(absolutePath);
+ }
+
+ private static boolean isGzipFile(String fileName) {
+ if (!fileName.isEmpty()) {
+ try (GzipFile specifiedTarSourceFile = new GzipFile(fileName);) {
+ return true;
+ } catch (IOException e) {
+ }
+ }
+ return false;
}
@Override
SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
destTempFolder.create(IResource.HIDDEN, true, monitor);
-
subMonitor = SubMonitor.convert(progressMonitor, 2);
String baseSourceLocation;
if (fImportFromArchive) {
/**
* This interface abstracts the differences between different kinds of
- * FileSystemObjects such as File, TarEntry and ZipEntry. This allows
+ * FileSystemObjects such as File, TarEntry, ZipEntry, etc. This allows
* clients (TraceFileSystemElement, TraceValidateAndImportOperation) to
* handle all the types transparently.
*/
}
/**
- * The "Tar" implementation of an IFileSystemObject
+ * The "Tar" implementation of an IFileSystemObject, entries can also be Gzipped and are uncompressed transparently.
*/
private static class TarFileSystemObject implements IFileSystemObject {
}
}
+ /**
+ * The "GZIP" implementation of an IFileSystemObject. For a GZIP file that is not in a tar.
+ */
+ private static class GzipFileSystemObject implements IFileSystemObject {
+
+ private GzipEntry fFileSystemObject;
+ private String fArchivePath;
+
+ private GzipFileSystemObject(GzipEntry fileSystemObject, String archivePath) {
+ fFileSystemObject = fileSystemObject;
+ fArchivePath = archivePath;
+ }
+
+ @Override
+ public String getLabel() {
+ return new Path(fFileSystemObject.getName()).lastSegment();
+ }
+
+ @Override
+ public String getName() {
+ return fFileSystemObject.getName();
+ }
+
+ @Override
+ public String getAbsolutePath(String parentContainerPath) {
+ return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString();
+ }
+
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public String getSourceLocation() {
+ File file = new File(fArchivePath);
+ try {
+ file = file.getCanonicalFile();
+ } catch (IOException e) {
+ // Will still work but might have extra ../ in the path
+ }
+ URI uri = file.toURI();
+ IPath entryPath = new Path(fFileSystemObject.getName());
+
+ URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath);
+ return URIUtil.toUnencodedString(jarURI);
+ }
+
+ @Override
+ public Object getRawFileSystemObject() {
+ return fFileSystemObject;
+ }
+ }
+
/**
* The "Zip" implementation of an IFileSystemObject
*/