Revert "tmf: Remove legacy import wizard"
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / project / wizards / importtrace / BatchImportTraceWizard.java
1 /*******************************************************************************
2 * Copyright (c) 2013 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 * Matthew Khouzam - Initial API and implementation
11 * Marc-Andre Laperle - Log some exceptions
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.tmf.ui.project.wizards.importtrace;
15
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.lang.reflect.InvocationTargetException;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.TreeSet;
29 import java.util.concurrent.BlockingQueue;
30
31 import org.eclipse.core.resources.IFile;
32 import org.eclipse.core.resources.IFolder;
33 import org.eclipse.core.resources.IResource;
34 import org.eclipse.core.resources.ResourcesPlugin;
35 import org.eclipse.core.runtime.CoreException;
36 import org.eclipse.core.runtime.IPath;
37 import org.eclipse.core.runtime.IProgressMonitor;
38 import org.eclipse.core.runtime.IStatus;
39 import org.eclipse.core.runtime.NullProgressMonitor;
40 import org.eclipse.core.runtime.Path;
41 import org.eclipse.core.runtime.Status;
42 import org.eclipse.core.runtime.SubMonitor;
43 import org.eclipse.jface.dialogs.ErrorDialog;
44 import org.eclipse.jface.dialogs.IDialogSettings;
45 import org.eclipse.jface.operation.IRunnableWithProgress;
46 import org.eclipse.jface.viewers.IStructuredSelection;
47 import org.eclipse.jface.wizard.IWizardPage;
48 import org.eclipse.jface.wizard.WizardDialog;
49 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
50 import org.eclipse.linuxtools.internal.tmf.ui.project.model.TmfImportHelper;
51 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
52 import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
53 import org.eclipse.linuxtools.tmf.core.project.model.TraceValidationHelper;
54 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
55 import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement;
56 import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectRegistry;
57 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
58 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
59 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceTypeUIUtils;
60 import org.eclipse.ui.IWorkbench;
61 import org.eclipse.ui.dialogs.IOverwriteQuery;
62 import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
63 import org.eclipse.ui.wizards.datatransfer.ImportOperation;
64
65 /**
66 * Batch Import trace wizard.
67 *
68 * @author Matthew Khouzam
69 * @since 2.0
70 */
71 public class BatchImportTraceWizard extends ImportTraceWizard {
72
73 private static final int WIN_HEIGHT = 400;
74 private static final int WIN_WIDTH = 800;
75 private static final Status CANCEL_STATUS = new Status(IStatus.CANCEL, Activator.PLUGIN_ID, ""); //$NON-NLS-1$
76 private static final int TOTALWORK = 65536;
77 // -----------------
78 // Constants
79 // -----------------
80
81 private static final int MAX_FILES = TOTALWORK - 1;
82 private static final String BATCH_IMPORT_WIZARD = "BatchImportTraceWizard"; //$NON-NLS-1$
83
84 // ------------------
85 // Fields
86 // ------------------
87
88 private IWizardPage fSelectDirectoriesPage;
89 private ImportTraceWizardScanPage fScanPage;
90 private IWizardPage fSelectTypePage;
91 private IWizardPage fOptions;
92
93 private final List<String> fTraceTypesToScan = new ArrayList<>();
94 private final Set<String> fParentFilesToScan = new HashSet<>();
95
96 private ImportTraceContentProvider fScannedTraces = new ImportTraceContentProvider(fTraceTypesToScan, fParentFilesToScan);
97
98 private final Map<TraceValidationHelper, Boolean> fResults = new HashMap<>();
99 private boolean fOverwrite = true;
100 private boolean fLinked = true;
101
102 private BlockingQueue<TraceValidationHelper> fTracesToScan;
103 private final Set<FileAndName> fTraces = new TreeSet<>();
104
105 private Map<String, Set<String>> fParentFiles = new HashMap<>();
106
107 // Target import directory ('Traces' folder)
108 private IFolder fTargetFolder;
109
110 /**
111 * Returns the ScannedTraces model
112 *
113 * @return the ScannedTraces model
114 */
115 public ImportTraceContentProvider getScannedTraces() {
116 return fScannedTraces;
117 }
118
119 /**
120 * Constructor
121 */
122 public BatchImportTraceWizard() {
123 IDialogSettings workbenchSettings = Activator.getDefault().getDialogSettings();
124 IDialogSettings section = workbenchSettings.getSection(BATCH_IMPORT_WIZARD);
125 if (section == null) {
126 section = workbenchSettings.addNewSection(BATCH_IMPORT_WIZARD);
127 }
128 setDialogSettings(section);
129 setNeedsProgressMonitor(true);
130 }
131
132 @Override
133 public void init(IWorkbench workbench, IStructuredSelection selection) {
134
135 fSelectDirectoriesPage = new ImportTraceWizardSelectDirectoriesPage(workbench, selection);
136 fScanPage = new ImportTraceWizardScanPage(workbench, selection);
137 fSelectTypePage = new ImportTraceWizardSelectTraceTypePage(workbench, selection);
138 fOptions = new ImportTraceWizardPageOptions(workbench, selection);
139 // keep in case it's called later
140 Iterator<?> iter = selection.iterator();
141 while (iter.hasNext()) {
142 Object selected = iter.next();
143 if (selected instanceof TmfTraceFolder) {
144 fTargetFolder = ((TmfTraceFolder) selected).getResource();
145 break;
146 }
147 }
148 fResults.clear();
149 }
150
151 @Override
152 public void addPages() {
153 addPage(fSelectTypePage);
154 addPage(fSelectDirectoriesPage);
155 addPage(fScanPage);
156 addPage(fOptions);
157 final WizardDialog container = (WizardDialog) getContainer();
158 if (container != null) {
159 container.setPageSize(WIN_WIDTH, WIN_HEIGHT);
160 }
161 }
162
163 /**
164 * Add a file to scan
165 *
166 * @param fileName
167 * the file to scan
168 */
169 public void addFileToScan(final String fileName) {
170 String absolutePath = new File(fileName).getAbsolutePath();
171 if (!fParentFiles.containsKey(absolutePath)) {
172 fParentFiles.put(absolutePath, new HashSet<String>());
173 startUpdateTask(Messages.BatchImportTraceWizardAdd + ' ' + absolutePath, absolutePath);
174
175 }
176
177 }
178
179 /**
180 * Remove files from selection
181 *
182 * @param fileName
183 * the name of the file to remove
184 */
185 public void removeFile(final String fileName) {
186 fParentFiles.remove(fileName);
187 fParentFilesToScan.remove(fileName);
188 startUpdateTask(Messages.BatchImportTraceWizardRemove + ' ' + fileName, null);
189 }
190
191 private void startUpdateTask(final String taskName, final String fileAbsolutePath) {
192 try {
193 this.getContainer().run(true, true, new IRunnableWithProgress() {
194
195 @Override
196 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
197 synchronized (BatchImportTraceWizard.this) { // this should
198 // only run one
199 // at a time
200 SubMonitor sm;
201 sm = SubMonitor.convert(monitor);
202 sm.setTaskName(taskName);
203 sm.setWorkRemaining(TOTALWORK);
204 updateFiles(sm, fileAbsolutePath);
205 sm.done();
206 }
207 }
208 });
209 } catch (InvocationTargetException e) {
210 Activator.getDefault().logError(Messages.ImportTraceWizardImportProblem, e);
211 } catch (InterruptedException e) {
212 }
213 }
214
215 /**
216 * The set of names of the selected files
217 *
218 * @return the set of names of the selected files
219 */
220 public Set<String> getFileNames() {
221 return fParentFilesToScan;
222 }
223
224 /**
225 * Reset the trace list to import
226 */
227 public void clearTraces() {
228 fTraces.clear();
229 }
230
231 @Override
232 public boolean performFinish() {
233 if (fTraces.isEmpty()) {
234 return false;
235 }
236 // if this turns out to be too slow, put in a progress monitor. Does not
237 // appear to be slow for the moment.
238 boolean success = importTraces();
239 return success;
240 }
241
242 private boolean importTraces() {
243 boolean success = false;
244 IOverwriteQuery overwriteQuery = new IOverwriteQuery() {
245 @Override
246 public String queryOverwrite(String file) {
247 return fOverwrite ? IOverwriteQuery.ALL : IOverwriteQuery.NO_ALL;
248 }
249 };
250 FileSystemStructureProvider fileSystemStructureProvider = FileSystemStructureProvider.INSTANCE;
251
252 for (FileAndName traceToImport : fTraces) {
253 try {
254 if (fLinked) {
255 if (TmfImportHelper.createLink(fTargetFolder, Path.fromOSString(traceToImport.getFile().getAbsolutePath()), traceToImport.getName()) == null) {
256 success = false;
257 }
258 else {
259 success = setTraceType(traceToImport).isOK();
260 }
261 }
262 else {
263 List<File> subList = new ArrayList<>();
264 IPath path = fTargetFolder.getFullPath();
265 File parentFile = traceToImport.getFile();
266 final boolean isFile = parentFile.isFile();
267 if (isFile) {
268 IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path.append(traceToImport.getName()));
269 if (fOverwrite || !resource.exists()) {
270 subList.add(parentFile);
271 parentFile = parentFile.getParentFile();
272 try (final FileInputStream source = new FileInputStream(traceToImport.getFile());) {
273 if (resource.exists()) {
274 resource.delete(IResource.FORCE, new NullProgressMonitor());
275 }
276 resource.create(source, true, new NullProgressMonitor());
277 }
278 setTraceType(traceToImport);
279 success = true;
280 }
281 } else {
282 // Add trace directory
283 subList.add(traceToImport.getFile());
284 // Add all files in trace directory
285 File[] fileList = traceToImport.getFile().listFiles();
286 for (File child : fileList) {
287 subList.add(child);
288 }
289
290 Collections.sort(subList, new Comparator<File>() {
291 @Override
292 public int compare(File o1, File o2) {
293 return o1.getAbsolutePath().compareTo(o2.getAbsolutePath());
294 }
295 });
296 ImportOperation operation = new ImportOperation(
297 path,
298 parentFile.getParentFile(),
299 fileSystemStructureProvider,
300 overwriteQuery,
301 subList);
302 operation.setContext(getShell());
303 operation.setCreateContainerStructure(false);
304 if (executeImportOperation(operation)) {
305 setTraceType(traceToImport);
306 success = true;
307 }
308 }
309
310 }
311 } catch (Exception e) {
312 }
313 }
314 return success;
315 }
316
317 private IStatus setTraceType(FileAndName traceToImport) {
318 IStatus validate = Status.OK_STATUS;
319 IPath path = fTargetFolder.getFullPath().append(traceToImport.getName());
320 IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
321 if (resource != null) {
322 try {
323 // Set the trace type for this resource
324 String traceTypeId = traceToImport.getTraceTypeId();
325 TraceTypeHelper traceType = TmfTraceType.getInstance().getTraceType(traceTypeId);
326 if (traceType != null) {
327 TmfTraceTypeUIUtils.setTraceType(path, traceType);
328 }
329
330 TmfProjectElement tmfProject =
331 TmfProjectRegistry.getProject(resource.getProject());
332 if (tmfProject != null) {
333 final TmfTraceFolder tracesFolder = tmfProject.getTracesFolder();
334
335 List<TmfTraceElement> traces = tracesFolder.getTraces();
336 boolean found = false;
337 for (TmfTraceElement traceElement : traces) {
338 if (traceElement.getName().equals(resource.getName())) {
339 traceElement.refreshTraceType();
340 found = true;
341 break;
342 }
343 }
344 if (!found) {
345 TmfTraceElement te = new TmfTraceElement(traceToImport.getName(), resource, tracesFolder);
346 te.refreshTraceType();
347 traces = tracesFolder.getTraces();
348 for (TmfTraceElement traceElement : traces) {
349 if (traceElement.getName().equals(resource.getName())) {
350 traceElement.refreshTraceType();
351 ITmfTrace tmfTrace = null;
352 try {
353 tmfTrace = traceElement.instantiateTrace();
354 if (tmfTrace != null) {
355 validate = tmfTrace.validate(tmfProject.getResource(), traceElement.getLocation().getPath());
356 } else {
357 return new Status(IStatus.ERROR, traceElement.getName(), "File does not exist : " + traceElement.getLocation().getPath()); //$NON-NLS-1$
358 }
359 } finally {
360 if (tmfTrace != null) {
361 tmfTrace.dispose();
362 }
363 }
364 break;
365 }
366 }
367
368 }
369
370 }
371 } catch (CoreException e) {
372 Activator.getDefault().logError(Messages.BatchImportTraceWizardErrorImportingTraceResource
373 + ' ' + resource.getName(), e);
374 }
375 }
376 return validate;
377 }
378
379 @Override
380 public boolean canFinish() {
381 return super.canFinish() && hasTracesToImport() && !hasConflicts() && (fTargetFolder != null);
382 }
383
384 /**
385 * Returns if a trace to import is selected
386 *
387 * @return if there are traces to import
388 */
389 public boolean hasTracesToImport() {
390 return fTraces.size() > 0;
391 }
392
393 /**
394 * Reset the files to scan
395 */
396 public void clearFilesToScan() {
397 fTracesToScan.clear();
398 }
399
400 /**
401 * Set the trace types to scan
402 *
403 * @param tracesToScan
404 * a list of trace types to scan for
405 */
406 public void setTraceTypesToScan(List<String> tracesToScan) {
407 // intersection to know if there's a diff.
408 // if there's a diff, we need to re-enque everything
409 List<String> added = new ArrayList<>();
410 for (String traceLoc : tracesToScan) {
411 if (!fTraceTypesToScan.contains(traceLoc)) {
412 added.add(traceLoc);
413 }
414 }
415 fTraceTypesToScan.clear();
416 fTraceTypesToScan.addAll(tracesToScan);
417 updateTracesToScan(added);
418 }
419
420 /**
421 * Get the trace types to scan
422 *
423 * @return a list of traces to Scan for
424 */
425 public List<String> getTraceTypesToScan() {
426 return fTraceTypesToScan;
427 }
428
429 /**
430 * Add files to Import
431 *
432 * @param element
433 * add the file and tracetype to import
434 */
435 public void addFileToImport(FileAndName element) {
436 fTraces.add(element);
437 updateConflicts();
438 }
439
440 /**
441 * Remove the file to scan
442 *
443 * @param element
444 * the element to remove
445 */
446 public void removeFileToImport(FileAndName element) {
447 fTraces.remove(element);
448 element.setConflictingName(false);
449 updateConflicts();
450 }
451
452 /**
453 * Updates the trace to see if there are conflicts.
454 */
455 public void updateConflicts() {
456 final FileAndName[] fChildren = fTraces.toArray(new FileAndName[0]);
457 for (int i = 0; i < fChildren.length; i++) {
458 fChildren[i].setConflictingName(false);
459 }
460 for (int i = 1; i < fChildren.length; i++) {
461 for (int j = 0; j < i; j++) {
462 if (fChildren[i].getName().equals(fChildren[j].getName())) {
463 fChildren[i].setConflictingName(true);
464 fChildren[j].setConflictingName(true);
465 }
466 }
467 }
468 getContainer().updateButtons();
469 }
470
471 /**
472 * Is there a name conflict
473 */
474 boolean hasConflicts() {
475 boolean conflict = false;
476 for (FileAndName child : fTraces) {
477 conflict |= child.isConflictingName();
478 }
479 return conflict;
480 }
481
482 private boolean executeImportOperation(ImportOperation op) {
483 initializeOperation(op);
484
485 try {
486 getContainer().run(true, true, op);
487 } catch (InterruptedException e) {
488 return false;
489 } catch (InvocationTargetException e) {
490 Activator.getDefault().logError(Messages.ImportTraceWizardImportProblem, e);
491 return false;
492 }
493
494 IStatus status = op.getStatus();
495 if (!status.isOK()) {
496 ErrorDialog.openError(getContainer().getShell(), Messages.ImportTraceWizardImportProblem, null, status);
497 return false;
498 }
499
500 return true;
501 }
502
503 private static void initializeOperation(ImportOperation op) {
504 op.setCreateContainerStructure(false);
505 op.setOverwriteResources(false);
506 op.setVirtualFolders(false);
507 }
508
509 /**
510 * Override existing resources
511 *
512 * @param selection
513 * true or false
514 */
515 public void setOverwrite(boolean selection) {
516 fOverwrite = selection;
517 }
518
519 /**
520 * Is the trace linked?
521 *
522 * @param isLink
523 * true or false
524 */
525 public void setLinked(boolean isLink) {
526 fLinked = isLink;
527 }
528
529 /**
530 * @param tracesToScan
531 * sets the common traces to scan
532 */
533 public void setTracesToScan(BlockingQueue<TraceValidationHelper> tracesToScan) {
534 fTracesToScan = tracesToScan;
535 }
536
537 /**
538 * @param traceToScan
539 * The trace to scan
540 * @return if the trace has been scanned yet or not
541 * @since 3.0
542 */
543 public boolean hasScanned(TraceValidationHelper traceToScan) {
544 return fResults.containsKey(traceToScan);
545 }
546
547 /**
548 * Add a result to a cache
549 *
550 * @param traceToScan
551 * The trace that has been scanned
552 * @param validate
553 * if the trace is valid
554 * @since 3.0
555 */
556 public void addResult(TraceValidationHelper traceToScan, boolean validate) {
557 fResults.put(traceToScan, validate);
558 }
559
560 /**
561 * Gets if the trace has been scanned or not
562 *
563 * @param traceToScan
564 * the scanned trace
565 * @return whether it passes or not
566 * @since 3.0
567 */
568 public Boolean getResult(TraceValidationHelper traceToScan) {
569 return fResults.get(traceToScan);
570 }
571
572 /**
573 * Returns the amount of files scanned
574 *
575 * @return the amount of files scanned
576 */
577 public int getNumberOfResults() {
578 return fResults.size();
579 }
580
581 private void updateTracesToScan(final List<String> added) {
582 // Treeset is used instead of a hashset since the traces should be read
583 // in the order they were added.
584 final Set<String> filesToScan = new TreeSet<>();
585 for (String name : fParentFiles.keySet()) {
586 filesToScan.addAll(fParentFiles.get(name));
587 }
588 IProgressMonitor pm = new NullProgressMonitor();
589 try {
590 updateScanQueue(pm, filesToScan, added);
591 } catch (InterruptedException e) {
592 }
593
594 }
595
596 /*
597 * I am a job. Make me work
598 */
599 private synchronized IStatus updateFiles(IProgressMonitor monitor, String traceToScanAbsPath) {
600 final Set<String> filesToScan = new TreeSet<>();
601
602 int workToDo = 1;
603 for (String name : fParentFiles.keySet()) {
604
605 final File file = new File(name);
606 final File[] listFiles = file.listFiles();
607 if (listFiles != null) {
608 workToDo += listFiles.length;
609 }
610 }
611 int step = TOTALWORK / workToDo;
612 try {
613 for (String name : fParentFiles.keySet()) {
614 final File fileToAdd = new File(name);
615 final Set<String> parentFilesToScan = fParentFiles.get(fileToAdd.getAbsolutePath());
616 recurse(parentFilesToScan, fileToAdd, monitor, step);
617 if (monitor.isCanceled()) {
618 fParentFilesToScan.remove(traceToScanAbsPath);
619 fParentFiles.remove(traceToScanAbsPath);
620 return CANCEL_STATUS;
621 }
622 }
623 filesToScan.clear();
624 for (String name : fParentFiles.keySet()) {
625 filesToScan.addAll(fParentFiles.get(name));
626 fParentFilesToScan.add(name);
627 }
628 IStatus cancelled = updateScanQueue(monitor, filesToScan, fTraceTypesToScan);
629 if (cancelled.matches(IStatus.CANCEL)) {
630 fParentFilesToScan.remove(traceToScanAbsPath);
631 fParentFiles.remove(traceToScanAbsPath);
632 }
633 } catch (InterruptedException e) {
634 monitor.done();
635 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
636 }
637
638 monitor.done();
639 return Status.OK_STATUS;
640 }
641
642 private IStatus updateScanQueue(IProgressMonitor monitor, final Set<String> filesToScan, final List<String> traceTypes) throws InterruptedException {
643 for (String fileToScan : filesToScan) {
644 for (String traceCat : traceTypes) {
645 TraceValidationHelper tv = new TraceValidationHelper(fileToScan, traceCat);
646 // for thread safety, keep checks in this order.
647 if (!fResults.containsKey(tv)) {
648 if (!fTracesToScan.contains(tv)) {
649 fTracesToScan.put(tv);
650 monitor.subTask(tv.getTraceToScan());
651 if (monitor.isCanceled()) {
652 fScanPage.refresh();
653 return CANCEL_STATUS;
654 }
655 }
656 }
657 }
658 }
659 fScanPage.refresh();
660 return Status.OK_STATUS;
661 }
662
663 private IStatus recurse(Set<String> filesToScan, File fileToAdd, IProgressMonitor monitor, int step) {
664 final String absolutePath = fileToAdd.getAbsolutePath();
665 if (!filesToScan.contains(absolutePath) && (filesToScan.size() < MAX_FILES)) {
666 filesToScan.add(absolutePath);
667 final File[] listFiles = fileToAdd.listFiles();
668 if (null != listFiles) {
669 for (File child : listFiles) {
670 monitor.subTask(child.getName());
671 if (monitor.isCanceled()) {
672 return CANCEL_STATUS;
673 }
674 IStatus retVal = recurse(filesToScan, child, monitor);
675 if (retVal.matches(IStatus.CANCEL)) {
676 return retVal;
677 }
678 monitor.worked(step);
679 }
680 }
681 }
682 return Status.OK_STATUS;
683 }
684
685 private IStatus recurse(Set<String> filesToScan, File fileToAdd, IProgressMonitor monitor) {
686 final String absolutePath = fileToAdd.getAbsolutePath();
687 if (!filesToScan.contains(absolutePath) && (filesToScan.size() < MAX_FILES)) {
688 filesToScan.add(absolutePath);
689 final File[] listFiles = fileToAdd.listFiles();
690 if (null != listFiles) {
691 for (File child : listFiles) {
692 if (monitor.isCanceled()) {
693 return CANCEL_STATUS;
694 }
695 IStatus retVal = recurse(filesToScan, child, monitor);
696 if (retVal.matches(IStatus.CANCEL)) {
697 return retVal;
698 }
699 }
700 }
701 }
702 return Status.OK_STATUS;
703 }
704
705 /**
706 * Gets the folder in the resource (project)
707 *
708 * @param targetFolder
709 * the folder to import to
710 */
711 public void setTraceFolder(IFolder targetFolder) {
712 fTargetFolder = targetFolder;
713 if (this.getContainer() != null && this.getContainer().getCurrentPage() != null) {
714 this.getContainer().updateButtons();
715 }
716 }
717
718 /**
719 * Gets the target folder
720 *
721 * @return the target folder
722 */
723 public IFolder getTargetFolder() {
724 return fTargetFolder;
725 }
726
727 }
This page took 0.051345 seconds and 5 git commands to generate.