From f17bb886f56f8c7d335aba2f1ec0b512533ddca6 Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Mon, 13 Jul 2015 02:11:34 -0400 Subject: [PATCH] tmf: Split ImportTraceWizardPage into multiple classes This should make it easier to reuse some parts and also reduce the file complexity. Change-Id: I790f8c86a1e7e7011d9f8350d68de4bbc73f5e76 Signed-off-by: Marc-Andre Laperle Reviewed-on: https://git.eclipse.org/r/51815 Reviewed-by: Hudson CI Reviewed-by: Bernd Hufmann Tested-by: Bernd Hufmann Reviewed-by: Matthew Khouzam --- .../wizards/importtrace/ArchiveUtil.java | 192 +++ .../importtrace/FileFileSystemObject.java | 88 ++ ...leSystemObjectImportStructureProvider.java | 100 ++ ...mObjectLeveledImportStructureProvider.java | 57 + .../importtrace/GzipFileSystemObject.java | 71 + .../importtrace/IFileSystemObject.java | 57 + .../importtrace/ImportTraceWizardPage.java | 1325 +---------------- .../importtrace/TarFileSystemObject.java | 73 + .../importtrace/TraceFileSystemElement.java | 231 +++ .../TraceValidateAndImportOperation.java | 686 +++++++++ .../importtrace/ZipFileSystemObject.java | 71 + 11 files changed, 1670 insertions(+), 1281 deletions(-) create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ArchiveUtil.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileFileSystemObject.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectImportStructureProvider.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectLeveledImportStructureProvider.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFileSystemObject.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/IFileSystemObject.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarFileSystemObject.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceFileSystemElement.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceValidateAndImportOperation.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipFileSystemObject.java diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ArchiveUtil.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ArchiveUtil.java new file mode 100644 index 0000000000..a466205adc --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ArchiveUtil.java @@ -0,0 +1,192 @@ +/******************************************************************************* + * 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.IOException; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tracecompass.tmf.core.util.Pair; +import org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileManipulations; +import org.eclipse.ui.internal.wizards.datatransfer.TarException; +import org.eclipse.ui.internal.wizards.datatransfer.TarFile; +import org.eclipse.ui.internal.wizards.datatransfer.TarLeveledStructureProvider; +import org.eclipse.ui.internal.wizards.datatransfer.ZipLeveledStructureProvider; +import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; + +/** + * Various utilities for dealing with archives in the context of importing + * traces. + */ +@SuppressWarnings({"restriction" }) +public class ArchiveUtil { + + /** + * Returns whether or not the source file is an archive file (Zip, tar, + * tar.gz, gz). + * + * @param sourceFile + * the source file + * @return whether or not the source file is an archive file + */ + public static boolean isArchiveFile(File sourceFile) { + String absolutePath = sourceFile.getAbsolutePath(); + return isTarFile(absolutePath) || ArchiveFileManipulations.isZipFile(absolutePath) || isGzipFile(absolutePath); + } + + private static boolean isTarFile(String fileName) { + TarFile specifiedTarSourceFile = getSpecifiedTarSourceFile(fileName); + if (specifiedTarSourceFile != null) { + try { + specifiedTarSourceFile.close(); + return true; + } catch (IOException e) { + // ignore + } + } + return false; + } + + private static boolean isGzipFile(String fileName) { + if (!fileName.isEmpty()) { + try (GzipFile specifiedTarSourceFile = new GzipFile(fileName);) { + return true; + } catch (IOException e) { + } + } + return false; + } + + private static ZipFile getSpecifiedZipSourceFile(String fileName) { + if (fileName.length() == 0) { + return null; + } + + try { + return new ZipFile(fileName); + } catch (ZipException e) { + // ignore + } catch (IOException e) { + // ignore + } + + return null; + } + + private static TarFile getSpecifiedTarSourceFile(String fileName) { + if (fileName.length() == 0) { + return null; + } + + // FIXME: Work around Bug 463633. Remove this block once we move to Eclipse 4.5. + if (new File(fileName).length() < 512) { + return null; + } + + try { + return new TarFile(fileName); + } catch (TarException | IOException e) { + // ignore + } + + return null; + } + + @SuppressWarnings("resource") + static boolean ensureZipSourceIsValid(String archivePath, Shell shell) { + ZipFile specifiedFile = getSpecifiedZipSourceFile(archivePath); + if (specifiedFile == null) { + return false; + } + return ArchiveFileManipulations.closeZipFile(specifiedFile, shell); + } + + static boolean ensureTarSourceIsValid(String archivePath, Shell shell) { + TarFile specifiedFile = getSpecifiedTarSourceFile(archivePath); + if (specifiedFile == null) { + return false; + } + return ArchiveFileManipulations.closeTarFile(specifiedFile, shell); + } + + static boolean ensureGzipSourceIsValid(String archivePath) { + return isGzipFile(archivePath); + } + + /** + * Get the root file system object and it's associated import provider for + * the specified source file. A shell is used to display messages in case of + * errors. + * + * @param sourceFile + * the source file + * @param shell + * the parent shell to use to display error messages + * @return the root file system object and it's associated import provider + */ + @SuppressWarnings("resource") + public static Pair getRootObjectAndProvider(File sourceFile, Shell shell) { + if (sourceFile == null) { + return null; + } + + IFileSystemObject rootElement = null; + FileSystemObjectImportStructureProvider importStructureProvider = null; + + // Import from directory + if (!isArchiveFile(sourceFile)) { + importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null); + rootElement = importStructureProvider.getIFileSystemObject(sourceFile); + } else { + // Import from archive + FileSystemObjectLeveledImportStructureProvider leveledImportStructureProvider = null; + String archivePath = sourceFile.getAbsolutePath(); + if (isTarFile(archivePath)) { + if (ensureTarSourceIsValid(archivePath, shell)) { + // We close the file when we dispose the import provider, + // see disposeSelectionGroupRoot + TarFile tarFile = getSpecifiedTarSourceFile(archivePath); + leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new TarLeveledStructureProvider(tarFile), archivePath); + } + } else if (ensureZipSourceIsValid(archivePath, shell)) { + // We close the file when we dispose the import provider, see + // disposeSelectionGroupRoot + ZipFile zipFile = getSpecifiedZipSourceFile(archivePath); + leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new ZipLeveledStructureProvider(zipFile), archivePath); + } else if (ensureGzipSourceIsValid(archivePath)) { + // We close the file when we dispose the import provider, see + // disposeSelectionGroupRoot + GzipFile zipFile = null; + try { + zipFile = new GzipFile(archivePath); + leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new GzipLeveledStructureProvider(zipFile), archivePath); + } catch (IOException e) { + // do nothing + } + } + if (leveledImportStructureProvider == null) { + return null; + } + rootElement = leveledImportStructureProvider.getRoot(); + importStructureProvider = leveledImportStructureProvider; + } + + if (rootElement == null) { + return null; + } + + return new Pair<>(rootElement, importStructureProvider); + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileFileSystemObject.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileFileSystemObject.java new file mode 100644 index 0000000000..edf35a5763 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileFileSystemObject.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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.IOException; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.tracecompass.tmf.core.TmfCommonConstants; + +/** + * The "File" implementation of an IFileSystemObject + */ +class FileFileSystemObject implements IFileSystemObject { + + private File fFileSystemObject; + + FileFileSystemObject(File fileSystemObject) { + fFileSystemObject = fileSystemObject; + } + + @Override + public String getName() { + String name = fFileSystemObject.getName(); + if (name.length() == 0) { + return fFileSystemObject.getPath(); + } + return name; + } + + @Override + public String getAbsolutePath() { + return fFileSystemObject.getAbsolutePath(); + } + + @Override + public boolean exists() { + return fFileSystemObject.exists(); + } + + @Override + public String getSourceLocation() { + IResource sourceResource; + String sourceLocation = null; + if (fFileSystemObject.isDirectory()) { + sourceResource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(Path.fromOSString(fFileSystemObject.getAbsolutePath())); + } else { + sourceResource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(fFileSystemObject.getAbsolutePath())); + } + if (sourceResource != null && sourceResource.exists()) { + try { + sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION); + } catch (CoreException e) { + // Something went wrong with the already existing resource. + // This is not a problem, we'll assign a new location below. + } + } + if (sourceLocation == null) { + try { + sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.getCanonicalFile().toURI()); + } catch (IOException e) { + // Something went wrong canonicalizing the file. We can still + // use the URI but there might be extra ../ in it. + sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.toURI()); + } + } + return sourceLocation; + } + + @Override + public Object getRawFileSystemObject() { + return fFileSystemObject; + } +} \ 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/FileSystemObjectImportStructureProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectImportStructureProvider.java new file mode 100644 index 0000000000..73498c78c7 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectImportStructureProvider.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2015 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc-Andre Laperle - Initial API and implementation + *******************************************************************************/ + +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.List; +import java.util.zip.ZipEntry; + +import org.eclipse.ui.internal.wizards.datatransfer.TarEntry; +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) + */ +@SuppressWarnings("restriction") +public class FileSystemObjectImportStructureProvider implements IImportStructureProvider { + + private IImportStructureProvider fImportProvider; + private String fArchivePath; + + FileSystemObjectImportStructureProvider(IImportStructureProvider importStructureProvider, String archivePath) { + fImportProvider = importStructureProvider; + fArchivePath = archivePath; + } + + @Override + public List getChildren(Object element) { + @SuppressWarnings("rawtypes") + List children = fImportProvider.getChildren(((IFileSystemObject) element).getRawFileSystemObject()); + List adapted = new ArrayList<>(children.size()); + for (Object o : children) { + adapted.add(getIFileSystemObject(o)); + } + return adapted; + } + + /** + * Get the IFileSystemObject corresponding to the specified raw object + * + * @param o + * the raw object + * @return the corresponding IFileSystemObject + */ + public IFileSystemObject getIFileSystemObject(Object o) { + if (o == null) { + return null; + } + + if (o instanceof File) { + return new FileFileSystemObject((File) o); + } else if (o instanceof TarEntry) { + return new TarFileSystemObject((TarEntry) o, fArchivePath); + } else if (o instanceof ZipEntry) { + return new ZipFileSystemObject((ZipEntry) o, fArchivePath); + } else if (o instanceof GzipEntry) { + return new GzipFileSystemObject((GzipEntry) o, fArchivePath); + } + + throw new IllegalArgumentException("Object type not handled"); //$NON-NLS-1$ + } + + @Override + public InputStream getContents(Object fileSystemObject) { + return fImportProvider.getContents(((IFileSystemObject) fileSystemObject).getRawFileSystemObject()); + } + + @Override + public String getFullPath(Object element) { + return fImportProvider.getFullPath(((IFileSystemObject) element).getRawFileSystemObject()); + } + + @Override + public String getLabel(Object element) { + return fImportProvider.getLabel(((IFileSystemObject) element).getRawFileSystemObject()); + } + + @Override + public boolean isFolder(Object element) { + return fImportProvider.isFolder(((IFileSystemObject) element).getRawFileSystemObject()); + } + + /** + * Disposes of the resources associated with the provider. + */ + public void dispose() { + } +} \ 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/FileSystemObjectLeveledImportStructureProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectLeveledImportStructureProvider.java new file mode 100644 index 0000000000..9bbaffdc0e --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/FileSystemObjectLeveledImportStructureProvider.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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 org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider; + +/** + * An import provider that both supports using IFileSystemObject and adds + * "archive functionality" by delegating to a leveled import provider + * (TarLeveledStructureProvider, ZipLeveledStructureProvider) + */ +@SuppressWarnings("restriction") +class FileSystemObjectLeveledImportStructureProvider extends FileSystemObjectImportStructureProvider implements ILeveledImportStructureProvider { + + private ILeveledImportStructureProvider fLeveledImportProvider; + + FileSystemObjectLeveledImportStructureProvider(ILeveledImportStructureProvider importStructureProvider, String archivePath) { + super(importStructureProvider, archivePath); + fLeveledImportProvider = importStructureProvider; + } + + @Override + public IFileSystemObject getRoot() { + return getIFileSystemObject(fLeveledImportProvider.getRoot()); + } + + @Override + public void setStrip(int level) { + fLeveledImportProvider.setStrip(level); + } + + @Override + public int getStrip() { + return fLeveledImportProvider.getStrip(); + } + + @Override + public boolean closeArchive() { + return fLeveledImportProvider.closeArchive(); + } + + @Override + public void dispose() { + super.dispose(); + closeArchive(); + } +} \ 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/GzipFileSystemObject.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFileSystemObject.java new file mode 100644 index 0000000000..848d8003f3 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/GzipFileSystemObject.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * 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.IOException; +import java.net.URI; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.URIUtil; + +/** + * The "GZIP" implementation of an IFileSystemObject. For a GZIP file that is + * not in a tar. + */ +class GzipFileSystemObject implements IFileSystemObject { + + private GzipEntry fFileSystemObject; + private String fArchivePath; + + GzipFileSystemObject(GzipEntry fileSystemObject, String archivePath) { + fFileSystemObject = fileSystemObject; + fArchivePath = archivePath; + } + + @Override + public String getName() { + return new Path(fFileSystemObject.getName()).lastSegment(); + } + + @Override + public String getAbsolutePath() { + throw new UnsupportedOperationException(); + } + + @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; + } +} \ 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/IFileSystemObject.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/IFileSystemObject.java new file mode 100644 index 0000000000..0bf69441d1 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/IFileSystemObject.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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; + +/** + * This interface abstracts the differences between different kinds of + * FileSystemObjects such as File, TarEntry, ZipEntry, etc. This allows clients + * (TraceFileSystemElement, TraceValidateAndImportOperation) to handle all the + * types transparently. + */ +public interface IFileSystemObject { + + /** + * Get the name of the file system object (last segment). + * + * @return the name of the file system object. + */ + String getName(); + + /** + * Get the absolute path of the file system object. + * + * @return the absolute path of the file system object + */ + String getAbsolutePath(); + + /** + * Get the source location for this file system object. + * + * @return the source location + */ + String getSourceLocation(); + + /** + * Returns the raw object wrapped by this IFileSystemObject (File, TarEntry, etc). + * + * @return the raw object wrapped by this IFileSystemObject + */ + Object getRawFileSystemObject(); + + /** + * Returns whether or not the file system object exists. + * + * @return whether or not the file system object exists + */ + boolean exists(); +} \ 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/ImportTraceWizardPage.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java index a6618fba06..248ea78148 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ImportTraceWizardPage.java @@ -22,27 +22,14 @@ package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace; import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.lang.reflect.InvocationTargetException; -import java.net.URI; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -53,12 +40,9 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.SubProgressMonitor; -import org.eclipse.core.runtime.URIUtil; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.layout.PixelConverter; import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.operation.ModalContext; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IStructuredSelection; @@ -86,36 +70,20 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.tracecompass.internal.tmf.ui.Activator; import org.eclipse.tracecompass.tmf.core.TmfCommonConstants; import org.eclipse.tracecompass.tmf.core.TmfProjectNature; -import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException; import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType; -import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper; import org.eclipse.tracecompass.tmf.core.util.Pair; import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement; import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry; import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder; -import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils; import org.eclipse.tracecompass.tmf.ui.project.model.TmfTracesFolder; -import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils; import org.eclipse.ui.dialogs.FileSystemElement; -import org.eclipse.ui.dialogs.IOverwriteQuery; import org.eclipse.ui.dialogs.WizardResourceImportPage; +import org.eclipse.ui.ide.dialogs.IElementFilter; import org.eclipse.ui.ide.dialogs.ResourceTreeAndListGroup; import org.eclipse.ui.internal.ide.DialogUtil; -import org.eclipse.ui.internal.ide.dialogs.IElementFilter; -import org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileManipulations; -import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider; -import org.eclipse.ui.internal.wizards.datatransfer.TarEntry; -import org.eclipse.ui.internal.wizards.datatransfer.TarException; -import org.eclipse.ui.internal.wizards.datatransfer.TarFile; -import org.eclipse.ui.internal.wizards.datatransfer.TarLeveledStructureProvider; -import org.eclipse.ui.internal.wizards.datatransfer.ZipLeveledStructureProvider; -import org.eclipse.ui.model.AdaptableList; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.model.WorkbenchViewerComparator; -import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; -import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider; -import org.eclipse.ui.wizards.datatransfer.ImportOperation; /** * A variant of the standard resource import wizard for importing traces to @@ -148,7 +116,6 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { // constant from WizardArchiveFileResourceImportPage1 private static final String[] FILE_IMPORT_MASK = { "*.jar;*.zip;*.tar;*.tar.gz;*.tgz;*.gz", "*.*" }; //$NON-NLS-1$ //$NON-NLS-2$ - private static final String TRACE_IMPORT_TEMP_FOLDER = ".traceImport"; //$NON-NLS-1$ /** * A special trace type value to communicate that automatic trace type @@ -785,247 +752,13 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { } private TraceFileSystemElement getFileSystemTree() { - Pair rootObjectAndProvider = getRootObjectAndProvider(getSourceFile()); + Pair rootObjectAndProvider = ArchiveUtil.getRootObjectAndProvider(getSourceFile(), getContainer().getShell()); if (rootObjectAndProvider == null) { return null; } return selectFiles(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond()); } - @SuppressWarnings("resource") - private Pair getRootObjectAndProvider(File sourceFile) { - if (sourceFile == null) { - return null; - } - - IFileSystemObject rootElement = null; - FileSystemObjectImportStructureProvider importStructureProvider = null; - - // Import from directory - if (!isArchiveFile(sourceFile)) { - importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null); - rootElement = importStructureProvider.getIFileSystemObject(sourceFile); - } else { - // Import from archive - FileSystemObjectLeveledImportStructureProvider leveledImportStructureProvider = null; - String archivePath = sourceFile.getAbsolutePath(); - if (isTarFile(archivePath)) { - if (ensureTarSourceIsValid(archivePath)) { - // We close the file when we dispose the import provider, - // see disposeSelectionGroupRoot - TarFile tarFile = getSpecifiedTarSourceFile(archivePath); - leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new TarLeveledStructureProvider(tarFile), archivePath); - } - } else if (ensureZipSourceIsValid(archivePath)) { - // We close the file when we dispose the import provider, see - // disposeSelectionGroupRoot - ZipFile zipFile = getSpecifiedZipSourceFile(archivePath); - leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new ZipLeveledStructureProvider(zipFile), archivePath); - } else if (ensureGzipSourceIsValid(archivePath)) { - // We close the file when we dispose the import provider, see - // disposeSelectionGroupRoot - GzipFile zipFile = null; - try { - zipFile = new GzipFile(archivePath); - leveledImportStructureProvider = new FileSystemObjectLeveledImportStructureProvider(new GzipLeveledStructureProvider(zipFile), archivePath); - } catch (IOException e) { - // do nothing - } - } - if (leveledImportStructureProvider == null) { - return null; - } - rootElement = leveledImportStructureProvider.getRoot(); - importStructureProvider = leveledImportStructureProvider; - } - - if (rootElement == null) { - return null; - } - - return new Pair<>(rootElement, importStructureProvider); - } - - /** - * An import provider that makes use of the IFileSystemObject abstraction - * instead of using plain file system objects (File, TarEntry, ZipEntry, etc) - */ - private static class FileSystemObjectImportStructureProvider implements IImportStructureProvider { - - private IImportStructureProvider fImportProvider; - private String fArchivePath; - - private FileSystemObjectImportStructureProvider(IImportStructureProvider importStructureProvider, String archivePath) { - fImportProvider = importStructureProvider; - fArchivePath = archivePath; - } - - @Override - public List getChildren(Object element) { - @SuppressWarnings("rawtypes") - List children = fImportProvider.getChildren(((IFileSystemObject) element).getRawFileSystemObject()); - List adapted = new ArrayList<>(children.size()); - for (Object o : children) { - adapted.add(getIFileSystemObject(o)); - } - return adapted; - } - - public IFileSystemObject getIFileSystemObject(Object o) { - if (o == null) { - return null; - } - - if (o instanceof File) { - return new FileFileSystemObject((File) o); - } else if (o instanceof TarEntry) { - return new TarFileSystemObject((TarEntry) o, fArchivePath); - } else if (o instanceof ZipEntry) { - return new ZipFileSystemObject((ZipEntry) o, fArchivePath); - } else if (o instanceof GzipEntry) { - return new GzipFileSystemObject((GzipEntry) o, fArchivePath); - } - - throw new IllegalArgumentException("Object type not handled"); //$NON-NLS-1$ - } - - @Override - public InputStream getContents(Object element) { - return fImportProvider.getContents(((IFileSystemObject) element).getRawFileSystemObject()); - } - - @Override - public String getFullPath(Object element) { - return fImportProvider.getFullPath(((IFileSystemObject) element).getRawFileSystemObject()); - } - - @Override - public String getLabel(Object element) { - return fImportProvider.getLabel(((IFileSystemObject) element).getRawFileSystemObject()); - } - - @Override - public boolean isFolder(Object element) { - return fImportProvider.isFolder(((IFileSystemObject) element).getRawFileSystemObject()); - } - - /** - * Disposes of the resources associated with the provider. - */ - public void dispose() { - } - } - - /** - * An import provider that both supports using IFileSystemObject and adds - * "archive functionality" by delegating to a leveled import provider - * (TarLeveledStructureProvider, ZipLeveledStructureProvider) - */ - private static class FileSystemObjectLeveledImportStructureProvider extends FileSystemObjectImportStructureProvider implements ILeveledImportStructureProvider { - - private ILeveledImportStructureProvider fLeveledImportProvider; - - private FileSystemObjectLeveledImportStructureProvider(ILeveledImportStructureProvider importStructureProvider, String archivePath) { - super(importStructureProvider, archivePath); - fLeveledImportProvider = importStructureProvider; - } - - @Override - public IFileSystemObject getRoot() { - return getIFileSystemObject(fLeveledImportProvider.getRoot()); - } - - @Override - public void setStrip(int level) { - fLeveledImportProvider.setStrip(level); - } - - @Override - public int getStrip() { - return fLeveledImportProvider.getStrip(); - } - - @Override - public boolean closeArchive() { - return fLeveledImportProvider.closeArchive(); - } - - @Override - public void dispose() { - super.dispose(); - closeArchive(); - } - } - - @SuppressWarnings("resource") - private boolean ensureZipSourceIsValid(String archivePath) { - ZipFile specifiedFile = getSpecifiedZipSourceFile(archivePath); - if (specifiedFile == null) { - return false; - } - return ArchiveFileManipulations.closeZipFile(specifiedFile, getShell()); - } - - private boolean ensureTarSourceIsValid(String archivePath) { - TarFile specifiedFile = getSpecifiedTarSourceFile(archivePath); - if (specifiedFile == null) { - return false; - } - return ArchiveFileManipulations.closeTarFile(specifiedFile, getShell()); - } - - private static ZipFile getSpecifiedZipSourceFile(String fileName) { - if (fileName.length() == 0) { - return null; - } - - try { - return new ZipFile(fileName); - } catch (ZipException e) { - // ignore - } catch (IOException e) { - // ignore - } - - return null; - } - - private static boolean isTarFile(String fileName) { - TarFile specifiedTarSourceFile = getSpecifiedTarSourceFile(fileName); - if (specifiedTarSourceFile != null) { - try { - specifiedTarSourceFile.close(); - return true; - } catch (IOException e) { - // ignore - } - } - return false; - } - - private static TarFile getSpecifiedTarSourceFile(String fileName) { - if (fileName.length() == 0) { - return null; - } - - // FIXME: Work around Bug 463633. Remove this block once we move to Eclipse 4.5. - if (new File(fileName).length() < 512) { - return null; - } - - try { - return new TarFile(fileName); - } catch (TarException | IOException e) { - // ignore - } - - return null; - } - - private static boolean ensureGzipSourceIsValid(String archivePath) { - return isGzipFile(archivePath); - } - private TraceFileSystemElement selectFiles(final IFileSystemObject rootFileSystemObject, final FileSystemObjectImportStructureProvider structureProvider) { final TraceFileSystemElement[] results = new TraceFileSystemElement[1]; @@ -1033,37 +766,12 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { @Override public void run() { // Create the root element from the supplied file system object - results[0] = createRootTraceFileElement(rootFileSystemObject, structureProvider); + results[0] = TraceFileSystemElement.createRootTraceFileElement(rootFileSystemObject, structureProvider); } }); return results[0]; } - private static TraceFileSystemElement createRootTraceFileElement(IFileSystemObject element, - FileSystemObjectImportStructureProvider provider) { - boolean isContainer = provider.isFolder(element); - String elementLabel = provider.getLabel(element); - - // Use an empty label so that display of the element's full name - // doesn't include a confusing label - TraceFileSystemElement dummyParent = new TraceFileSystemElement("", null, true, provider);//$NON-NLS-1$ - Object dummyParentFileSystemObject = element; - Object rawFileSystemObject = element.getRawFileSystemObject(); - if (rawFileSystemObject instanceof File) { - dummyParentFileSystemObject = provider.getIFileSystemObject(((File) rawFileSystemObject).getParentFile()); - } - dummyParent.setFileSystemObject(dummyParentFileSystemObject); - dummyParent.setPopulated(); - TraceFileSystemElement result = new TraceFileSystemElement( - elementLabel, dummyParent, isContainer, provider); - result.setFileSystemObject(element); - - // Get the files for the element so as to build the first level - result.getFiles(); - - return dummyParent; - } - // ------------------------------------------------------------------------ // Trace Type Group // ------------------------------------------------------------------------ @@ -1164,7 +872,7 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { return false; } - if (!isImportFromDirectory() && !ensureTarSourceIsValid(source.getAbsolutePath()) && !ensureZipSourceIsValid(source.getAbsolutePath()) && !ensureGzipSourceIsValid(source.getAbsolutePath())) { + if (!isImportFromDirectory() && !ArchiveUtil.ensureTarSourceIsValid(source.getAbsolutePath(), getContainer().getShell()) && !ArchiveUtil.ensureZipSourceIsValid(source.getAbsolutePath(), getContainer().getShell()) && !ArchiveUtil.ensureGzipSourceIsValid(source.getAbsolutePath())) { setMessage(null); setErrorMessage(Messages.ImportTraceWizard_BadArchiveFormat); return false; @@ -1202,21 +910,6 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { return fImportFromDirectoryRadio != null && fImportFromDirectoryRadio.getSelection(); } - private static boolean isArchiveFile(File sourceFile) { - String absolutePath = sourceFile.getAbsolutePath(); - return isTarFile(absolutePath) || ArchiveFileManipulations.isZipFile(absolutePath) || isGzipFile(absolutePath); - } - - private static boolean isGzipFile(String fileName) { - if (!fileName.isEmpty()) { - try (GzipFile specifiedTarSourceFile = new GzipFile(fileName);) { - return true; - } catch (IOException e) { - } - } - return false; - } - @Override protected void restoreWidgetValues() { super.restoreWidgetValues(); @@ -1326,44 +1019,66 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { */ public boolean finish() { String traceTypeLabel = getImportTraceTypeId(); - String traceId = null; - if (!TRACE_TYPE_AUTO_DETECT.equals(traceTypeLabel)) { - traceId = TmfTraceType.getTraceTypeId(traceTypeLabel); - } + final String traceId = !TRACE_TYPE_AUTO_DETECT.equals(traceTypeLabel) ? TmfTraceType.getTraceTypeId(traceTypeLabel) : null; // Save dialog settings saveWidgetValues(); - IPath baseSourceContainerPath = new Path(getSourceContainerPath()); - boolean importFromArchive = getSourceArchiveFile() != null; - int importOptionFlags = getImportOptionFlags(); - - final TraceValidateAndImportOperation operation = new TraceValidateAndImportOperation(traceId, baseSourceContainerPath, getContainerFullPath(), importFromArchive, - importOptionFlags); + final IPath baseSourceContainerPath = new Path(getSourceContainerPath()); + final boolean importFromArchive = getSourceArchiveFile() != null; + final int importOptionFlags = getImportOptionFlags(); + final IPath destinationContainerPath = getContainerFullPath(); - IStatus status = Status.OK_STATUS; + final IStatus[] operationStatus = new IStatus[1]; + operationStatus[0] = Status.OK_STATUS; try { getContainer().run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + + final List selectedFileSystemElements = new LinkedList<>(); + IElementFilter passThroughFilter = new IElementFilter() { + + @Override + public void filterElements(Collection elements, IProgressMonitor m) { + selectedFileSystemElements.addAll(elements); + } + + @Override + public void filterElements(Object[] elements, IProgressMonitor m) { + for (int i = 0; i < elements.length; i++) { + selectedFileSystemElements.add((TraceFileSystemElement) elements[i]); + } + } + }; + + // List fileSystemElements will be filled using the + // passThroughFilter + SubMonitor subMonitor = SubMonitor.convert(monitor, 1); + fSelectionGroup.getAllCheckedListItems(passThroughFilter, subMonitor); + + final TraceValidateAndImportOperation operation = new TraceValidateAndImportOperation(getContainer().getShell(), selectedFileSystemElements, traceId, baseSourceContainerPath, destinationContainerPath, importFromArchive, + importOptionFlags, fTraceFolderElement); operation.run(monitor); monitor.done(); + operationStatus[0] = operation.getStatus(); } }); - status = operation.getStatus(); } catch (InvocationTargetException e) { - status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportTraceWizard_ImportProblem, e); + operationStatus[0] = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportTraceWizard_ImportProblem, e.getTargetException()); } catch (InterruptedException e) { - status = Status.CANCEL_STATUS; + operationStatus[0] = Status.CANCEL_STATUS; } - if (!status.isOK()) { - if (status.getSeverity() == IStatus.CANCEL) { + if (!operationStatus[0].isOK()) { + if (operationStatus[0].getSeverity() == IStatus.CANCEL) { setMessage(Messages.ImportTraceWizard_ImportOperationCancelled); setErrorMessage(null); } else { - if (status.getException() != null) { - displayErrorDialog(status.getMessage() + ": " + status.getException()); //$NON-NLS-1$ + Throwable exception = operationStatus[0].getException(); + if (exception != null) { + Activator.getDefault().logError(exception.getMessage(), exception); + displayErrorDialog(operationStatus[0].getMessage() + ": " + exception); //$NON-NLS-1$ } setMessage(null); setErrorMessage(Messages.ImportTraceWizard_ImportProblem); @@ -1417,956 +1132,4 @@ public class ImportTraceWizardPage extends WizardResourceImportPage { super.dispose(); disposeSelectionGroupRoot(); } - - // ------------------------------------------------------------------------ - // Classes - // ------------------------------------------------------------------------ - - private class TraceValidateAndImportOperation { - private IStatus fStatus; - private String fTraceType; - private IPath fDestinationContainerPath; - private IPath fBaseSourceContainerPath; - private boolean fImportFromArchive; - private int fImportOptionFlags; - private ImportConflictHandler fConflictHandler; - private String fCurrentPath; - - private TraceValidateAndImportOperation(String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean importFromArchive, int importOptionFlags) { - fTraceType = traceId; - fBaseSourceContainerPath = baseSourceContainerPath; - fDestinationContainerPath = destinationContainerPath; - fImportOptionFlags = importOptionFlags; - fImportFromArchive = importFromArchive; - - boolean overwriteExistingResources = (importOptionFlags & OPTION_OVERWRITE_EXISTING_RESOURCES) != 0; - if (overwriteExistingResources) { - fConflictHandler = new ImportConflictHandler(getContainer().getShell(), fTraceFolderElement, ImportConfirmation.OVERWRITE_ALL); - } else { - fConflictHandler = new ImportConflictHandler(getContainer().getShell(), fTraceFolderElement, ImportConfirmation.SKIP); - } - } - - public void run(IProgressMonitor progressMonitor) { - try { - - final List selectedFileSystemElements = new LinkedList<>(); - IElementFilter passThroughFilter = new IElementFilter() { - - @Override - public void filterElements(Collection elements, IProgressMonitor monitor) { - selectedFileSystemElements.addAll(elements); - } - - @Override - public void filterElements(Object[] elements, IProgressMonitor monitor) { - for (int i = 0; i < elements.length; i++) { - selectedFileSystemElements.add((TraceFileSystemElement) elements[i]); - } - } - }; - - // List fileSystemElements will be filled using the - // passThroughFilter - SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 1); - fSelectionGroup.getAllCheckedListItems(passThroughFilter, subMonitor); - - // Check if operation was cancelled. - ModalContext.checkCanceled(subMonitor); - - // Temporary directory to contain any extracted files - IFolder destTempFolder = fTargetFolder.getProject().getFolder(TRACE_IMPORT_TEMP_FOLDER); - if (destTempFolder.exists()) { - SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); - destTempFolder.delete(true, monitor); - } - SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); - destTempFolder.create(IResource.HIDDEN, true, monitor); - - subMonitor = SubMonitor.convert(progressMonitor, 2); - String baseSourceLocation = null; - 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)); - - if (!selectedFileSystemElements.isEmpty()) { - // 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 tempFolderFileSystemElements = createElementsForFolder(destTempFolder); - extractAllArchiveFiles(tempFolderFileSystemElements, destTempFolder, destTempFolder.getLocation(), archiveMonitor.newChild(1)); - } - } else { - SubMonitor directoryMonitor = SubMonitor.convert(subMonitor.newChild(1), 2); - // Import selected files, excluding archives (done in a later step) - importFileSystemElements(directoryMonitor.newChild(1), selectedFileSystemElements); - - // Extract archives in selected files (if any) to temporary folder - extractAllArchiveFiles(selectedFileSystemElements, destTempFolder, fBaseSourceContainerPath, directoryMonitor.newChild(1)); - // Even if the files were extracted to temporary folder, they have to look like they originate from the source folder - baseSourceLocation = URIUtil.toUnencodedString(fBaseSourceContainerPath.toFile().getCanonicalFile().toURI()); - } - - /* Import extracted files that are now in the temporary folder, if any */ - - // We need to update the source container path because the - // "preserve folder structure" option would create the - // wrong trace folders otherwise. - fBaseSourceContainerPath = destTempFolder.getLocation(); - List tempFolderFileSystemElements = createElementsForFolder(destTempFolder); - if (!tempFolderFileSystemElements.isEmpty()) { - calculateSourceLocations(tempFolderFileSystemElements, baseSourceLocation); - // Never import extracted files as links, they would link to the - // temporary directory that will be deleted - fImportOptionFlags = fImportOptionFlags & ~OPTION_CREATE_LINKS_IN_WORKSPACE; - SubMonitor importTempMonitor = subMonitor.newChild(1); - importFileSystemElements(importTempMonitor, tempFolderFileSystemElements); - } - if (destTempFolder.exists()) { - destTempFolder.delete(true, progressMonitor); - } - - setStatus(Status.OK_STATUS); - } catch (InterruptedException e) { - setStatus(Status.CANCEL_STATUS); - } catch (Exception e) { - String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$ - (fCurrentPath != null ? fCurrentPath : ""); //$NON-NLS-1$ - Activator.getDefault().logError(errorMessage, e); - setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage, e)); - } - } - - /** - * Import a collection of file system elements into the workspace. - */ - private void importFileSystemElements(IProgressMonitor monitor, List fileSystemElements) - throws InterruptedException, TmfTraceImportException, CoreException, InvocationTargetException { - SubMonitor subMonitor = SubMonitor.convert(monitor, fileSystemElements.size()); - - ListIterator fileSystemElementsIter = fileSystemElements.listIterator(); - - // Map to remember already imported directory traces - final Map 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 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 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 fileSystemElements, IFolder destFolder, IPath baseSourceContainerPath, IProgressMonitor progressMonitor) throws InterruptedException, CoreException, InvocationTargetException { - SubMonitor subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size()); - ListIterator 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 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 rootObjectAndProvider = getRootObjectAndProvider(sourceFile); - TraceFileSystemElement rootElement = createRootTraceFileElement(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond()); - List 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 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 fileSystemElementsIter, IFolder tempFolder, IProgressMonitor progressMonitor) throws InterruptedException, - InvocationTargetException { - List subList = new ArrayList<>(); - // Collect all the elements - while (fileSystemElementsIter.hasNext()) { - ModalContext.checkCanceled(progressMonitor); - TraceFileSystemElement element = fileSystemElementsIter.next(); - if (element.isDirectory()) { - Object[] array = element.getFiles().getChildren(); - for (int i = 0; i < array.length; i++) { - subList.add((TraceFileSystemElement) array[i]); - } - } - subList.add(element); - } - - if (subList.isEmpty()) { - return; - } - - TraceFileSystemElement root = getRootElement(subList.get(0)); - - ImportProvider fileSystemStructureProvider = new ImportProvider(); - - IOverwriteQuery myQueryImpl = new IOverwriteQuery() { - @Override - public String queryOverwrite(String file) { - return IOverwriteQuery.NO_ALL; - } - }; - - progressMonitor.setTaskName(Messages.ImportTraceWizard_ExtractImportOperationTaskName); - IPath containerPath = tempFolder.getFullPath(); - ImportOperation operation = new ImportOperation(containerPath, root, fileSystemStructureProvider, myQueryImpl, subList); - operation.setContext(getShell()); - - operation.setCreateContainerStructure(true); - operation.setOverwriteResources(false); - operation.setVirtualFolders(false); - - operation.run(new SubProgressMonitor(progressMonitor, subList.size(), SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); - } - - private TraceFileSystemElement getRootElement(TraceFileSystemElement element) { - TraceFileSystemElement root = element; - while (root.getParent() != null) { - root = (TraceFileSystemElement) root.getParent(); - } - return root; - } - - /** - * Get all the TraceFileSystemElements recursively. - * - * @param result - * the list accumulating the result - * @param rootElement - * the root element of the file system to be imported - */ - private void getAllChildren(List result, TraceFileSystemElement rootElement) { - AdaptableList files = rootElement.getFiles(); - for (Object file : files.getChildren()) { - result.add((TraceFileSystemElement) file); - } - - AdaptableList folders = rootElement.getFolders(); - for (Object folder : folders.getChildren()) { - getAllChildren(result, (TraceFileSystemElement) folder); - } - } - - private IPath computeDestinationContainerPath(Path resourcePath) { - IPath destinationContainerPath = fDestinationContainerPath; - - // We need to figure out the new destination path relative to the - // selected "base" source directory. - // Here for example, the selected source directory is /home/user - if ((fImportOptionFlags & OPTION_PRESERVE_FOLDER_STRUCTURE) != 0) { - // /home/user/bar/foo/trace -> /home/user/bar/foo - IPath sourceContainerPath = resourcePath.removeLastSegments(1); - if (fBaseSourceContainerPath.equals(resourcePath)) { - // Use resourcePath directory if fBaseSourceContainerPath - // points to a directory trace - sourceContainerPath = resourcePath; - } - // /home/user/bar/foo, /home/user -> bar/foo - IPath relativeContainerPath = sourceContainerPath.makeRelativeTo(fBaseSourceContainerPath); - // project/Traces + bar/foo -> project/Traces/bar/foo - destinationContainerPath = fDestinationContainerPath.append(relativeContainerPath); - } - return destinationContainerPath; - } - - /** - * Import a single file system element into the workspace. - */ - private void validateAndImportTrace(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) - throws TmfTraceImportException, CoreException, InvocationTargetException, InterruptedException { - String parentContainerPath = fBaseSourceContainerPath.toOSString(); - String path = fileSystemElement.getFileSystemObject().getAbsolutePath(parentContainerPath); - TraceTypeHelper traceTypeHelper = null; - - File file = (File) fileSystemElement.getFileSystemObject().getRawFileSystemObject(); - boolean isArchiveFileElement = fileSystemElement.getFileSystemObject() instanceof FileFileSystemObject && isArchiveFile(file); - if (isArchiveFileElement) { - // We'll be extracting this later, do not import as a trace - return; - } - - if (fTraceType == null) { - // Auto Detection - try { - traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(path, null, null); - } catch (TmfTraceImportException e) { - // the trace did not match any trace type - } - if (traceTypeHelper == null) { - if ((fImportOptionFlags & OPTION_IMPORT_UNRECOGNIZED_TRACES) != 0) { - importResource(fileSystemElement, monitor); - } - return; - } - } else { - boolean isDirectoryTraceType = TmfTraceType.isDirectoryTraceType(fTraceType); - if (fileSystemElement.isDirectory() != isDirectoryTraceType) { - return; - } - traceTypeHelper = TmfTraceType.getTraceType(fTraceType); - - if (traceTypeHelper == null) { - // Trace type not found - throw new TmfTraceImportException(Messages.ImportTraceWizard_TraceTypeNotFound); - } - - if (!traceTypeHelper.validate(path).isOK()) { - // Trace type exist but doesn't validate for given trace. - return; - } - } - - // Finally import trace - IResource importedResource = importResource(fileSystemElement, monitor); - if (importedResource != null) { - TmfTraceTypeUIUtils.setTraceType(importedResource, traceTypeHelper); - } - - } - - /** - * Imports a trace resource to project. In case of name collision the - * user will be asked to confirm overwriting the existing trace, - * overwriting or skipping the trace to be imported. - * - * @param fileSystemElement - * trace file system object to import - * @param monitor - * a progress monitor - * @return the imported resource or null if no resource was imported - * - * @throws InvocationTargetException - * if problems during import operation - * @throws InterruptedException - * if cancelled - * @throws CoreException - * if problems with workspace - */ - private IResource importResource(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) - throws InvocationTargetException, InterruptedException, CoreException { - - IPath tracePath = getInitialDestinationPath(fileSystemElement); - String newName = fConflictHandler.checkAndHandleNameClash(tracePath, monitor); - if (newName == null) { - return null; - } - fileSystemElement.setLabel(newName); - - List subList = new ArrayList<>(); - - FileSystemElement parentFolder = fileSystemElement.getParent(); - - IPath containerPath = fileSystemElement.getDestinationContainerPath(); - tracePath = containerPath.addTrailingSeparator().append(fileSystemElement.getLabel()); - boolean createLinksInWorkspace = (fImportOptionFlags & OPTION_CREATE_LINKS_IN_WORKSPACE) != 0; - if (fileSystemElement.isDirectory() && !createLinksInWorkspace) { - containerPath = tracePath; - - Object[] array = fileSystemElement.getFiles().getChildren(); - for (int i = 0; i < array.length; i++) { - subList.add((TraceFileSystemElement) array[i]); - } - parentFolder = fileSystemElement; - - } else { - subList.add(fileSystemElement); - } - - ImportProvider fileSystemStructureProvider = new ImportProvider(); - - IOverwriteQuery myQueryImpl = new IOverwriteQuery() { - @Override - public String queryOverwrite(String file) { - return IOverwriteQuery.NO_ALL; - } - }; - - monitor.setTaskName(Messages.ImportTraceWizard_ImportOperationTaskName + " " + fileSystemElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString())); //$NON-NLS-1$ - ImportOperation operation = new ImportOperation(containerPath, parentFolder, fileSystemStructureProvider, myQueryImpl, subList); - operation.setContext(getShell()); - - operation.setCreateContainerStructure(false); - operation.setOverwriteResources(false); - operation.setCreateLinks(createLinksInWorkspace); - operation.setVirtualFolders(false); - - operation.run(new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); - String sourceLocation = fileSystemElement.getSourceLocation(); - IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(tracePath); - if (sourceLocation != null) { - resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation); - } - - return resource; - } - - private boolean isDirectoryTrace(TraceFileSystemElement fileSystemElement) { - String path = fileSystemElement.getFileSystemObject().getAbsolutePath(fBaseSourceContainerPath.toOSString()); - if (TmfTraceType.isDirectoryTrace(path)) { - return true; - } - return false; - } - - /** - * @return the initial destination path, before rename, if any - */ - private IPath getInitialDestinationPath(TraceFileSystemElement fileSystemElement) { - IPath traceFolderPath = fileSystemElement.getDestinationContainerPath(); - return traceFolderPath.append(fileSystemElement.getFileSystemObject().getLabel()); - } - - /** - * Set the status for this operation - * - * @param status - * the status - */ - protected void setStatus(IStatus status) { - fStatus = status; - } - - public IStatus getStatus() { - return fStatus; - } - } - - /** - * The TraceFileSystemElement is a - * FileSystemElement that knows if it has been populated or - * not. - */ - private static class TraceFileSystemElement extends FileSystemElement { - - private boolean fIsPopulated = false; - private String fLabel = null; - private IPath fDestinationContainerPath; - private FileSystemObjectImportStructureProvider fProvider; - private String fSourceLocation; - - public TraceFileSystemElement(String name, FileSystemElement parent, boolean isDirectory, FileSystemObjectImportStructureProvider provider) { - super(name, parent, isDirectory); - fProvider = provider; - } - - public void setDestinationContainerPath(IPath destinationContainerPath) { - fDestinationContainerPath = destinationContainerPath; - } - - public void setPopulated() { - fIsPopulated = true; - } - - public boolean isPopulated() { - return fIsPopulated; - } - - @Override - public AdaptableList getFiles() { - if (!fIsPopulated) { - populateElementChildren(); - } - return super.getFiles(); - } - - @Override - public AdaptableList getFolders() { - if (!fIsPopulated) { - populateElementChildren(); - } - return super.getFolders(); - } - - /** - * Sets the label for the trace to be used when importing at trace. - * - * @param name - * the label for the trace - */ - public void setLabel(String name) { - fLabel = name; - } - - /** - * Returns the label for the trace to be used when importing at trace. - * - * @return the label of trace resource - */ - public String getLabel() { - if (fLabel == null) { - return getFileSystemObject().getLabel(); - } - return fLabel; - } - - /** - * The full path to the container that will contain the trace - * - * @return the destination container path - */ - public IPath getDestinationContainerPath() { - return fDestinationContainerPath; - } - - /** - * Populates the children of the specified parent - * FileSystemElement - */ - private void populateElementChildren() { - List allchildren = fProvider.getChildren(this.getFileSystemObject()); - Object child = null; - TraceFileSystemElement newelement = null; - Iterator iter = allchildren.iterator(); - while (iter.hasNext()) { - child = iter.next(); - newelement = new TraceFileSystemElement(fProvider.getLabel(child), this, fProvider.isFolder(child), fProvider); - newelement.setFileSystemObject(child); - } - setPopulated(); - } - - public FileSystemObjectImportStructureProvider getProvider() { - return fProvider; - } - - @Override - public IFileSystemObject getFileSystemObject() { - Object fileSystemObject = super.getFileSystemObject(); - return (IFileSystemObject) fileSystemObject; - } - - public String getSourceLocation() { - if (fSourceLocation == null) { - fSourceLocation = getFileSystemObject().getSourceLocation(); - } - return fSourceLocation; - } - - public void setSourceLocation(String sourceLocation) { - fSourceLocation = sourceLocation; - } - } - - /** - * This interface abstracts the differences between different kinds of - * FileSystemObjects such as File, TarEntry, ZipEntry, etc. This allows - * clients (TraceFileSystemElement, TraceValidateAndImportOperation) to - * handle all the types transparently. - */ - private interface IFileSystemObject { - String getLabel(); - - String getName(); - - String getAbsolutePath(String parentContainerPath); - - String getSourceLocation(); - - Object getRawFileSystemObject(); - - boolean exists(); - } - - /** - * The "File" implementation of an IFileSystemObject - */ - private static class FileFileSystemObject implements IFileSystemObject { - - private File fFileSystemObject; - - private FileFileSystemObject(File fileSystemObject) { - fFileSystemObject = fileSystemObject; - } - - @Override - public String getLabel() { - String name = fFileSystemObject.getName(); - if (name.length() == 0) { - return fFileSystemObject.getPath(); - } - return name; - } - - @Override - public String getName() { - return fFileSystemObject.getName(); - } - - @Override - public String getAbsolutePath(String parentContainerPath) { - return fFileSystemObject.getAbsolutePath(); - } - - @Override - public boolean exists() { - return fFileSystemObject.exists(); - } - - @Override - public String getSourceLocation() { - IResource sourceResource; - String sourceLocation = null; - if (fFileSystemObject.isDirectory()) { - sourceResource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(Path.fromOSString(fFileSystemObject.getAbsolutePath())); - } else { - sourceResource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(fFileSystemObject.getAbsolutePath())); - } - if (sourceResource != null && sourceResource.exists()) { - try { - sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION); - } catch (CoreException e) { - // Something went wrong with the already existing resource. - // This is not a problem, we'll assign a new location below. - } - } - if (sourceLocation == null) { - try { - sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.getCanonicalFile().toURI()); - } catch (IOException e) { - // Something went wrong canonicalizing the file. We can still use the URI but there might be extra ../ in it. - sourceLocation = URIUtil.toUnencodedString(fFileSystemObject.toURI()); - } - } - return sourceLocation; - } - - @Override - public Object getRawFileSystemObject() { - return fFileSystemObject; - } - } - - /** - * The "Tar" implementation of an IFileSystemObject, entries can also be Gzipped and are uncompressed transparently. - */ - private static class TarFileSystemObject implements IFileSystemObject { - - private TarEntry fFileSystemObject; - private String fArchivePath; - - private TarFileSystemObject(TarEntry fileSystemObject, String archivePath) { - fFileSystemObject = fileSystemObject; - fArchivePath = archivePath; - } - - @Override - public String getLabel() { - return new Path(fFileSystemObject.getName()).lastSegment(); - } - - @Override - public String getName() { - return fFileSystemObject.getName(); - } - - @Override - public String getAbsolutePath(String parentContainerPath) { - return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString(); - } - - @Override - public boolean exists() { - return true; - } - - @Override - public String getSourceLocation() { - File file = new File(fArchivePath); - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - // Will still work but might have extra ../ in the path - } - URI uri = file.toURI(); - IPath entryPath = new Path(fFileSystemObject.getName()); - - URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath); - return URIUtil.toUnencodedString(jarURI); - } - - @Override - public Object getRawFileSystemObject() { - return fFileSystemObject; - } - } - - /** - * The "GZIP" implementation of an IFileSystemObject. For a GZIP file that is not in a tar. - */ - private static class GzipFileSystemObject implements IFileSystemObject { - - private GzipEntry fFileSystemObject; - private String fArchivePath; - - private GzipFileSystemObject(GzipEntry fileSystemObject, String archivePath) { - fFileSystemObject = fileSystemObject; - fArchivePath = archivePath; - } - - @Override - public String getLabel() { - return new Path(fFileSystemObject.getName()).lastSegment(); - } - - @Override - public String getName() { - return fFileSystemObject.getName(); - } - - @Override - public String getAbsolutePath(String parentContainerPath) { - return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString(); - } - - @Override - public boolean exists() { - return true; - } - - @Override - public String getSourceLocation() { - File file = new File(fArchivePath); - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - // Will still work but might have extra ../ in the path - } - URI uri = file.toURI(); - IPath entryPath = new Path(fFileSystemObject.getName()); - - URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath); - return URIUtil.toUnencodedString(jarURI); - } - - @Override - public Object getRawFileSystemObject() { - return fFileSystemObject; - } - } - - /** - * The "Zip" implementation of an IFileSystemObject - */ - private static class ZipFileSystemObject implements IFileSystemObject { - - private ZipEntry fFileSystemObject; - private String fArchivePath; - - private ZipFileSystemObject(ZipEntry fileSystemObject, String archivePath) { - fFileSystemObject = fileSystemObject; - fArchivePath = archivePath; - } - - @Override - public String getLabel() { - return new Path(fFileSystemObject.getName()).lastSegment(); - } - - @Override - public String getName() { - return fFileSystemObject.getName(); - } - - @Override - public String getAbsolutePath(String parentContainerPath) { - return new Path(parentContainerPath).append(fFileSystemObject.getName()).toOSString(); - } - - @Override - public boolean exists() { - return true; - } - - @Override - public String getSourceLocation() { - File file = new File(fArchivePath); - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - // Will still work but might have extra ../ in the path - } - URI uri = file.toURI(); - IPath entryPath = new Path(fFileSystemObject.getName()); - - URI jarURI = entryPath.isRoot() ? URIUtil.toJarURI(uri, Path.EMPTY) : URIUtil.toJarURI(uri, entryPath); - return URIUtil.toUnencodedString(jarURI); - } - - @Override - public Object getRawFileSystemObject() { - return fFileSystemObject; - } - } - - private class ImportProvider implements IImportStructureProvider { - - ImportProvider() { - } - - @Override - public String getLabel(Object element) { - TraceFileSystemElement resource = (TraceFileSystemElement) element; - return resource.getLabel(); - } - - @Override - public List getChildren(Object element) { - TraceFileSystemElement resource = (TraceFileSystemElement) element; - Object[] array = resource.getFiles().getChildren(); - List list = new ArrayList<>(); - for (int i = 0; i < array.length; i++) { - list.add(array[i]); - } - return list; - } - - @Override - public InputStream getContents(Object element) { - TraceFileSystemElement resource = (TraceFileSystemElement) element; - return resource.getProvider().getContents(resource.getFileSystemObject()); - } - - @Override - public String getFullPath(Object element) { - TraceFileSystemElement resource = (TraceFileSystemElement) element; - return resource.getProvider().getFullPath(resource.getFileSystemObject()); - } - - @Override - public boolean isFolder(Object element) { - TraceFileSystemElement resource = (TraceFileSystemElement) element; - return resource.isDirectory(); - } - } } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarFileSystemObject.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarFileSystemObject.java new file mode 100644 index 0000000000..8865ac49bb --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TarFileSystemObject.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.IOException; +import java.net.URI; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.ui.internal.wizards.datatransfer.TarEntry; + +/** + * The "Tar" implementation of an IFileSystemObject, entries can also be Gzipped + * and are uncompressed transparently. + */ +@SuppressWarnings("restriction") +class TarFileSystemObject implements IFileSystemObject { + + private TarEntry fFileSystemObject; + private String fArchivePath; + + TarFileSystemObject(TarEntry fileSystemObject, String archivePath) { + fFileSystemObject = fileSystemObject; + fArchivePath = archivePath; + } + + @Override + public String getName() { + return new Path(fFileSystemObject.getName()).lastSegment(); + } + + @Override + public String getAbsolutePath() { + throw new UnsupportedOperationException(); + } + + @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; + } +} \ 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/TraceFileSystemElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceFileSystemElement.java new file mode 100644 index 0000000000..294288314b --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceFileSystemElement.java @@ -0,0 +1,231 @@ +/******************************************************************************* + * 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.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.ui.dialogs.FileSystemElement; +import org.eclipse.ui.model.AdaptableList; + +/** + * The TraceFileSystemElement is a FileSystemElement + * that knows if it has been populated or not. + */ +public class TraceFileSystemElement extends FileSystemElement { + + private boolean fIsPopulated = false; + private String fLabel = null; + private IPath fDestinationContainerPath; + private FileSystemObjectImportStructureProvider fProvider; + private String fSourceLocation; + + /** + * Constructs a new TraceFileSystemElement + * + * @param name the name of the element + * @param parent the parent element + * @param isDirectory whether or not this element is a directory + * @param provider the provider associated with this element + */ + public TraceFileSystemElement(String name, FileSystemElement parent, boolean isDirectory, FileSystemObjectImportStructureProvider provider) { + super(name, parent, isDirectory); + fProvider = provider; + } + + /** + * Set the path for the container that will contain the trace once imported. + * + * @param destinationContainerPath the destination container path + */ + public void setDestinationContainerPath(IPath destinationContainerPath) { + fDestinationContainerPath = destinationContainerPath; + } + + /** + * Mark this element as populated. + */ + public void setPopulated() { + fIsPopulated = true; + } + + /** + * Returns whether or not the children of the element have been populated. + * + * @return whether or not the children of the element have been populated. + */ + public boolean isPopulated() { + return fIsPopulated; + } + + @Override + public AdaptableList getFiles() { + if (!fIsPopulated) { + populateElementChildren(); + } + return super.getFiles(); + } + + @Override + public AdaptableList getFolders() { + if (!fIsPopulated) { + populateElementChildren(); + } + return super.getFolders(); + } + + /** + * Sets the label for the trace to be used when importing at trace. + * + * @param name + * the label for the trace + */ + public void setLabel(String name) { + fLabel = name; + } + + /** + * Returns the label for the trace to be used when importing at trace. + * + * @return the label of trace resource + */ + public String getLabel() { + if (fLabel == null) { + return getFileSystemObject().getName(); + } + return fLabel; + } + + /** + * The full path to the container that will contain the trace once imported. + * + * @return the destination container path + */ + public IPath getDestinationContainerPath() { + return fDestinationContainerPath; + } + + /** + * Populates the children of the specified parent + * FileSystemElement + */ + private void populateElementChildren() { + List allchildren = fProvider.getChildren(this.getFileSystemObject()); + Object child = null; + TraceFileSystemElement newelement = null; + Iterator iter = allchildren.iterator(); + while (iter.hasNext()) { + child = iter.next(); + newelement = new TraceFileSystemElement(fProvider.getLabel(child), this, fProvider.isFolder(child), fProvider); + newelement.setFileSystemObject(child); + } + setPopulated(); + } + + /** + * Get the import provider associated with this element. + * + * @return the import provider. + */ + public FileSystemObjectImportStructureProvider getProvider() { + return fProvider; + } + + @Override + public IFileSystemObject getFileSystemObject() { + return (IFileSystemObject) super.getFileSystemObject(); + } + + /** + * Get the source location for this element. + * + * @return the source location + */ + public String getSourceLocation() { + if (fSourceLocation == null) { + fSourceLocation = getFileSystemObject().getSourceLocation(); + } + return fSourceLocation; + } + + /** + * Set the source location for this element. + * + * @param sourceLocation + * the source location + */ + public void setSourceLocation(String sourceLocation) { + fSourceLocation = sourceLocation; + } + + /** + * Get all the TraceFileSystemElements recursively. + * + * @param result + * the list accumulating the result + */ + public void getAllChildren(List result) { + AdaptableList files = getFiles(); + for (Object file : files.getChildren()) { + result.add((TraceFileSystemElement) file); + } + + AdaptableList folders = getFolders(); + for (Object folder : folders.getChildren()) { + TraceFileSystemElement traceElementFolder = (TraceFileSystemElement) folder; + traceElementFolder.getAllChildren(result); + } + } + + /** + * Create a root TraceFileSystemElement suitable to be passed to a + * {@link TraceValidateAndImportOperation} + * + * @param object + * the IFileSystemObject (abstracting File, Tar, Zip, etc) to + * create the root TraceFileSystemElement from + * @param provider + * the import provider to be used, compatible with the + * IFileSystemObject + * @return the resulting root TraceFileSystemElement + * + * @See {@link TraceValidateAndImportOperation} + * @See {@link ArchiveUtil#getRootObjectAndProvider(File, org.eclipse.swt.widgets.Shell)} + */ + public static TraceFileSystemElement createRootTraceFileElement(IFileSystemObject object, + FileSystemObjectImportStructureProvider provider) { + boolean isContainer = provider.isFolder(object); + String elementLabel = provider.getLabel(object); + + // Use an empty label so that display of the element's full name + // doesn't include a confusing label + TraceFileSystemElement dummyParent = new TraceFileSystemElement("", null, true, provider);//$NON-NLS-1$ + Object dummyParentFileSystemObject = object; + Object rawFileSystemObject = object.getRawFileSystemObject(); + if (rawFileSystemObject instanceof File) { + dummyParentFileSystemObject = provider.getIFileSystemObject(((File) rawFileSystemObject).getParentFile()); + } + dummyParent.setFileSystemObject(dummyParentFileSystemObject); + dummyParent.setPopulated(); + TraceFileSystemElement result = new TraceFileSystemElement( + elementLabel, dummyParent, isContainer, provider); + result.setFileSystemObject(object); + + // Get the files for the element so as to build the first level + result.getFiles(); + + return dummyParent; + } +} \ 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/TraceValidateAndImportOperation.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceValidateAndImportOperation.java new file mode 100644 index 0000000000..d6b24e5b57 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/TraceValidateAndImportOperation.java @@ -0,0 +1,686 @@ +/******************************************************************************* + * 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.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +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 org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.ModalContext; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tracecompass.internal.tmf.ui.Activator; +import org.eclipse.tracecompass.tmf.core.TmfCommonConstants; +import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException; +import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType; +import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper; +import org.eclipse.tracecompass.tmf.core.util.Pair; +import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder; +import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils; +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.wizards.datatransfer.FileSystemStructureProvider; +import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider; +import org.eclipse.ui.wizards.datatransfer.ImportOperation; + +/** + * An operation that performs validation and importing of traces. Its primary + * inputs are a collection of TraceFileSystemElement and several flags that control + * + */ +public class TraceValidateAndImportOperation implements IRunnableWithProgress { + + private static final String TRACE_IMPORT_TEMP_FOLDER = ".traceImport"; //$NON-NLS-1$ + + private String fTraceType; + private IPath fDestinationContainerPath; + private IPath fBaseSourceContainerPath; + private boolean fImportFromArchive; + private int fImportOptionFlags; + private Shell fShell; + private TmfTraceFolder fTraceFolderElement; + private List fSelectedFileSystemElements; + + private IStatus fStatus; + private ImportConflictHandler fConflictHandler; + private String fCurrentPath; + + private List fImportedResources; + + /** + * Constructs a new validate and import operation. + * + * @param shell + * the parent shell to use for possible error messages + * @param traceFileSystemElements + * the trace file elements to import + * @param traceId + * the trace type to import the traces as (can be set to null for + * automatic detection) + * @param baseSourceContainerPath + * the path to the container of the source. This is used as a + * "base" to generate the folder structure for the + * "preserve folder structure" option. + * @param destinationContainerPath + * the destination path of the import operation, typically a + * trace folder path. + * @param importFromArchive + * whether or not the source is an archive + * @param importOptionFlags + * bit-wise 'or' of import option flag constants ( + * {@link ImportTraceWizardPage#OPTION_PRESERVE_FOLDER_STRUCTURE} + * , + * {@link ImportTraceWizardPage#OPTION_CREATE_LINKS_IN_WORKSPACE} + * , + * {@link ImportTraceWizardPage#OPTION_IMPORT_UNRECOGNIZED_TRACES} + * , and + * {@link ImportTraceWizardPage#OPTION_OVERWRITE_EXISTING_RESOURCES} + * ) + * @param traceFolderElement + * the destination trace folder of the import operation. + */ + public TraceValidateAndImportOperation(Shell shell, List traceFileSystemElements, String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean importFromArchive, int importOptionFlags, TmfTraceFolder traceFolderElement) { + fTraceType = traceId; + fBaseSourceContainerPath = baseSourceContainerPath; + fDestinationContainerPath = destinationContainerPath; + fImportOptionFlags = importOptionFlags; + fImportFromArchive = importFromArchive; + fShell = shell; + fTraceFolderElement = traceFolderElement; + + boolean overwriteExistingResources = (importOptionFlags & ImportTraceWizardPage.OPTION_OVERWRITE_EXISTING_RESOURCES) != 0; + if (overwriteExistingResources) { + fConflictHandler = new ImportConflictHandler(fShell, fTraceFolderElement, ImportConfirmation.OVERWRITE_ALL); + } else { + fConflictHandler = new ImportConflictHandler(fShell, fTraceFolderElement, ImportConfirmation.SKIP); + } + fImportedResources = new ArrayList<>(); + fSelectedFileSystemElements = traceFileSystemElements; + } + + @Override + public void run(IProgressMonitor progressMonitor) { + try { + + final List selectedFileSystemElements = fSelectedFileSystemElements; + + // List fileSystemElements will be filled using the + // passThroughFilter + SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 1); + + // Check if operation was cancelled. + ModalContext.checkCanceled(subMonitor); + + // Temporary directory to contain any extracted files + IFolder destTempFolder = fTraceFolderElement.getProject().getResource().getFolder(TRACE_IMPORT_TEMP_FOLDER); + if (destTempFolder.exists()) { + SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + destTempFolder.delete(true, monitor); + } + SubProgressMonitor monitor = new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + destTempFolder.create(IResource.HIDDEN, true, monitor); + + subMonitor = SubMonitor.convert(progressMonitor, 2); + String baseSourceLocation = null; + 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)); + + if (!selectedFileSystemElements.isEmpty()) { + // 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 tempFolderFileSystemElements = createElementsForFolder(destTempFolder); + extractAllArchiveFiles(tempFolderFileSystemElements, destTempFolder, destTempFolder.getLocation(), archiveMonitor.newChild(1)); + } + } else { + SubMonitor directoryMonitor = SubMonitor.convert(subMonitor.newChild(1), 2); + // Import selected files, excluding archives (done in a later + // step) + importFileSystemElements(directoryMonitor.newChild(1), selectedFileSystemElements); + + // Extract archives in selected files (if any) to temporary + // folder + extractAllArchiveFiles(selectedFileSystemElements, destTempFolder, fBaseSourceContainerPath, directoryMonitor.newChild(1)); + // Even if the files were extracted to temporary folder, they + // have to look like they originate from the source folder + baseSourceLocation = URIUtil.toUnencodedString(fBaseSourceContainerPath.toFile().getCanonicalFile().toURI()); + } + + /* + * Import extracted files that are now in the temporary folder, if + * any + */ + + // We need to update the source container path because the + // "preserve folder structure" option would create the + // wrong trace folders otherwise. + fBaseSourceContainerPath = destTempFolder.getLocation(); + List tempFolderFileSystemElements = createElementsForFolder(destTempFolder); + if (!tempFolderFileSystemElements.isEmpty()) { + calculateSourceLocations(tempFolderFileSystemElements, baseSourceLocation); + // Never import extracted files as links, they would link to the + // temporary directory that will be deleted + fImportOptionFlags = fImportOptionFlags & ~ImportTraceWizardPage.OPTION_CREATE_LINKS_IN_WORKSPACE; + SubMonitor importTempMonitor = subMonitor.newChild(1); + importFileSystemElements(importTempMonitor, tempFolderFileSystemElements); + } + + if (destTempFolder.exists()) { + destTempFolder.delete(true, progressMonitor); + } + + setStatus(Status.OK_STATUS); + } catch (InterruptedException e) { + setStatus(Status.CANCEL_STATUS); + } catch (Exception e) { + String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$ + (fCurrentPath != null ? fCurrentPath : ""); //$NON-NLS-1$ + Activator.getDefault().logError(errorMessage, e); + setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage, e)); + } + } + + /** + * Get the list of resources that were imported by this operation. An + * example use case would be to use this to open traces that were imported + * by this operation. + * + * @return the resources that were imported + */ + public List getImportedResources() { + return fImportedResources; + } + + /** + * Import a collection of file system elements into the workspace. + */ + private void importFileSystemElements(IProgressMonitor monitor, List fileSystemElements) + throws InterruptedException, TmfTraceImportException, CoreException, InvocationTargetException { + SubMonitor subMonitor = SubMonitor.convert(monitor, fileSystemElements.size()); + + ListIterator fileSystemElementsIter = fileSystemElements.listIterator(); + + // Map to remember already imported directory traces + final Map directoryTraces = new HashMap<>(); + while (fileSystemElementsIter.hasNext()) { + ModalContext.checkCanceled(monitor); + fCurrentPath = null; + TraceFileSystemElement element = fileSystemElementsIter.next(); + IFileSystemObject fileSystemObject = element.getFileSystemObject(); + String resourcePath = element.getFileSystemObject().getAbsolutePath(); + 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(); + 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(); + 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 static List 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 = TraceFileSystemElement.createRootTraceFileElement(rootElement, importStructureProvider); + List list = new LinkedList<>(); + createRootElement.getAllChildren(list); + return list; + } + + /** + * Extract all file system elements (File) to destination folder (typically + * workspace/TraceProject/.traceImport) + */ + private void extractAllArchiveFiles(List fileSystemElements, IFolder destFolder, IPath baseSourceContainerPath, IProgressMonitor progressMonitor) throws InterruptedException, CoreException, InvocationTargetException { + SubMonitor subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size()); + ListIterator 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 && ArchiveUtil.isArchiveFile(archiveFile); + if (isArchiveFileElement) { + elementProgress = SubMonitor.convert(elementProgress, 4); + IPath relativeToSourceContainer = new Path(element.getFileSystemObject().getAbsolutePath()).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 = TraceFileSystemElement.createRootTraceFileElement(rootElement, importStructureProvider); + List extractedChildren = new ArrayList<>(); + newElement.getAllChildren(extractedChildren); + 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 rootObjectAndProvider = ArchiveUtil.getRootObjectAndProvider(sourceFile, fShell); + TraceFileSystemElement rootElement = TraceFileSystemElement.createRootTraceFileElement(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond()); + List fileSystemElements = new ArrayList<>(); + rootElement.getAllChildren(fileSystemElements); + 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 static 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 fileSystemElements, String baseSourceLocation) { + for (TraceFileSystemElement element : fileSystemElements) { + IPath tempRelative = new Path(element.getFileSystemObject().getAbsolutePath()).makeRelativeTo(fBaseSourceContainerPath); + String sourceLocation = baseSourceLocation + tempRelative; + element.setSourceLocation(sourceLocation); + + TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent(); + tempRelative = new Path(parentElement.getFileSystemObject().getAbsolutePath()).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 fileSystemElementsIter, IFolder tempFolder, IProgressMonitor progressMonitor) throws InterruptedException, + InvocationTargetException { + List subList = new ArrayList<>(); + // Collect all the elements + while (fileSystemElementsIter.hasNext()) { + ModalContext.checkCanceled(progressMonitor); + TraceFileSystemElement element = fileSystemElementsIter.next(); + if (element.isDirectory()) { + Object[] array = element.getFiles().getChildren(); + for (int i = 0; i < array.length; i++) { + subList.add((TraceFileSystemElement) array[i]); + } + } + subList.add(element); + } + + if (subList.isEmpty()) { + return; + } + + TraceFileSystemElement root = getRootElement(subList.get(0)); + + ImportProvider fileSystemStructureProvider = new ImportProvider(); + + IOverwriteQuery myQueryImpl = new IOverwriteQuery() { + @Override + public String queryOverwrite(String file) { + return IOverwriteQuery.NO_ALL; + } + }; + + progressMonitor.setTaskName(Messages.ImportTraceWizard_ExtractImportOperationTaskName); + IPath containerPath = tempFolder.getFullPath(); + ImportOperation operation = new ImportOperation(containerPath, root, fileSystemStructureProvider, myQueryImpl, subList); + operation.setContext(fShell); + + operation.setCreateContainerStructure(true); + operation.setOverwriteResources(false); + operation.setVirtualFolders(false); + + operation.run(new SubProgressMonitor(progressMonitor, subList.size(), SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); + } + + private static TraceFileSystemElement getRootElement(TraceFileSystemElement element) { + TraceFileSystemElement root = element; + while (root.getParent() != null) { + root = (TraceFileSystemElement) root.getParent(); + } + return root; + } + + private IPath computeDestinationContainerPath(Path resourcePath) { + IPath destinationContainerPath = fDestinationContainerPath; + + // We need to figure out the new destination path relative to the + // selected "base" source directory. + // Here for example, the selected source directory is /home/user + if ((fImportOptionFlags & ImportTraceWizardPage.OPTION_PRESERVE_FOLDER_STRUCTURE) != 0) { + // /home/user/bar/foo/trace -> /home/user/bar/foo + IPath sourceContainerPath = resourcePath.removeLastSegments(1); + if (fBaseSourceContainerPath.equals(resourcePath)) { + // Use resourcePath directory if fBaseSourceContainerPath + // points to a directory trace + sourceContainerPath = resourcePath; + } + // /home/user/bar/foo, /home/user -> bar/foo + IPath relativeContainerPath = sourceContainerPath.makeRelativeTo(fBaseSourceContainerPath); + // project/Traces + bar/foo -> project/Traces/bar/foo + destinationContainerPath = fDestinationContainerPath.append(relativeContainerPath); + } + return destinationContainerPath; + } + + /** + * Import a single file system element into the workspace. + */ + private void validateAndImportTrace(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) + throws TmfTraceImportException, CoreException, InvocationTargetException, InterruptedException { + String path = fileSystemElement.getFileSystemObject().getAbsolutePath(); + TraceTypeHelper traceTypeHelper = null; + + File file = (File) fileSystemElement.getFileSystemObject().getRawFileSystemObject(); + boolean isArchiveFileElement = fileSystemElement.getFileSystemObject() instanceof FileFileSystemObject && ArchiveUtil.isArchiveFile(file); + if (isArchiveFileElement) { + // We'll be extracting this later, do not import as a trace + return; + } + + if (fTraceType == null) { + // Auto Detection + try { + traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(path, null, null); + } catch (TmfTraceImportException e) { + // the trace did not match any trace type + } + if (traceTypeHelper == null) { + if ((fImportOptionFlags & ImportTraceWizardPage.OPTION_IMPORT_UNRECOGNIZED_TRACES) != 0) { + importResource(fileSystemElement, monitor); + } + return; + } + } else { + boolean isDirectoryTraceType = TmfTraceType.isDirectoryTraceType(fTraceType); + if (fileSystemElement.isDirectory() != isDirectoryTraceType) { + return; + } + traceTypeHelper = TmfTraceType.getTraceType(fTraceType); + + if (traceTypeHelper == null) { + // Trace type not found + throw new TmfTraceImportException(Messages.ImportTraceWizard_TraceTypeNotFound); + } + + if (!traceTypeHelper.validate(path).isOK()) { + // Trace type exist but doesn't validate for given trace. + return; + } + } + + // Finally import trace + IResource importedResource = importResource(fileSystemElement, monitor); + if (importedResource != null) { + TmfTraceTypeUIUtils.setTraceType(importedResource, traceTypeHelper); + fImportedResources.add(importedResource); + } + + } + + /** + * Imports a trace resource to project. In case of name collision the user + * will be asked to confirm overwriting the existing trace, overwriting or + * skipping the trace to be imported. + * + * @param fileSystemElement + * trace file system object to import + * @param monitor + * a progress monitor + * @return the imported resource or null if no resource was imported + * + * @throws InvocationTargetException + * if problems during import operation + * @throws InterruptedException + * if cancelled + * @throws CoreException + * if problems with workspace + */ + private IResource importResource(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException, CoreException { + + IPath tracePath = getInitialDestinationPath(fileSystemElement); + String newName = fConflictHandler.checkAndHandleNameClash(tracePath, monitor); + if (newName == null) { + return null; + } + fileSystemElement.setLabel(newName); + + List subList = new ArrayList<>(); + + FileSystemElement parentFolder = fileSystemElement.getParent(); + + IPath containerPath = fileSystemElement.getDestinationContainerPath(); + tracePath = containerPath.addTrailingSeparator().append(fileSystemElement.getLabel()); + boolean createLinksInWorkspace = (fImportOptionFlags & ImportTraceWizardPage.OPTION_CREATE_LINKS_IN_WORKSPACE) != 0; + if (fileSystemElement.isDirectory() && !createLinksInWorkspace) { + containerPath = tracePath; + + Object[] array = fileSystemElement.getFiles().getChildren(); + for (int i = 0; i < array.length; i++) { + subList.add((TraceFileSystemElement) array[i]); + } + parentFolder = fileSystemElement; + + } else { + subList.add(fileSystemElement); + } + + ImportProvider fileSystemStructureProvider = new ImportProvider(); + + IOverwriteQuery myQueryImpl = new IOverwriteQuery() { + @Override + public String queryOverwrite(String file) { + return IOverwriteQuery.NO_ALL; + } + }; + + monitor.setTaskName(Messages.ImportTraceWizard_ImportOperationTaskName + " " + fileSystemElement.getFileSystemObject().getAbsolutePath()); //$NON-NLS-1$ + ImportOperation operation = new ImportOperation(containerPath, parentFolder, fileSystemStructureProvider, myQueryImpl, subList); + operation.setContext(fShell); + + operation.setCreateContainerStructure(false); + operation.setOverwriteResources(false); + operation.setCreateLinks(createLinksInWorkspace); + operation.setVirtualFolders(false); + + operation.run(new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); + String sourceLocation = fileSystemElement.getSourceLocation(); + IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(tracePath); + if (sourceLocation != null) { + resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation); + } + + return resource; + } + + private static boolean isDirectoryTrace(TraceFileSystemElement fileSystemElement) { + String path = fileSystemElement.getFileSystemObject().getAbsolutePath(); + if (TmfTraceType.isDirectoryTrace(path)) { + return true; + } + return false; + } + + /** + * @return the initial destination path, before rename, if any + */ + private static IPath getInitialDestinationPath(TraceFileSystemElement fileSystemElement) { + IPath traceFolderPath = fileSystemElement.getDestinationContainerPath(); + return traceFolderPath.append(fileSystemElement.getFileSystemObject().getName()); + } + + /** + * Set the status for this operation + * + * @param status + * the status + */ + private void setStatus(IStatus status) { + fStatus = status; + } + + /** + * Get the resulting status of this operation. Clients can use this for + * error reporting, etc. + * + * @return the resulting status + */ + public IStatus getStatus() { + return fStatus; + } + + private class ImportProvider implements IImportStructureProvider { + + ImportProvider() { + } + + @Override + public String getLabel(Object element) { + TraceFileSystemElement resource = (TraceFileSystemElement) element; + return resource.getLabel(); + } + + @Override + public List getChildren(Object element) { + TraceFileSystemElement resource = (TraceFileSystemElement) element; + Object[] array = resource.getFiles().getChildren(); + List list = new ArrayList<>(); + for (int i = 0; i < array.length; i++) { + list.add(array[i]); + } + return list; + } + + @Override + public InputStream getContents(Object element) { + TraceFileSystemElement resource = (TraceFileSystemElement) element; + return resource.getProvider().getContents(resource.getFileSystemObject()); + } + + @Override + public String getFullPath(Object element) { + TraceFileSystemElement resource = (TraceFileSystemElement) element; + return resource.getProvider().getFullPath(resource.getFileSystemObject()); + } + + @Override + public boolean isFolder(Object element) { + TraceFileSystemElement resource = (TraceFileSystemElement) element; + return resource.isDirectory(); + } + } +} \ 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/ZipFileSystemObject.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipFileSystemObject.java new file mode 100644 index 0000000000..12f8a08f38 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/project/wizards/importtrace/ZipFileSystemObject.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * 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.IOException; +import java.net.URI; +import java.util.zip.ZipEntry; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.URIUtil; + +/** + * The "Zip" implementation of an IFileSystemObject + */ +class ZipFileSystemObject implements IFileSystemObject { + + private ZipEntry fFileSystemObject; + private String fArchivePath; + + ZipFileSystemObject(ZipEntry fileSystemObject, String archivePath) { + fFileSystemObject = fileSystemObject; + fArchivePath = archivePath; + } + + @Override + public String getName() { + return new Path(fFileSystemObject.getName()).lastSegment(); + } + + @Override + public String getAbsolutePath() { + throw new UnsupportedOperationException(); + } + + @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; + } +} \ No newline at end of file -- 2.34.1