tmf: Use Apache Common Compress for importing from archive
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / project / wizards / importtrace / TraceValidateAndImportOperation.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Marc-Andre Laperle - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
14
15 import java.io.File;
16 import java.io.InputStream;
17 import java.lang.reflect.InvocationTargetException;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.ListIterator;
26 import java.util.Map;
27
28 import org.eclipse.core.filesystem.EFS;
29 import org.eclipse.core.filesystem.IFileInfo;
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.resources.IFolder;
32 import org.eclipse.core.resources.IResource;
33 import org.eclipse.core.resources.ResourcesPlugin;
34 import org.eclipse.core.runtime.CoreException;
35 import org.eclipse.core.runtime.IPath;
36 import org.eclipse.core.runtime.IProgressMonitor;
37 import org.eclipse.core.runtime.IStatus;
38 import org.eclipse.core.runtime.Path;
39 import org.eclipse.core.runtime.Status;
40 import org.eclipse.core.runtime.SubMonitor;
41 import org.eclipse.core.runtime.URIUtil;
42 import org.eclipse.jface.operation.ModalContext;
43 import org.eclipse.swt.widgets.Shell;
44 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
45 import org.eclipse.tracecompass.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
46 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
47 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
48 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
49 import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
50 import org.eclipse.tracecompass.tmf.core.util.Pair;
51 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
52 import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceTypeUIUtils;
53 import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
54 import org.eclipse.ui.dialogs.FileSystemElement;
55 import org.eclipse.ui.dialogs.IOverwriteQuery;
56 import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
57 import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
58 import org.eclipse.ui.wizards.datatransfer.ImportOperation;
59
60 /**
61 * An operation that performs validation and importing of traces. Its primary
62 * inputs are a collection of TraceFileSystemElement and several flags that
63 * control
64 *
65 */
66 public class TraceValidateAndImportOperation extends TmfWorkspaceModifyOperation {
67
68 private static final String TRACE_IMPORT_TEMP_FOLDER = ".traceImport"; //$NON-NLS-1$
69
70 private String fTraceType;
71 private IPath fDestinationContainerPath;
72 private IPath fBaseSourceContainerPath;
73 private boolean fImportFromArchive;
74 private int fImportOptionFlags;
75 private Shell fShell;
76 private TmfTraceFolder fTraceFolderElement;
77 private List<TraceFileSystemElement> fSelectedFileSystemElements;
78
79 private IStatus fStatus;
80 private ImportConflictHandler fConflictHandler;
81 private String fCurrentPath;
82
83 private List<IResource> fImportedResources;
84
85 /**
86 * Constructs a new validate and import operation.
87 *
88 * @param shell
89 * the parent shell to use for possible error messages
90 * @param traceFileSystemElements
91 * the trace file elements to import
92 * @param traceId
93 * the trace type to import the traces as (can be set to null for
94 * automatic detection)
95 * @param baseSourceContainerPath
96 * the path to the container of the source. This is used as a
97 * "base" to generate the folder structure for the
98 * "preserve folder structure" option.
99 * @param destinationContainerPath
100 * the destination path of the import operation, typically a
101 * trace folder path.
102 * @param importFromArchive
103 * whether or not the source is an archive
104 * @param importOptionFlags
105 * bit-wise 'or' of import option flag constants (
106 * {@link ImportTraceWizardPage#OPTION_PRESERVE_FOLDER_STRUCTURE}
107 * ,
108 * {@link ImportTraceWizardPage#OPTION_CREATE_LINKS_IN_WORKSPACE}
109 * ,
110 * {@link ImportTraceWizardPage#OPTION_IMPORT_UNRECOGNIZED_TRACES}
111 * , and
112 * {@link ImportTraceWizardPage#OPTION_OVERWRITE_EXISTING_RESOURCES}
113 * )
114 * @param traceFolderElement
115 * the destination trace folder of the import operation.
116 */
117 public TraceValidateAndImportOperation(Shell shell, List<TraceFileSystemElement> traceFileSystemElements, String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean importFromArchive, int importOptionFlags,
118 TmfTraceFolder traceFolderElement) {
119 fTraceType = traceId;
120 fBaseSourceContainerPath = baseSourceContainerPath;
121 fDestinationContainerPath = destinationContainerPath;
122 fImportOptionFlags = importOptionFlags;
123 fImportFromArchive = importFromArchive;
124 fShell = shell;
125 fTraceFolderElement = traceFolderElement;
126
127 boolean overwriteExistingResources = (importOptionFlags & ImportTraceWizardPage.OPTION_OVERWRITE_EXISTING_RESOURCES) != 0;
128 if (overwriteExistingResources) {
129 setConflictHandler(new ImportConflictHandler(fShell, fTraceFolderElement, ImportConfirmation.OVERWRITE_ALL));
130 } else {
131 setConflictHandler(new ImportConflictHandler(fShell, fTraceFolderElement, ImportConfirmation.SKIP));
132 }
133 fImportedResources = new ArrayList<>();
134 fSelectedFileSystemElements = traceFileSystemElements;
135 }
136
137 /**
138 * This orders by files first then the folders. Then by lexical order.
139 * This comparator handles full paths.
140 * Example of ordering:
141 *
142 * /trace.txt
143 * /folderA/trace.txt
144 * /folderA/folderB/trace.txt
145 * /folderZ/trace.txt
146 */
147 private final class FileObjectPathComparator implements Comparator<TraceFileSystemElement> {
148 @Override
149 public int compare(TraceFileSystemElement e1, TraceFileSystemElement e2) {
150 IFileSystemObject o1 = e1.getFileSystemObject();
151 IFileSystemObject o2 = e2.getFileSystemObject();
152 IPath p1 = new Path(e1.getProvider().getFullPath(o1));
153 IPath p2 = new Path(e2.getProvider().getFullPath(o2));
154 int segmentCount1 = p1.segmentCount();
155 int segmentCount2 = p2.segmentCount();
156
157 int commonParentSegmentCount = Math.min(segmentCount1, segmentCount2) - 1;
158 // Compare parents that are common (in terms of segment number).
159 // If one of them is different, we do not need to worry about any
160 // children, we already know in which order they are going to be.
161 for (int i = 0; i < commonParentSegmentCount; i++) {
162 int compare = p1.segment(i).compareToIgnoreCase(p2.segment(i));
163 if (compare != 0) {
164 return compare;
165 }
166 }
167
168 // At this point, we know all the common parent folders are the same.
169 // Either:
170 // - One of them is shorter which means it should be processed first because files are processed before sub-folders.
171 // or
172 // - They are the same level so only the name matters.
173 if (segmentCount1 != segmentCount2) {
174 return Integer.compare(segmentCount1, segmentCount2);
175 }
176
177 //
178 return o1.getName().compareToIgnoreCase(o2.getName());
179 }
180 }
181
182 @Override
183 protected void execute(IProgressMonitor progressMonitor) throws CoreException, InvocationTargetException, InterruptedException {
184 try {
185 final int ARCHIVE_OR_DIRECTORY_PROGRESS = 45;
186 final int EXTRA_IMPORT_OPERATION_PROGRESS = 45;
187 final int DELETE_PROGRESS = 10;
188 final int TOTAL_PROGRESS = ARCHIVE_OR_DIRECTORY_PROGRESS +
189 EXTRA_IMPORT_OPERATION_PROGRESS + DELETE_PROGRESS;
190
191 final List<TraceFileSystemElement> selectedFileSystemElements = fSelectedFileSystemElements;
192
193 // List fileSystemElements will be filled using the
194 // passThroughFilter
195 SubMonitor subMonitor = SubMonitor.convert(progressMonitor, TOTAL_PROGRESS);
196
197 // Check if operation was cancelled.
198 ModalContext.checkCanceled(subMonitor);
199
200 // Temporary directory to contain any extracted files
201 IFolder destTempFolder = fTraceFolderElement.getProject().getResource().getFolder(TRACE_IMPORT_TEMP_FOLDER);
202 if (destTempFolder.exists()) {
203 SubMonitor monitor = subMonitor.newChild(1);
204 destTempFolder.delete(true, monitor);
205 }
206 SubMonitor monitor = subMonitor.newChild(1);
207 destTempFolder.create(IResource.HIDDEN, true, monitor);
208
209 String baseSourceLocation = null;
210 if (fImportFromArchive) {
211 // When importing from archive, we first extract the
212 // *selected* files to a temporary folder then create new
213 // TraceFileSystemElements
214
215 SubMonitor archiveMonitor = SubMonitor.convert(subMonitor.newChild(ARCHIVE_OR_DIRECTORY_PROGRESS), 2);
216
217 // Extract selected files from source archive to temporary
218 // folder
219 extractArchiveContent(selectedFileSystemElements.iterator(), destTempFolder, archiveMonitor.newChild(1));
220
221 if (!selectedFileSystemElements.isEmpty()) {
222 // Even if the files were extracted to temporary folder, they
223 // have to look like they originate from the source archive
224 baseSourceLocation = getRootElement(selectedFileSystemElements.get(0)).getSourceLocation();
225 // Extract additional archives contained in the extracted files
226 // (archives in archives)
227 List<TraceFileSystemElement> tempFolderFileSystemElements = createElementsForFolder(destTempFolder);
228 extractAllArchiveFiles(tempFolderFileSystemElements, destTempFolder, destTempFolder.getLocation(), archiveMonitor.newChild(1));
229 }
230 } else {
231 SubMonitor directoryMonitor = SubMonitor.convert(subMonitor.newChild(ARCHIVE_OR_DIRECTORY_PROGRESS), 2);
232 // Import selected files, excluding archives (done in a later step)
233 importFileSystemElements(directoryMonitor.newChild(1), selectedFileSystemElements);
234
235 // Extract archives in selected files (if any) to temporary folder
236 extractAllArchiveFiles(selectedFileSystemElements, destTempFolder, fBaseSourceContainerPath, directoryMonitor.newChild(1));
237 // Even if the files were extracted to temporary folder, they
238 // have to look like they originate from the source folder
239 baseSourceLocation = URIUtil.toUnencodedString(fBaseSourceContainerPath.toFile().getCanonicalFile().toURI());
240 }
241
242 /*
243 * Import extracted files that are now in the temporary folder, if any
244 */
245
246 // We need to update the source container path because the
247 // "preserve folder structure" option would create the
248 // wrong trace folders otherwise.
249 fBaseSourceContainerPath = destTempFolder.getLocation();
250 List<TraceFileSystemElement> tempFolderFileSystemElements = createElementsForFolder(destTempFolder);
251 if (!tempFolderFileSystemElements.isEmpty()) {
252 calculateSourceLocations(tempFolderFileSystemElements, baseSourceLocation);
253 // Never import extracted files as links, they would link to the
254 // temporary directory that will be deleted
255 fImportOptionFlags = fImportOptionFlags & ~ImportTraceWizardPage.OPTION_CREATE_LINKS_IN_WORKSPACE;
256 SubMonitor importTempMonitor = subMonitor.newChild(EXTRA_IMPORT_OPERATION_PROGRESS);
257 importFileSystemElements(importTempMonitor, tempFolderFileSystemElements);
258 }
259
260 if (destTempFolder.exists()) {
261 destTempFolder.delete(true, subMonitor.newChild(TOTAL_PROGRESS));
262 }
263
264 setStatus(Status.OK_STATUS);
265 } catch (InterruptedException e) {
266 setStatus(Status.CANCEL_STATUS);
267 } catch (Exception e) {
268 String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$
269 (fCurrentPath != null ? fCurrentPath : ""); //$NON-NLS-1$
270 Activator.getDefault().logError(errorMessage, e);
271 setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage, e));
272 }
273 }
274
275 /**
276 * Get the list of resources that were imported by this operation. An
277 * example use case would be to use this to open traces that were imported
278 * by this operation.
279 *
280 * Note this includes only valid traces and doesn'tinclude unrecognized
281 * files.
282 *
283 * @return the trace resources that were imported
284 */
285 public List<IResource> getImportedResources() {
286 return fImportedResources;
287 }
288
289 /**
290 * Import a collection of file system elements into the workspace.
291 */
292 private void importFileSystemElements(IProgressMonitor monitor, List<TraceFileSystemElement> fileSystemElements)
293 throws InterruptedException, TmfTraceImportException, CoreException, InvocationTargetException {
294 SubMonitor subMonitor = SubMonitor.convert(monitor, fileSystemElements.size());
295 // Sort the elements in a sensible order to make it more predictable to
296 // the user when there can be name clashes. Otherwise, the order can
297 // seem pretty random depending on the OS/Filesystem.
298 fileSystemElements.sort(new FileObjectPathComparator());
299
300 ListIterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.listIterator();
301
302 // Map to remember already imported directory traces
303 final Map<String, TraceFileSystemElement> directoryTraces = new HashMap<>();
304 while (fileSystemElementsIter.hasNext()) {
305 ModalContext.checkCanceled(monitor);
306 fCurrentPath = null;
307 TraceFileSystemElement element = fileSystemElementsIter.next();
308 IFileSystemObject fileSystemObject = element.getFileSystemObject();
309 String resourcePath = element.getFileSystemObject().getAbsolutePath();
310 element.setDestinationContainerPath(computeDestinationContainerPath(new Path(resourcePath)));
311
312 fCurrentPath = resourcePath;
313 SubMonitor sub = subMonitor.newChild(1);
314 if (element.isDirectory()) {
315 if (!directoryTraces.containsKey(resourcePath) && isDirectoryTrace(element)) {
316 directoryTraces.put(resourcePath, element);
317 validateAndImportTrace(element, sub);
318 }
319 } else {
320 TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
321 String parentPath = parentElement.getFileSystemObject().getAbsolutePath();
322 parentElement.setDestinationContainerPath(computeDestinationContainerPath(new Path(parentPath)));
323 fCurrentPath = parentPath;
324 if (!directoryTraces.containsKey(parentPath)) {
325 if (isDirectoryTrace(parentElement)) {
326 directoryTraces.put(parentPath, parentElement);
327 validateAndImportTrace(parentElement, sub);
328 } else {
329 boolean validateFile = true;
330 TraceFileSystemElement grandParentElement = (TraceFileSystemElement) parentElement.getParent();
331 // Special case for LTTng trace that may contain index
332 // directory and files
333 if (grandParentElement != null) {
334 String grandParentPath = grandParentElement.getFileSystemObject().getAbsolutePath();
335 grandParentElement.setDestinationContainerPath(computeDestinationContainerPath(new Path(parentPath)));
336 fCurrentPath = grandParentPath;
337 if (directoryTraces.containsKey(grandParentPath)) {
338 validateFile = false;
339 } else if (isDirectoryTrace(grandParentElement)) {
340 directoryTraces.put(grandParentPath, grandParentElement);
341 validateAndImportTrace(grandParentElement, sub);
342 validateFile = false;
343 }
344 }
345 if (validateFile && (fileSystemObject.exists())) {
346 validateAndImportTrace(element, sub);
347 }
348 }
349 }
350 }
351 }
352 }
353
354 /**
355 * Generate a new list of file system elements for the specified folder.
356 */
357 private static List<TraceFileSystemElement> createElementsForFolder(IFolder folder) {
358 // Create the new import provider and root element based on the
359 // specified folder
360 FileSystemObjectImportStructureProvider importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
361 IFileSystemObject rootElement = importStructureProvider.getIFileSystemObject(new File(folder.getLocation().toOSString()));
362 TraceFileSystemElement createRootElement = TraceFileSystemElement.createRootTraceFileElement(rootElement, importStructureProvider);
363 List<TraceFileSystemElement> list = new LinkedList<>();
364 createRootElement.getAllChildren(list);
365 return list;
366 }
367
368 /**
369 * Extract all file system elements (File) to destination folder (typically
370 * workspace/TraceProject/.traceImport)
371 */
372 private void extractAllArchiveFiles(List<TraceFileSystemElement> fileSystemElements, IFolder destFolder, IPath baseSourceContainerPath, IProgressMonitor progressMonitor) throws InterruptedException, CoreException, InvocationTargetException {
373 SubMonitor subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size());
374 ListIterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.listIterator();
375 while (fileSystemElementsIter.hasNext()) {
376 ModalContext.checkCanceled(subMonitor);
377
378 SubMonitor elementProgress = subMonitor.newChild(1);
379 TraceFileSystemElement element = fileSystemElementsIter.next();
380 File archiveFile = (File) element.getFileSystemObject().getRawFileSystemObject();
381 boolean isArchiveFileElement = element.getFileSystemObject() instanceof FileFileSystemObject && ArchiveUtil.isArchiveFile(archiveFile);
382 if (isArchiveFileElement) {
383 elementProgress = SubMonitor.convert(elementProgress, 4);
384 IPath makeAbsolute = baseSourceContainerPath.makeAbsolute();
385 IPath relativeToSourceContainer = new Path(element.getFileSystemObject().getAbsolutePath()).makeRelativeTo(makeAbsolute);
386 IFolder folder = safeCreateExtractedFolder(destFolder, relativeToSourceContainer, elementProgress.newChild(1));
387 extractArchiveToFolder(archiveFile, folder, elementProgress.newChild(1));
388
389 // Delete original archive, we don't want to import this, just
390 // the extracted content
391 IFile fileRes = destFolder.getFile(relativeToSourceContainer);
392 fileRes.delete(true, elementProgress.newChild(1));
393 IPath newPath = destFolder.getFullPath().append(relativeToSourceContainer);
394 // Rename extracted folder (.extract) to original archive name
395 folder.move(newPath, true, elementProgress.newChild(1));
396 folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(newPath);
397
398 // Create the new import provider and root element based on
399 // the newly extracted temporary folder
400 FileSystemObjectImportStructureProvider importStructureProvider = new FileSystemObjectImportStructureProvider(FileSystemStructureProvider.INSTANCE, null);
401 IFileSystemObject rootElement = importStructureProvider.getIFileSystemObject(new File(folder.getLocation().toOSString()));
402 TraceFileSystemElement newElement = TraceFileSystemElement.createRootTraceFileElement(rootElement, importStructureProvider);
403 List<TraceFileSystemElement> extractedChildren = new ArrayList<>();
404 newElement.getAllChildren(extractedChildren);
405 extractAllArchiveFiles(extractedChildren, folder, folder.getLocation(), progressMonitor);
406 }
407 }
408 }
409
410 /**
411 * Extract a file (File) to a destination folder
412 */
413 private void extractArchiveToFolder(File sourceFile, IFolder destinationFolder, IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException {
414 Pair<IFileSystemObject, FileSystemObjectImportStructureProvider> rootObjectAndProvider = ArchiveUtil.getRootObjectAndProvider(sourceFile, fShell);
415 TraceFileSystemElement rootElement = TraceFileSystemElement.createRootTraceFileElement(rootObjectAndProvider.getFirst(), rootObjectAndProvider.getSecond());
416 List<TraceFileSystemElement> fileSystemElements = new ArrayList<>();
417 rootElement.getAllChildren(fileSystemElements);
418 extractArchiveContent(fileSystemElements.listIterator(), destinationFolder, progressMonitor);
419 rootObjectAndProvider.getSecond().dispose();
420 }
421
422 /**
423 * Safely create a folder meant to receive extracted content by making sure
424 * there is no name clash.
425 */
426 private static IFolder safeCreateExtractedFolder(IFolder destinationFolder, IPath relativeContainerRelativePath, IProgressMonitor monitor) throws CoreException {
427 SubMonitor subMonitor = SubMonitor.convert(monitor, 2);
428 IFolder extractedFolder;
429 String suffix = ""; //$NON-NLS-1$
430 int i = 2;
431 while (true) {
432 IPath fullPath = destinationFolder.getFullPath().append(relativeContainerRelativePath + ".extract" + suffix); //$NON-NLS-1$
433 IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(fullPath);
434 if (!folder.exists()) {
435 extractedFolder = folder;
436 break;
437 }
438 suffix = "(" + i + ")"; //$NON-NLS-1$//$NON-NLS-2$
439 i++;
440 }
441 subMonitor.worked(1);
442
443 TraceUtils.createFolder(extractedFolder, subMonitor.newChild(1));
444 return extractedFolder;
445 }
446
447 private void calculateSourceLocations(List<TraceFileSystemElement> fileSystemElements, String baseSourceLocation) {
448 for (TraceFileSystemElement element : fileSystemElements) {
449 IPath tempRelative = new Path(element.getFileSystemObject().getAbsolutePath()).makeRelativeTo(fBaseSourceContainerPath);
450 String sourceLocation = baseSourceLocation + tempRelative;
451 element.setSourceLocation(sourceLocation);
452
453 TraceFileSystemElement parentElement = (TraceFileSystemElement) element.getParent();
454 tempRelative = new Path(parentElement.getFileSystemObject().getAbsolutePath()).makeRelativeTo(fBaseSourceContainerPath);
455 sourceLocation = baseSourceLocation + tempRelative + '/';
456 parentElement.setSourceLocation(sourceLocation);
457 }
458 }
459
460 /**
461 * Extract all file system elements (Tar, Zip elements) to destination
462 * folder (typically workspace/TraceProject/.traceImport or a subfolder of
463 * it)
464 */
465 private void extractArchiveContent(Iterator<TraceFileSystemElement> fileSystemElementsIter, IFolder tempFolder, IProgressMonitor progressMonitor) throws InterruptedException,
466 InvocationTargetException {
467 List<TraceFileSystemElement> subList = new ArrayList<>();
468 // Collect all the elements
469 while (fileSystemElementsIter.hasNext()) {
470 ModalContext.checkCanceled(progressMonitor);
471 TraceFileSystemElement element = fileSystemElementsIter.next();
472 if (element.isDirectory()) {
473 Object[] array = element.getFiles().getChildren();
474 for (int i = 0; i < array.length; i++) {
475 subList.add((TraceFileSystemElement) array[i]);
476 }
477 }
478 subList.add(element);
479 }
480
481 if (subList.isEmpty()) {
482 return;
483 }
484
485 TraceFileSystemElement root = getRootElement(subList.get(0));
486
487 ImportProvider fileSystemStructureProvider = new ImportProvider();
488
489 IOverwriteQuery myQueryImpl = new IOverwriteQuery() {
490 @Override
491 public String queryOverwrite(String file) {
492 return IOverwriteQuery.NO_ALL;
493 }
494 };
495
496 progressMonitor.setTaskName(Messages.ImportTraceWizard_ExtractImportOperationTaskName);
497 IPath containerPath = tempFolder.getFullPath();
498 ImportOperation operation = new ImportOperation(containerPath, root, fileSystemStructureProvider, myQueryImpl, subList);
499 operation.setContext(fShell);
500
501 operation.setCreateContainerStructure(true);
502 operation.setOverwriteResources(false);
503 operation.setVirtualFolders(false);
504
505 operation.run(SubMonitor.convert(progressMonitor).newChild(subList.size()));
506 }
507
508 private static TraceFileSystemElement getRootElement(TraceFileSystemElement element) {
509 TraceFileSystemElement root = element;
510 while (root.getParent() != null) {
511 root = (TraceFileSystemElement) root.getParent();
512 }
513 return root;
514 }
515
516 private IPath computeDestinationContainerPath(Path resourcePath) {
517 IPath destinationContainerPath = fDestinationContainerPath;
518
519 // We need to figure out the new destination path relative to the
520 // selected "base" source directory.
521 // Here for example, the selected source directory is /home/user
522 if ((fImportOptionFlags & ImportTraceWizardPage.OPTION_PRESERVE_FOLDER_STRUCTURE) != 0) {
523 // /home/user/bar/foo/trace -> /home/user/bar/foo
524 IPath sourceContainerPath = resourcePath.removeLastSegments(1);
525 if (fBaseSourceContainerPath.equals(resourcePath)) {
526 // Use resourcePath directory if fBaseSourceContainerPath
527 // points to a directory trace
528 sourceContainerPath = resourcePath;
529 }
530 // /home/user/bar/foo, /home/user -> bar/foo
531 IPath relativeContainerPath = sourceContainerPath.makeRelativeTo(fBaseSourceContainerPath);
532 // project/Traces + bar/foo -> project/Traces/bar/foo
533 destinationContainerPath = fDestinationContainerPath.append(relativeContainerPath);
534 }
535 return destinationContainerPath;
536 }
537
538 /**
539 * Import a single file system element into the workspace.
540 */
541 private void validateAndImportTrace(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor)
542 throws TmfTraceImportException, CoreException, InvocationTargetException, InterruptedException {
543 String path = fileSystemElement.getFileSystemObject().getAbsolutePath();
544 TraceTypeHelper traceTypeHelper = null;
545
546 File file = (File) fileSystemElement.getFileSystemObject().getRawFileSystemObject();
547 boolean isArchiveFileElement = fileSystemElement.getFileSystemObject() instanceof FileFileSystemObject && ArchiveUtil.isArchiveFile(file);
548 if (isArchiveFileElement) {
549 // We'll be extracting this later, do not import as a trace
550 return;
551 }
552
553 if (fTraceType == null) {
554 // Auto Detection
555 try {
556 traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(path, null, null);
557 } catch (TmfTraceImportException e) {
558 // the trace did not match any trace type
559 }
560 if (traceTypeHelper == null) {
561 if ((fImportOptionFlags & ImportTraceWizardPage.OPTION_IMPORT_UNRECOGNIZED_TRACES) != 0) {
562 importResource(fileSystemElement, monitor);
563 }
564 return;
565 }
566 } else {
567 boolean isDirectoryTraceType = TmfTraceType.isDirectoryTraceType(fTraceType);
568 if (fileSystemElement.isDirectory() != isDirectoryTraceType) {
569 return;
570 }
571 traceTypeHelper = TmfTraceType.getTraceType(fTraceType);
572
573 if (traceTypeHelper == null) {
574 // Trace type not found
575 throw new TmfTraceImportException(Messages.ImportTraceWizard_TraceTypeNotFound);
576 }
577
578 if (!traceTypeHelper.validate(path).isOK()) {
579 // Trace type exist but doesn't validate for given trace.
580 return;
581 }
582 }
583
584 // Finally import trace
585 IResource importedResource = importResource(fileSystemElement, monitor);
586 if (importedResource != null) {
587 TmfTraceTypeUIUtils.setTraceType(importedResource, traceTypeHelper, false);
588 fImportedResources.add(importedResource);
589 }
590
591 }
592
593 /**
594 * Imports a trace resource to project. In case of name collision the user
595 * will be asked to confirm overwriting the existing trace, overwriting or
596 * skipping the trace to be imported.
597 *
598 * @param fileSystemElement
599 * trace file system object to import
600 * @param monitor
601 * a progress monitor
602 * @return the imported resource or null if no resource was imported
603 *
604 * @throws InvocationTargetException
605 * if problems during import operation
606 * @throws InterruptedException
607 * if cancelled
608 * @throws CoreException
609 * if problems with workspace
610 */
611 private IResource importResource(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor)
612 throws InvocationTargetException, InterruptedException, CoreException {
613
614 IPath tracePath = getInitialDestinationPath(fileSystemElement);
615 String newName = fConflictHandler.checkAndHandleNameClash(tracePath, monitor);
616
617 if (newName == null) {
618 return null;
619 }
620 fileSystemElement.setLabel(newName);
621
622 List<TraceFileSystemElement> subList = new ArrayList<>();
623
624 FileSystemElement parentFolder = fileSystemElement.getParent();
625
626 IPath containerPath = fileSystemElement.getDestinationContainerPath();
627 tracePath = containerPath.addTrailingSeparator().append(fileSystemElement.getLabel());
628 boolean createLinksInWorkspace = (fImportOptionFlags & ImportTraceWizardPage.OPTION_CREATE_LINKS_IN_WORKSPACE) != 0;
629 if (fileSystemElement.isDirectory() && !createLinksInWorkspace) {
630 containerPath = tracePath;
631
632 Object[] array = fileSystemElement.getFiles().getChildren();
633 for (int i = 0; i < array.length; i++) {
634 subList.add((TraceFileSystemElement) array[i]);
635 }
636 parentFolder = fileSystemElement;
637
638 } else {
639 if (!fileSystemElement.isDirectory()) {
640 // File traces
641 IFileInfo info = EFS.getStore(new File(fileSystemElement.getFileSystemObject().getAbsolutePath()).toURI()).fetchInfo();
642 if (info.getLength() == 0) {
643 // Don't import empty traces
644 return null;
645 }
646 }
647 subList.add(fileSystemElement);
648 }
649
650 ImportProvider fileSystemStructureProvider = new ImportProvider();
651
652 IOverwriteQuery myQueryImpl = new IOverwriteQuery() {
653 @Override
654 public String queryOverwrite(String file) {
655 return IOverwriteQuery.NO_ALL;
656 }
657 };
658
659 monitor.setTaskName(Messages.ImportTraceWizard_ImportOperationTaskName + " " + fileSystemElement.getFileSystemObject().getAbsolutePath()); //$NON-NLS-1$
660 ImportOperation operation = new ImportOperation(containerPath, parentFolder, fileSystemStructureProvider, myQueryImpl, subList);
661 operation.setContext(fShell);
662
663 operation.setCreateContainerStructure(false);
664 operation.setOverwriteResources(false);
665 operation.setCreateLinks(createLinksInWorkspace);
666 operation.setVirtualFolders(false);
667
668 operation.run(SubMonitor.convert(monitor).newChild(1));
669 String sourceLocation = fileSystemElement.getSourceLocation();
670 IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(tracePath);
671 if ((sourceLocation != null) && (resource != null)) {
672 resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
673 }
674
675 return resource;
676 }
677
678 private static boolean isDirectoryTrace(TraceFileSystemElement fileSystemElement) {
679 String path = fileSystemElement.getFileSystemObject().getAbsolutePath();
680 if (TmfTraceType.isDirectoryTrace(path)) {
681 return true;
682 }
683 return false;
684 }
685
686 /**
687 * @return the initial destination path, before rename, if any
688 */
689 private static IPath getInitialDestinationPath(TraceFileSystemElement fileSystemElement) {
690 IPath traceFolderPath = fileSystemElement.getDestinationContainerPath();
691 return traceFolderPath.append(fileSystemElement.getFileSystemObject().getName());
692 }
693
694 /**
695 * Set the status for this operation
696 *
697 * @param status
698 * the status
699 */
700 private void setStatus(IStatus status) {
701 fStatus = status;
702 }
703
704 /**
705 * Get the resulting status of this operation. Clients can use this for
706 * error reporting, etc.
707 *
708 * @return the resulting status
709 */
710 public IStatus getStatus() {
711 return fStatus;
712 }
713
714 private class ImportProvider implements IImportStructureProvider {
715
716 ImportProvider() {
717 }
718
719 @Override
720 public String getLabel(Object element) {
721 TraceFileSystemElement resource = (TraceFileSystemElement) element;
722 return resource.getLabel();
723 }
724
725 @Override
726 public List getChildren(Object element) {
727 TraceFileSystemElement resource = (TraceFileSystemElement) element;
728 return Arrays.asList(resource.getFiles().getChildren());
729 }
730
731 @Override
732 public InputStream getContents(Object element) {
733 TraceFileSystemElement resource = (TraceFileSystemElement) element;
734 return resource.getProvider().getContents(resource.getFileSystemObject());
735 }
736
737 @Override
738 public String getFullPath(Object element) {
739 TraceFileSystemElement resource = (TraceFileSystemElement) element;
740 return resource.getProvider().getFullPath(resource.getFileSystemObject());
741 }
742
743 @Override
744 public boolean isFolder(Object element) {
745 TraceFileSystemElement resource = (TraceFileSystemElement) element;
746 return resource.isDirectory();
747 }
748 }
749
750 /**
751 * Sets the conflict handler
752 *
753 * @param conflictHandler
754 * the conflict handler
755 */
756 public void setConflictHandler(ImportConflictHandler conflictHandler) {
757 fConflictHandler = conflictHandler;
758 }
759 }
This page took 0.09488 seconds and 5 git commands to generate.