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