/*******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
package org.eclipse.tracecompass.internal.tmf.remote.ui.wizards.fetch.model;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.tracecompass.internal.tmf.remote.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.remote.ui.messages.RemoteMessages;
import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ArchiveUtil;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.FileSystemObjectImportStructureProvider;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.IFileSystemObject;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportConfirmation;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportConflictHandler;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.ImportTraceWizardPage;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.TraceFileSystemElement;
+import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace.TraceValidateAndImportOperation;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageElement;
import org.eclipse.tracecompass.internal.tmf.ui.project.wizards.tracepkg.TracePackageTraceElement;
import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
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.wizards.datatransfer.FileSystemStructureProvider;
/**
- * Operation to import a set of traces from a remote node into a tracing project.
+ * Operation to import a set of traces from a remote node into a tracing
+ * project.
*
* @author Bernd Hufmann
*/
public class RemoteImportTracesOperation extends TmfWorkspaceModifyOperation {
+ private static final String TRACE_IMPORT = ".traceRemoteImport"; //$NON-NLS-1$
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
private final TmfTraceFolder fDestination;
private final Object[] fTraceElements;
private final ImportConflictHandler fConflictHandler;
+ private final List<IResource> fImportedResources = new ArrayList<>();
// ------------------------------------------------------------------------
// Constructor(s)
// ------------------------------------------------------------------------
/**
- * Operation to import a set of traces from a remote node into a tracing project.
+ * Operation to import a set of traces from a remote node into a tracing
+ * project.
+ *
* @param shell
- * shell to display confirmation dialog
+ * shell to display confirmation dialog
* @param destination
- * The destination traces folder
+ * The destination traces folder
* @param elements
- * The trace model elements describing the traces to import
+ * The trace model elements describing the traces to import
* @param overwriteAll
- * Flag to indicate to overwrite all existing traces
+ * Flag to indicate to overwrite all existing traces
*/
public RemoteImportTracesOperation(Shell shell, TmfTraceFolder destination, Object[] elements, boolean overwriteAll) {
super();
try {
doRun(monitor);
setStatus(Status.OK_STATUS);
- } catch (InterruptedException e) {
+ } catch (InterruptedException | OperationCanceledException e) {
setStatus(Status.CANCEL_STATUS);
throw e;
} catch (Exception e) {
IFileStore remoteFile = traceFilesElement.getRemoteFile();
// Preserve folder structure
- IPath sessionParentPath = TmfTraceCoreUtils.newSafePath(rootPath);
+ IPath sessionParentPath = TmfTraceCoreUtils.newSafePath(rootPath).removeLastSegments(1);
IPath traceParentPath = TmfTraceCoreUtils.newSafePath(remoteFile.getParent().toURI().getPath());
IPath relativeTracePath = Path.EMPTY;
if (sessionParentPath.isPrefixOf(traceParentPath)) {
childMonitor.done();
traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(traceRes.getLocation().toOSString(), null, null);
} catch (TmfTraceImportException e) {
- //Could not figure out the type
+ // Could not figure out the type
}
}
if (traceTypeHelper != null) {
TmfTraceTypeUIUtils.setTraceType(traceRes, traceTypeHelper);
+ fImportedResources.add(traceRes);
}
// Set source location
// TODO allow for downloading index directory and files
if (!info.isDirectory()) {
SubMonitor childMonitor = subMonitor.newChild(1);
- childMonitor.setTaskName(RemoteMessages.RemoteImportTracesOperation_DownloadTask + ' ' + trace.getName()+ '/' + source.getName());
-
+ childMonitor.setTaskName(RemoteMessages.RemoteImportTracesOperation_DownloadTask + ' ' + trace.getName() + '/' + source.getName());
try (InputStream in = source.openInputStream(EFS.NONE, new NullProgressMonitor())) {
- copy(in, destination, childMonitor, info.getLength());
+ copy(in, folder, destination, childMonitor, info.getLength());
}
}
}
IPath destination = folder.getLocation().addTrailingSeparator().append(traceName);
IFileInfo info = trace.fetchInfo();
- subMonitor.setTaskName(RemoteMessages.RemoteImportTracesOperation_DownloadTask + ' ' + trace.getName()+ '/' +trace.getName());
+ subMonitor.setTaskName(RemoteMessages.RemoteImportTracesOperation_DownloadTask + ' ' + trace.getName() + '/' + trace.getName());
try (InputStream in = trace.openInputStream(EFS.NONE, new NullProgressMonitor())) {
- copy(in, destination, subMonitor, info.getLength());
+ copy(in, folder, destination, subMonitor, info.getLength());
}
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
return folder.findMember(traceName);
}
+ private void copy(InputStream in, IFolder destFolder, IPath destination, SubMonitor monitor, long length) throws IOException {
+ IFolder intermediateTempFolder = null;
+ IFile tempFile = null;
+ File intermediateFile = null;
+ try {
+ intermediateTempFolder = fDestination.getProject().getResource().getFolder(TRACE_IMPORT);
+ if (intermediateTempFolder.exists()) {
+ intermediateTempFolder.delete(true, SubMonitor.convert(monitor));
+ }
+ intermediateTempFolder.create(true, true, SubMonitor.convert(monitor));
+ tempFile = intermediateTempFolder.getFile(destination.lastSegment());
+ tempFile.create(null, true, SubMonitor.convert(monitor));
+ intermediateFile = tempFile.getLocation().toFile();
+ intermediateFile.createNewFile();
+ copy(in, intermediateFile, length, monitor);
+ if (ArchiveUtil.isArchiveFile(intermediateFile)) {
+ // Select all the elements in the archive
+ FileSystemObjectImportStructureProvider importProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
+ IFileSystemObject fileSystemObject = importProvider.getIFileSystemObject(intermediateFile);
+ TraceFileSystemElement rootTraceFileElement = TraceFileSystemElement.createRootTraceFileElement(fileSystemObject, importProvider);
+
+ // Select all the elements in the archive
+ List<TraceFileSystemElement> list = new ArrayList<>();
+ rootTraceFileElement.getAllChildren(list);
+ if (!destFolder.exists()) {
+ destFolder.create(true, true, SubMonitor.convert(monitor));
+ }
+ final IFolder folder = destFolder.getFolder(destination.lastSegment());
+ if (!folder.exists()) {
+ folder.create(true, true, SubMonitor.convert(monitor));
+ }
- private static void copy(InputStream in, IPath destination, SubMonitor monitor, long length) throws IOException {
- try (OutputStream out = new FileOutputStream(destination.toFile())) {
+ final TraceValidateAndImportOperation operation = new TraceValidateAndImportOperation(
+ fShell, list, null, intermediateTempFolder.getLocation(), destFolder.getFullPath(), false,
+ ImportTraceWizardPage.OPTION_PRESERVE_FOLDER_STRUCTURE | ImportTraceWizardPage.OPTION_IMPORT_UNRECOGNIZED_TRACES,
+ fDestination);
+ operation.setConflictHandler(fConflictHandler);
+ operation.run(SubMonitor.convert(monitor));
+ monitor.done();
+ } else {
+ // should be lightning fast unless someone maps different files
+ // to different physical disks. In windows and linux, moves are
+ // super fast on the same drive
+ Files.move(intermediateFile.toPath(), destination.toFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+ } catch (CoreException | InvocationTargetException | InterruptedException e) {
+ Activator.getDefault().logError(e.getMessage(), e);
+ } finally {
+ if (intermediateFile != null && intermediateFile.exists()) {
+ intermediateFile.delete();
+ }
+ try {
+ if (tempFile != null && tempFile.exists()) {
+ tempFile.delete(true, SubMonitor.convert(monitor));
+ }
+ if (intermediateTempFolder != null && intermediateTempFolder.exists()) {
+ intermediateTempFolder.delete(true, SubMonitor.convert(monitor));
+ }
+ } catch (CoreException e) {
+ Activator.getDefault().logError(e.getMessage(), e);
+ }
+ }
+ }
+
+ private static void copy(InputStream in, File intermediateFile, long length, SubMonitor monitor) throws IOException, FileNotFoundException {
+ try (OutputStream out = new FileOutputStream(intermediateFile)) {
monitor.setWorkRemaining((int) (length / BYTES_PER_KB));
byte[] buf = new byte[BYTES_PER_KB * BUFFER_IN_KB];
int counter = 0;
for (;;) {
int n = in.read(buf);
if (n <= 0) {
- return;
+ break;
}
out.write(buf, 0, n);
counter = (counter % BYTES_PER_KB) + n;
public IStatus getStatus() {
return fStatus;
}
+
+ /**
+ * 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.
+ *
+ * Note this includes only valid traces and doesn'tinclude unrecognized
+ * files.
+ *
+ * @return the trace resources that were imported
+ */
+ public List<IResource> getImportedResources() {
+ return fImportedResources;
+ }
}