diff options
Diffstat (limited to 'lttng/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java')
-rw-r--r-- | lttng/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java | 699 |
1 files changed, 699 insertions, 0 deletions
diff --git a/lttng/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java b/lttng/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java new file mode 100644 index 0000000000..4f940518e7 --- /dev/null +++ b/lttng/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/wizards/importtrace/BatchImportTraceWizard.java @@ -0,0 +1,699 @@ +/******************************************************************************* + * Copyright (c) 2013, 2014 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: + * Matthew Khouzam - Initial API and implementation + * Marc-Andre Laperle - Log some exceptions + * Patrick Tasse - Add support for source location + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.tmf.ui.project.wizards.importtrace; + +import java.io.File; +import java.io.FileInputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.BlockingQueue; + +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.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.linuxtools.internal.tmf.ui.Activator; +import org.eclipse.linuxtools.internal.tmf.ui.project.model.TmfImportHelper; +import org.eclipse.linuxtools.tmf.core.TmfCommonConstants; +import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType; +import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper; +import org.eclipse.linuxtools.tmf.core.project.model.TraceValidationHelper; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceTypeUIUtils; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.dialogs.IOverwriteQuery; +import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; +import org.eclipse.ui.wizards.datatransfer.ImportOperation; + +/** + * Batch Import trace wizard. + * + * @author Matthew Khouzam + * @since 2.0 + */ +public class BatchImportTraceWizard extends ImportTraceWizard { + + private static final int WIN_HEIGHT = 400; + private static final int WIN_WIDTH = 800; + private static final Status CANCEL_STATUS = new Status(IStatus.CANCEL, Activator.PLUGIN_ID, ""); //$NON-NLS-1$ + private static final int TOTALWORK = 65536; + // ----------------- + // Constants + // ----------------- + + private static final int MAX_FILES = TOTALWORK - 1; + private static final String BATCH_IMPORT_WIZARD = "BatchImportTraceWizard"; //$NON-NLS-1$ + + // ------------------ + // Fields + // ------------------ + + private IWizardPage fSelectDirectoriesPage; + private ImportTraceWizardScanPage fScanPage; + private IWizardPage fSelectTypePage; + private IWizardPage fOptions; + + private final List<String> fTraceTypesToScan = new ArrayList<>(); + private final Set<String> fParentFilesToScan = new HashSet<>(); + + private ImportTraceContentProvider fScannedTraces = new ImportTraceContentProvider(fTraceTypesToScan, fParentFilesToScan); + + private final Map<TraceValidationHelper, Boolean> fResults = new HashMap<>(); + private boolean fOverwrite = true; + private boolean fLinked = true; + + private BlockingQueue<TraceValidationHelper> fTracesToScan; + private final Set<FileAndName> fTraces = new TreeSet<>(); + + private Map<String, Set<String>> fParentFiles = new HashMap<>(); + + // Target import directory (trace folder) + private IFolder fTargetFolder; + + /** + * Returns the ScannedTraces model + * + * @return the ScannedTraces model + */ + public ImportTraceContentProvider getScannedTraces() { + return fScannedTraces; + } + + /** + * Constructor + */ + public BatchImportTraceWizard() { + IDialogSettings workbenchSettings = Activator.getDefault().getDialogSettings(); + IDialogSettings section = workbenchSettings.getSection(BATCH_IMPORT_WIZARD); + if (section == null) { + section = workbenchSettings.addNewSection(BATCH_IMPORT_WIZARD); + } + setDialogSettings(section); + setNeedsProgressMonitor(true); + } + + @Override + public void init(IWorkbench workbench, IStructuredSelection selection) { + + fSelectDirectoriesPage = new ImportTraceWizardSelectDirectoriesPage(workbench, selection); + fScanPage = new ImportTraceWizardScanPage(workbench, selection); + fSelectTypePage = new ImportTraceWizardSelectTraceTypePage(workbench, selection); + fOptions = new ImportTraceWizardPageOptions(workbench, selection); + // keep in case it's called later + Iterator<?> iter = selection.iterator(); + while (iter.hasNext()) { + Object selected = iter.next(); + if (selected instanceof TmfTraceFolder) { + fTargetFolder = ((TmfTraceFolder) selected).getResource(); + break; + } + } + fResults.clear(); + } + + @Override + public void addPages() { + addPage(fSelectTypePage); + addPage(fSelectDirectoriesPage); + addPage(fScanPage); + addPage(fOptions); + final WizardDialog container = (WizardDialog) getContainer(); + if (container != null) { + container.setPageSize(WIN_WIDTH, WIN_HEIGHT); + } + } + + /** + * Add a file to scan + * + * @param fileName + * the file to scan + */ + public void addFileToScan(final String fileName) { + String absolutePath = new File(fileName).getAbsolutePath(); + if (!fParentFiles.containsKey(absolutePath)) { + fParentFiles.put(absolutePath, new HashSet<String>()); + startUpdateTask(Messages.BatchImportTraceWizardAdd + ' ' + absolutePath, absolutePath); + + } + + } + + /** + * Remove files from selection + * + * @param fileName + * the name of the file to remove + */ + public void removeFile(final String fileName) { + fParentFiles.remove(fileName); + fParentFilesToScan.remove(fileName); + startUpdateTask(Messages.BatchImportTraceWizardRemove + ' ' + fileName, null); + } + + private void startUpdateTask(final String taskName, final String fileAbsolutePath) { + try { + this.getContainer().run(true, true, new IRunnableWithProgress() { + + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + synchronized (BatchImportTraceWizard.this) { // this should + // only run one + // at a time + SubMonitor sm; + sm = SubMonitor.convert(monitor); + sm.setTaskName(taskName); + sm.setWorkRemaining(TOTALWORK); + updateFiles(sm, fileAbsolutePath); + sm.done(); + } + } + }); + } catch (InvocationTargetException e) { + Activator.getDefault().logError(Messages.ImportTraceWizardImportProblem, e); + } catch (InterruptedException e) { + } + } + + /** + * The set of names of the selected files + * + * @return the set of names of the selected files + */ + public Set<String> getFileNames() { + return fParentFilesToScan; + } + + /** + * Reset the trace list to import + */ + public void clearTraces() { + fTraces.clear(); + } + + @Override + public boolean performFinish() { + if (fTraces.isEmpty()) { + return false; + } + // if this turns out to be too slow, put in a progress monitor. Does not + // appear to be slow for the moment. + boolean success = importTraces(); + return success; + } + + private boolean importTraces() { + boolean success = false; + IOverwriteQuery overwriteQuery = new IOverwriteQuery() { + @Override + public String queryOverwrite(String file) { + return fOverwrite ? IOverwriteQuery.ALL : IOverwriteQuery.NO_ALL; + } + }; + FileSystemStructureProvider fileSystemStructureProvider = FileSystemStructureProvider.INSTANCE; + + for (FileAndName traceToImport : fTraces) { + try { + if (fLinked) { + if (TmfImportHelper.createLink(fTargetFolder, Path.fromOSString(traceToImport.getFile().getAbsolutePath()), traceToImport.getName()) == null) { + success = false; + } + else { + success = setTraceTypeAndSourceLocation(traceToImport).isOK(); + } + } + else { + List<File> subList = new ArrayList<>(); + IPath path = fTargetFolder.getFullPath(); + File parentFile = traceToImport.getFile(); + final boolean isFile = parentFile.isFile(); + if (isFile) { + IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path.append(traceToImport.getName())); + if (fOverwrite || !resource.exists()) { + subList.add(parentFile); + parentFile = parentFile.getParentFile(); + try (final FileInputStream source = new FileInputStream(traceToImport.getFile());) { + if (resource.exists()) { + resource.delete(IResource.FORCE, new NullProgressMonitor()); + } + resource.create(source, true, new NullProgressMonitor()); + } + setTraceTypeAndSourceLocation(traceToImport); + success = true; + } + } else { + path = path.addTrailingSeparator().append(traceToImport.getName()); + // Add all files in trace directory + File[] fileList = traceToImport.getFile().listFiles(); + for (File child : fileList) { + subList.add(child); + } + + Collections.sort(subList, new Comparator<File>() { + @Override + public int compare(File o1, File o2) { + return o1.getAbsolutePath().compareTo(o2.getAbsolutePath()); + } + }); + ImportOperation operation = new ImportOperation( + path, + parentFile, + fileSystemStructureProvider, + overwriteQuery, + subList); + operation.setContext(getShell()); + operation.setCreateContainerStructure(false); + if (executeImportOperation(operation)) { + setTraceTypeAndSourceLocation(traceToImport); + success = true; + } + } + + } + } catch (Exception e) { + } + } + return success; + } + + private IStatus setTraceTypeAndSourceLocation(FileAndName traceToImport) { + IStatus status = Status.OK_STATUS; + IResource resource = fTargetFolder.findMember(traceToImport.getName()); + if (resource != null) { + try { + // Set the trace type for this resource + String traceTypeId = traceToImport.getTraceTypeId(); + TraceTypeHelper traceType = TmfTraceType.getInstance().getTraceType(traceTypeId); + if (traceType != null) { + status = TmfTraceTypeUIUtils.setTraceType(resource, traceType); + } + + // Set the source location for this resource + File file = traceToImport.getFile(); + String sourceLocation = null; + IResource sourceResource; + if (file.isDirectory()) { + sourceResource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(Path.fromOSString(file.getAbsolutePath())); + } else { + sourceResource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(file.getAbsolutePath())); + } + if (sourceResource != null && sourceResource.exists()) { + sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION); + } + if (sourceLocation == null) { + sourceLocation = URIUtil.toUnencodedString(file.toURI()); + } + resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation); + } catch (CoreException e) { + Activator.getDefault().logError(Messages.BatchImportTraceWizardErrorImportingTraceResource + + ' ' + resource.getName(), e); + } + } + return status; + } + + @Override + public boolean canFinish() { + return super.canFinish() && hasTracesToImport() && !hasConflicts() && (fTargetFolder != null); + } + + /** + * Returns if a trace to import is selected + * + * @return if there are traces to import + */ + public boolean hasTracesToImport() { + return fTraces.size() > 0; + } + + /** + * Reset the files to scan + */ + public void clearFilesToScan() { + fTracesToScan.clear(); + } + + /** + * Set the trace types to scan + * + * @param tracesToScan + * a list of trace types to scan for + */ + public void setTraceTypesToScan(List<String> tracesToScan) { + // intersection to know if there's a diff. + // if there's a diff, we need to re-enque everything + List<String> added = new ArrayList<>(); + for (String traceLoc : tracesToScan) { + if (!fTraceTypesToScan.contains(traceLoc)) { + added.add(traceLoc); + } + } + fTraceTypesToScan.clear(); + fTraceTypesToScan.addAll(tracesToScan); + updateTracesToScan(added); + } + + /** + * Get the trace types to scan + * + * @return a list of traces to Scan for + */ + public List<String> getTraceTypesToScan() { + return fTraceTypesToScan; + } + + /** + * Add files to Import + * + * @param element + * add the file and tracetype to import + */ + public void addFileToImport(FileAndName element) { + fTraces.add(element); + updateConflicts(); + } + + /** + * Remove the file to scan + * + * @param element + * the element to remove + */ + public void removeFileToImport(FileAndName element) { + fTraces.remove(element); + element.setConflictingName(false); + updateConflicts(); + } + + /** + * Updates the trace to see if there are conflicts. + */ + public void updateConflicts() { + final FileAndName[] fChildren = fTraces.toArray(new FileAndName[0]); + for (int i = 0; i < fChildren.length; i++) { + fChildren[i].setConflictingName(false); + } + for (int i = 1; i < fChildren.length; i++) { + for (int j = 0; j < i; j++) { + if (fChildren[i].getName().equals(fChildren[j].getName())) { + fChildren[i].setConflictingName(true); + fChildren[j].setConflictingName(true); + } + } + } + getContainer().updateButtons(); + } + + /** + * Is there a name conflict + */ + boolean hasConflicts() { + boolean conflict = false; + for (FileAndName child : fTraces) { + conflict |= child.isConflictingName(); + } + return conflict; + } + + private boolean executeImportOperation(ImportOperation op) { + initializeOperation(op); + + try { + getContainer().run(true, true, op); + } catch (InterruptedException e) { + return false; + } catch (InvocationTargetException e) { + Activator.getDefault().logError(Messages.ImportTraceWizardImportProblem, e); + return false; + } + + IStatus status = op.getStatus(); + if (!status.isOK()) { + ErrorDialog.openError(getContainer().getShell(), Messages.ImportTraceWizardImportProblem, null, status); + return false; + } + + return true; + } + + private static void initializeOperation(ImportOperation op) { + op.setCreateContainerStructure(false); + op.setOverwriteResources(false); + op.setVirtualFolders(false); + } + + /** + * Override existing resources + * + * @param selection + * true or false + */ + public void setOverwrite(boolean selection) { + fOverwrite = selection; + } + + /** + * Is the trace linked? + * + * @param isLink + * true or false + */ + public void setLinked(boolean isLink) { + fLinked = isLink; + } + + /** + * @param tracesToScan + * sets the common traces to scan + */ + public void setTracesToScan(BlockingQueue<TraceValidationHelper> tracesToScan) { + fTracesToScan = tracesToScan; + } + + /** + * @param traceToScan + * The trace to scan + * @return if the trace has been scanned yet or not + * @since 3.0 + */ + public boolean hasScanned(TraceValidationHelper traceToScan) { + return fResults.containsKey(traceToScan); + } + + /** + * Add a result to a cache + * + * @param traceToScan + * The trace that has been scanned + * @param validate + * if the trace is valid + * @since 3.0 + */ + public void addResult(TraceValidationHelper traceToScan, boolean validate) { + fResults.put(traceToScan, validate); + } + + /** + * Gets if the trace has been scanned or not + * + * @param traceToScan + * the scanned trace + * @return whether it passes or not + * @since 3.0 + */ + public boolean getResult(TraceValidationHelper traceToScan) { + return fResults.get(traceToScan); + } + + /** + * Returns the amount of files scanned + * + * @return the amount of files scanned + */ + public int getNumberOfResults() { + return fResults.size(); + } + + private void updateTracesToScan(final List<String> added) { + // Treeset is used instead of a hashset since the traces should be read + // in the order they were added. + final Set<String> filesToScan = new TreeSet<>(); + for (String name : fParentFiles.keySet()) { + filesToScan.addAll(fParentFiles.get(name)); + } + IProgressMonitor pm = new NullProgressMonitor(); + try { + updateScanQueue(pm, filesToScan, added); + } catch (InterruptedException e) { + } + + } + + /* + * I am a job. Make me work + */ + private synchronized IStatus updateFiles(IProgressMonitor monitor, String traceToScanAbsPath) { + final Set<String> filesToScan = new TreeSet<>(); + + int workToDo = 1; + for (String name : fParentFiles.keySet()) { + + final File file = new File(name); + final File[] listFiles = file.listFiles(); + if (listFiles != null) { + workToDo += listFiles.length; + } + } + int step = TOTALWORK / workToDo; + try { + for (String name : fParentFiles.keySet()) { + final File fileToAdd = new File(name); + final Set<String> parentFilesToScan = fParentFiles.get(fileToAdd.getAbsolutePath()); + recurse(parentFilesToScan, fileToAdd, monitor, step); + if (monitor.isCanceled()) { + fParentFilesToScan.remove(traceToScanAbsPath); + fParentFiles.remove(traceToScanAbsPath); + return CANCEL_STATUS; + } + } + filesToScan.clear(); + for (String name : fParentFiles.keySet()) { + filesToScan.addAll(fParentFiles.get(name)); + fParentFilesToScan.add(name); + } + IStatus cancelled = updateScanQueue(monitor, filesToScan, fTraceTypesToScan); + if (cancelled.matches(IStatus.CANCEL)) { + fParentFilesToScan.remove(traceToScanAbsPath); + fParentFiles.remove(traceToScanAbsPath); + } + } catch (InterruptedException e) { + monitor.done(); + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e); + } + + monitor.done(); + return Status.OK_STATUS; + } + + private IStatus updateScanQueue(IProgressMonitor monitor, final Set<String> filesToScan, final List<String> traceTypes) throws InterruptedException { + for (String fileToScan : filesToScan) { + for (String traceCat : traceTypes) { + TraceValidationHelper tv = new TraceValidationHelper(fileToScan, traceCat); + // for thread safety, keep checks in this order. + if (!fResults.containsKey(tv)) { + if (!fTracesToScan.contains(tv)) { + fTracesToScan.put(tv); + monitor.subTask(tv.getTraceToScan()); + if (monitor.isCanceled()) { + fScanPage.refresh(); + return CANCEL_STATUS; + } + } + } + } + } + fScanPage.refresh(); + return Status.OK_STATUS; + } + + private IStatus recurse(Set<String> filesToScan, File fileToAdd, IProgressMonitor monitor, int step) { + final String absolutePath = fileToAdd.getAbsolutePath(); + if (!filesToScan.contains(absolutePath) && (filesToScan.size() < MAX_FILES)) { + filesToScan.add(absolutePath); + final File[] listFiles = fileToAdd.listFiles(); + if (null != listFiles) { + for (File child : listFiles) { + monitor.subTask(child.getName()); + if (monitor.isCanceled()) { + return CANCEL_STATUS; + } + IStatus retVal = recurse(filesToScan, child, monitor); + if (retVal.matches(IStatus.CANCEL)) { + return retVal; + } + monitor.worked(step); + } + } + } + return Status.OK_STATUS; + } + + private IStatus recurse(Set<String> filesToScan, File fileToAdd, IProgressMonitor monitor) { + final String absolutePath = fileToAdd.getAbsolutePath(); + if (!filesToScan.contains(absolutePath) && (filesToScan.size() < MAX_FILES)) { + filesToScan.add(absolutePath); + final File[] listFiles = fileToAdd.listFiles(); + if (null != listFiles) { + for (File child : listFiles) { + if (monitor.isCanceled()) { + return CANCEL_STATUS; + } + IStatus retVal = recurse(filesToScan, child, monitor); + if (retVal.matches(IStatus.CANCEL)) { + return retVal; + } + } + } + } + return Status.OK_STATUS; + } + + /** + * Gets the folder in the resource (project) + * + * @param targetFolder + * the folder to import to + */ + public void setTraceFolder(IFolder targetFolder) { + fTargetFolder = targetFolder; + if (this.getContainer() != null && this.getContainer().getCurrentPage() != null) { + this.getContainer().updateButtons(); + } + } + + /** + * Gets the target folder + * + * @return the target folder + */ + public IFolder getTargetFolder() { + return fTargetFolder; + } + +} |