| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2009, 2014 Ericsson and others. |
| 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 | * Francois Chouinard - Initial API and implementation |
| 11 | * Francois Chouinard - Got rid of dependency on internal platform class |
| 12 | * Francois Chouinard - Complete re-design |
| 13 | * Anna Dushistova(Montavista) - [383047] NPE while importing a CFT trace |
| 14 | * Matthew Khouzam - Moved out some common functions |
| 15 | * Patrick Tasse - Add sorting of file system elements |
| 16 | * Bernd Hufmann - Re-design of trace selection and trace validation |
| 17 | * Marc-Andre Laperle - Preserve folder structure on import |
| 18 | *******************************************************************************/ |
| 19 | |
| 20 | package org.eclipse.linuxtools.tmf.ui.project.wizards.importtrace; |
| 21 | |
| 22 | import java.io.File; |
| 23 | import java.io.InputStream; |
| 24 | import java.lang.reflect.InvocationTargetException; |
| 25 | import java.util.ArrayList; |
| 26 | import java.util.Collection; |
| 27 | import java.util.HashMap; |
| 28 | import java.util.Iterator; |
| 29 | import java.util.List; |
| 30 | import java.util.Map; |
| 31 | |
| 32 | import org.eclipse.core.resources.IContainer; |
| 33 | import org.eclipse.core.resources.IFolder; |
| 34 | import org.eclipse.core.resources.IProject; |
| 35 | import org.eclipse.core.resources.IResource; |
| 36 | import org.eclipse.core.resources.ResourcesPlugin; |
| 37 | import org.eclipse.core.runtime.CoreException; |
| 38 | import org.eclipse.core.runtime.IPath; |
| 39 | import org.eclipse.core.runtime.IProgressMonitor; |
| 40 | import org.eclipse.core.runtime.IStatus; |
| 41 | import org.eclipse.core.runtime.NullProgressMonitor; |
| 42 | import org.eclipse.core.runtime.Path; |
| 43 | import org.eclipse.core.runtime.Platform; |
| 44 | import org.eclipse.core.runtime.Status; |
| 45 | import org.eclipse.core.runtime.SubMonitor; |
| 46 | import org.eclipse.core.runtime.SubProgressMonitor; |
| 47 | import org.eclipse.core.runtime.URIUtil; |
| 48 | import org.eclipse.jface.dialogs.IDialogSettings; |
| 49 | import org.eclipse.jface.dialogs.MessageDialog; |
| 50 | import org.eclipse.jface.operation.IRunnableWithProgress; |
| 51 | import org.eclipse.jface.operation.ModalContext; |
| 52 | import org.eclipse.jface.viewers.IStructuredSelection; |
| 53 | import org.eclipse.jface.viewers.ITreeContentProvider; |
| 54 | import org.eclipse.linuxtools.internal.tmf.ui.Activator; |
| 55 | import org.eclipse.linuxtools.tmf.core.TmfCommonConstants; |
| 56 | import org.eclipse.linuxtools.tmf.core.TmfProjectNature; |
| 57 | import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceImportException; |
| 58 | import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType; |
| 59 | import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper; |
| 60 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement; |
| 61 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectRegistry; |
| 62 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement; |
| 63 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder; |
| 64 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceTypeUIUtils; |
| 65 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfTracesFolder; |
| 66 | import org.eclipse.linuxtools.tmf.ui.project.wizards.Messages; |
| 67 | import org.eclipse.osgi.util.NLS; |
| 68 | import org.eclipse.swt.SWT; |
| 69 | import org.eclipse.swt.custom.BusyIndicator; |
| 70 | import org.eclipse.swt.events.FocusEvent; |
| 71 | import org.eclipse.swt.events.FocusListener; |
| 72 | import org.eclipse.swt.events.KeyEvent; |
| 73 | import org.eclipse.swt.events.KeyListener; |
| 74 | import org.eclipse.swt.events.SelectionAdapter; |
| 75 | import org.eclipse.swt.events.SelectionEvent; |
| 76 | import org.eclipse.swt.layout.GridData; |
| 77 | import org.eclipse.swt.layout.GridLayout; |
| 78 | import org.eclipse.swt.widgets.Button; |
| 79 | import org.eclipse.swt.widgets.Combo; |
| 80 | import org.eclipse.swt.widgets.Composite; |
| 81 | import org.eclipse.swt.widgets.DirectoryDialog; |
| 82 | import org.eclipse.swt.widgets.Event; |
| 83 | import org.eclipse.swt.widgets.Group; |
| 84 | import org.eclipse.swt.widgets.Label; |
| 85 | import org.eclipse.ui.IWorkbench; |
| 86 | import org.eclipse.ui.dialogs.FileSystemElement; |
| 87 | import org.eclipse.ui.dialogs.IOverwriteQuery; |
| 88 | import org.eclipse.ui.dialogs.WizardResourceImportPage; |
| 89 | import org.eclipse.ui.internal.ide.dialogs.IElementFilter; |
| 90 | import org.eclipse.ui.model.AdaptableList; |
| 91 | import org.eclipse.ui.model.WorkbenchContentProvider; |
| 92 | import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; |
| 93 | import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider; |
| 94 | import org.eclipse.ui.wizards.datatransfer.ImportOperation; |
| 95 | |
| 96 | /** |
| 97 | * A variant of the standard resource import wizard for importing traces |
| 98 | * to given tracing project. If no project or tracing project was selected |
| 99 | * the wizard imports it to the default tracing project which is created |
| 100 | * if necessary. |
| 101 | * |
| 102 | * In our case traces could be files or a directory structure. This wizard |
| 103 | * supports both cases. It imports traces for a selected trace type or, if |
| 104 | * no trace type is selected, it tries to detect the trace type automatically. |
| 105 | * However, the automatic detection is a best-effort and cannot guarantee |
| 106 | * that the detection is successful. The reason for this is that there might |
| 107 | * be multiple trace types that can be assigned to a single trace. |
| 108 | * |
| 109 | * |
| 110 | * @author Francois Chouinard |
| 111 | * @since 2.0 |
| 112 | */ |
| 113 | @SuppressWarnings("restriction") |
| 114 | public class ImportTraceWizardPage extends WizardResourceImportPage { |
| 115 | |
| 116 | // ------------------------------------------------------------------------ |
| 117 | // Constants |
| 118 | // ------------------------------------------------------------------------ |
| 119 | private static final String IMPORT_WIZARD_PAGE = "ImportTraceWizardPage"; //$NON-NLS-1$ |
| 120 | private static final String IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID = IMPORT_WIZARD_PAGE + ".import_unrecognized_traces_id"; //$NON-NLS-1$ |
| 121 | private static final String SEPARATOR = ":"; //$NON-NLS-1$ |
| 122 | private static final String AUTO_DETECT = Messages.ImportTraceWizard_AutoDetection; |
| 123 | |
| 124 | // ------------------------------------------------------------------------ |
| 125 | // Attributes |
| 126 | // ------------------------------------------------------------------------ |
| 127 | |
| 128 | // Folder navigation start point (saved between invocations) |
| 129 | private static String fRootDirectory = null; |
| 130 | // Target import directory ('Traces' folder) |
| 131 | private IFolder fTargetFolder; |
| 132 | // Target Trace folder element |
| 133 | private TmfTraceFolder fTraceFolderElement; |
| 134 | // Flag to handle destination folder change event |
| 135 | private Boolean fIsDestinationChanged = false; |
| 136 | // Combo box containing trace types |
| 137 | private Combo fTraceTypes; |
| 138 | // Button to ignore unrecognized traces or not |
| 139 | private Button fImportUnrecognizedButton; |
| 140 | // Button to overwrite existing resources or not |
| 141 | private Button fOverwriteExistingResourcesCheckbox; |
| 142 | // Button to link or copy traces to workspace |
| 143 | private Button fCreateLinksInWorkspaceButton; |
| 144 | // Button to preserve folder structure |
| 145 | private Button fPreserveFolderStructureButton; |
| 146 | private boolean entryChanged = false; |
| 147 | /** The directory name field */ |
| 148 | protected Combo directoryNameField; |
| 149 | /** The directory browse button. */ |
| 150 | protected Button directoryBrowseButton; |
| 151 | |
| 152 | // ------------------------------------------------------------------------ |
| 153 | // Constructors |
| 154 | // ------------------------------------------------------------------------ |
| 155 | |
| 156 | /** |
| 157 | * Constructor. Creates the trace wizard page. |
| 158 | * |
| 159 | * @param name |
| 160 | * The name of the page. |
| 161 | * @param selection |
| 162 | * The current selection |
| 163 | */ |
| 164 | protected ImportTraceWizardPage(String name, IStructuredSelection selection) { |
| 165 | super(name, selection); |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * Constructor |
| 170 | * |
| 171 | * @param workbench |
| 172 | * The workbench reference. |
| 173 | * @param selection |
| 174 | * The current selection |
| 175 | */ |
| 176 | public ImportTraceWizardPage(IWorkbench workbench, IStructuredSelection selection) { |
| 177 | this(IMPORT_WIZARD_PAGE, selection); |
| 178 | setTitle(Messages.ImportTraceWizard_FileSystemTitle); |
| 179 | setDescription(Messages.ImportTraceWizard_ImportTrace); |
| 180 | |
| 181 | // Locate the target trace folder |
| 182 | IFolder traceFolder = null; |
| 183 | Object element = selection.getFirstElement(); |
| 184 | |
| 185 | if (element instanceof TmfTraceFolder) { |
| 186 | fTraceFolderElement = (TmfTraceFolder) element; |
| 187 | traceFolder = fTraceFolderElement.getResource(); |
| 188 | } else if (element instanceof IProject) { |
| 189 | IProject project = (IProject) element; |
| 190 | try { |
| 191 | if (project.hasNature(TmfProjectNature.ID)) { |
| 192 | TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true); |
| 193 | fTraceFolderElement = projectElement.getTracesFolder(); |
| 194 | traceFolder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME); |
| 195 | } |
| 196 | } catch (CoreException e) { |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | // If no tracing project was selected or trace folder doesn't exist use |
| 201 | // default tracing project |
| 202 | if (traceFolder == null) { |
| 203 | IProject project = TmfProjectRegistry.createProject( |
| 204 | TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME, null, new NullProgressMonitor()); |
| 205 | TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true); |
| 206 | fTraceFolderElement = projectElement.getTracesFolder(); |
| 207 | traceFolder = project.getFolder(TmfTracesFolder.TRACES_FOLDER_NAME); |
| 208 | } |
| 209 | |
| 210 | // Set the target trace folder |
| 211 | if (traceFolder != null) { |
| 212 | fTargetFolder = traceFolder; |
| 213 | String path = traceFolder.getFullPath().toString(); |
| 214 | setContainerFieldValue(path); |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | // ------------------------------------------------------------------------ |
| 219 | // WizardResourceImportPage |
| 220 | // ------------------------------------------------------------------------ |
| 221 | |
| 222 | @Override |
| 223 | public void createControl(Composite parent) { |
| 224 | super.createControl(parent); |
| 225 | // Restore last directory if applicable |
| 226 | if (fRootDirectory != null) { |
| 227 | directoryNameField.setText(fRootDirectory); |
| 228 | updateFromSourceField(); |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | @Override |
| 233 | protected void createSourceGroup(Composite parent) { |
| 234 | createDirectorySelectionGroup(parent); |
| 235 | createFileSelectionGroup(parent); |
| 236 | createTraceTypeGroup(parent); |
| 237 | validateSourceGroup(); |
| 238 | } |
| 239 | |
| 240 | @Override |
| 241 | protected ITreeContentProvider getFileProvider() { |
| 242 | return new WorkbenchContentProvider() { |
| 243 | @Override |
| 244 | public Object[] getChildren(Object object) { |
| 245 | if (object instanceof TraceFileSystemElement) { |
| 246 | TraceFileSystemElement element = (TraceFileSystemElement) object; |
| 247 | return element.getFiles().getChildren(element); |
| 248 | } |
| 249 | return new Object[0]; |
| 250 | } |
| 251 | }; |
| 252 | } |
| 253 | |
| 254 | @Override |
| 255 | protected ITreeContentProvider getFolderProvider() { |
| 256 | return new WorkbenchContentProvider() { |
| 257 | @Override |
| 258 | public Object[] getChildren(Object o) { |
| 259 | if (o instanceof TraceFileSystemElement) { |
| 260 | TraceFileSystemElement element = (TraceFileSystemElement) o; |
| 261 | return element.getFolders().getChildren(); |
| 262 | } |
| 263 | return new Object[0]; |
| 264 | } |
| 265 | |
| 266 | @Override |
| 267 | public boolean hasChildren(Object o) { |
| 268 | if (o instanceof TraceFileSystemElement) { |
| 269 | TraceFileSystemElement element = (TraceFileSystemElement) o; |
| 270 | if (element.isPopulated()) { |
| 271 | return getChildren(element).length > 0; |
| 272 | } |
| 273 | //If we have not populated then wait until asked |
| 274 | return true; |
| 275 | } |
| 276 | return false; |
| 277 | } |
| 278 | }; |
| 279 | } |
| 280 | |
| 281 | // ------------------------------------------------------------------------ |
| 282 | // Directory Selection Group (forked WizardFileSystemResourceImportPage1) |
| 283 | // ------------------------------------------------------------------------ |
| 284 | |
| 285 | /** |
| 286 | * creates the directory selection group. |
| 287 | * |
| 288 | * @param parent |
| 289 | * the parent composite |
| 290 | */ |
| 291 | protected void createDirectorySelectionGroup(Composite parent) { |
| 292 | |
| 293 | Composite directoryContainerGroup = new Composite(parent, SWT.NONE); |
| 294 | GridLayout layout = new GridLayout(); |
| 295 | layout.numColumns = 3; |
| 296 | directoryContainerGroup.setLayout(layout); |
| 297 | directoryContainerGroup.setFont(parent.getFont()); |
| 298 | directoryContainerGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); |
| 299 | |
| 300 | // Label ("Trace directory:") |
| 301 | Label groupLabel = new Label(directoryContainerGroup, SWT.NONE); |
| 302 | groupLabel.setText(Messages.ImportTraceWizard_DirectoryLocation); |
| 303 | groupLabel.setFont(parent.getFont()); |
| 304 | |
| 305 | // Directory name entry field |
| 306 | directoryNameField = new Combo(directoryContainerGroup, SWT.BORDER); |
| 307 | GridData data = new GridData(SWT.FILL, SWT.FILL, true, false); |
| 308 | data.widthHint = SIZING_TEXT_FIELD_WIDTH; |
| 309 | directoryNameField.setLayoutData(data); |
| 310 | directoryNameField.setFont(parent.getFont()); |
| 311 | |
| 312 | directoryNameField.addSelectionListener(new SelectionAdapter() { |
| 313 | @Override |
| 314 | public void widgetSelected(SelectionEvent e) { |
| 315 | updateFromSourceField(); |
| 316 | } |
| 317 | }); |
| 318 | |
| 319 | directoryNameField.addKeyListener(new KeyListener() { |
| 320 | @Override |
| 321 | public void keyPressed(KeyEvent e) { |
| 322 | // If there has been a key pressed then mark as dirty |
| 323 | entryChanged = true; |
| 324 | if (e.character == SWT.CR) { // Windows... |
| 325 | entryChanged = false; |
| 326 | updateFromSourceField(); |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | @Override |
| 331 | public void keyReleased(KeyEvent e) { |
| 332 | } |
| 333 | }); |
| 334 | |
| 335 | directoryNameField.addFocusListener(new FocusListener() { |
| 336 | @Override |
| 337 | public void focusGained(FocusEvent e) { |
| 338 | // Do nothing when getting focus |
| 339 | } |
| 340 | @Override |
| 341 | public void focusLost(FocusEvent e) { |
| 342 | // Clear the flag to prevent constant update |
| 343 | if (entryChanged) { |
| 344 | entryChanged = false; |
| 345 | updateFromSourceField(); |
| 346 | } |
| 347 | } |
| 348 | }); |
| 349 | |
| 350 | // Browse button |
| 351 | directoryBrowseButton = new Button(directoryContainerGroup, SWT.PUSH); |
| 352 | directoryBrowseButton.setText(Messages.ImportTraceWizard_BrowseButton); |
| 353 | directoryBrowseButton.addListener(SWT.Selection, this); |
| 354 | directoryBrowseButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); |
| 355 | directoryBrowseButton.setFont(parent.getFont()); |
| 356 | setButtonLayoutData(directoryBrowseButton); |
| 357 | } |
| 358 | |
| 359 | // ------------------------------------------------------------------------ |
| 360 | // Browse for the source directory |
| 361 | // ------------------------------------------------------------------------ |
| 362 | |
| 363 | @Override |
| 364 | public void handleEvent(Event event) { |
| 365 | if (event.widget == directoryBrowseButton) { |
| 366 | handleSourceDirectoryBrowseButtonPressed(); |
| 367 | } |
| 368 | |
| 369 | // Avoid overwriting destination path without repeatedly trigger |
| 370 | // call of handleEvent(); |
| 371 | synchronized (fIsDestinationChanged) { |
| 372 | if (fIsDestinationChanged == false) { |
| 373 | event.display.asyncExec(new Runnable() { |
| 374 | @Override |
| 375 | public void run() { |
| 376 | synchronized (fIsDestinationChanged) { |
| 377 | fIsDestinationChanged = true; |
| 378 | String path = fTargetFolder.getFullPath().toString(); |
| 379 | setContainerFieldValue(path); |
| 380 | } |
| 381 | } |
| 382 | }); |
| 383 | } else { |
| 384 | fIsDestinationChanged = false; |
| 385 | } |
| 386 | } |
| 387 | super.handleEvent(event); |
| 388 | } |
| 389 | |
| 390 | @Override |
| 391 | protected void handleContainerBrowseButtonPressed() { |
| 392 | // Do nothing so that destination directory cannot be changed. |
| 393 | } |
| 394 | |
| 395 | /** |
| 396 | * Handle the button pressed event |
| 397 | */ |
| 398 | protected void handleSourceDirectoryBrowseButtonPressed() { |
| 399 | String currentSource = directoryNameField.getText(); |
| 400 | DirectoryDialog dialog = new DirectoryDialog(directoryNameField.getShell(), SWT.SAVE | SWT.SHEET); |
| 401 | dialog.setText(Messages.ImportTraceWizard_SelectTraceDirectoryTitle); |
| 402 | dialog.setMessage(Messages.ImportTraceWizard_SelectTraceDirectoryMessage); |
| 403 | dialog.setFilterPath(getSourceDirectoryName(currentSource)); |
| 404 | |
| 405 | String selectedDirectory = dialog.open(); |
| 406 | if (selectedDirectory != null) { |
| 407 | // Just quit if the directory is not valid |
| 408 | if ((getSourceDirectory(selectedDirectory) == null) || selectedDirectory.equals(currentSource)) { |
| 409 | return; |
| 410 | } |
| 411 | // If it is valid then proceed to populate |
| 412 | setErrorMessage(null); |
| 413 | setSourceName(selectedDirectory); |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | private File getSourceDirectory() { |
| 418 | return getSourceDirectory(directoryNameField.getText()); |
| 419 | } |
| 420 | |
| 421 | private static File getSourceDirectory(String path) { |
| 422 | File sourceDirectory = new File(getSourceDirectoryName(path)); |
| 423 | if (!sourceDirectory.exists() || !sourceDirectory.isDirectory()) { |
| 424 | return null; |
| 425 | } |
| 426 | |
| 427 | return sourceDirectory; |
| 428 | } |
| 429 | |
| 430 | private static String getSourceDirectoryName(String sourceName) { |
| 431 | IPath result = new Path(sourceName.trim()); |
| 432 | if (result.getDevice() != null && result.segmentCount() == 0) { |
| 433 | result = result.addTrailingSeparator(); |
| 434 | } else { |
| 435 | result = result.removeTrailingSeparator(); |
| 436 | } |
| 437 | return result.toOSString(); |
| 438 | } |
| 439 | |
| 440 | private String getSourceDirectoryName() { |
| 441 | return getSourceDirectoryName(directoryNameField.getText()); |
| 442 | } |
| 443 | |
| 444 | private void updateFromSourceField() { |
| 445 | setSourceName(directoryNameField.getText()); |
| 446 | updateWidgetEnablements(); |
| 447 | } |
| 448 | |
| 449 | private void setSourceName(String path) { |
| 450 | if (path.length() > 0) { |
| 451 | String[] currentItems = directoryNameField.getItems(); |
| 452 | int selectionIndex = -1; |
| 453 | for (int i = 0; i < currentItems.length; i++) { |
| 454 | if (currentItems[i].equals(path)) { |
| 455 | selectionIndex = i; |
| 456 | } |
| 457 | } |
| 458 | if (selectionIndex < 0) { |
| 459 | int oldLength = currentItems.length; |
| 460 | String[] newItems = new String[oldLength + 1]; |
| 461 | System.arraycopy(currentItems, 0, newItems, 0, oldLength); |
| 462 | newItems[oldLength] = path; |
| 463 | directoryNameField.setItems(newItems); |
| 464 | selectionIndex = oldLength; |
| 465 | } |
| 466 | directoryNameField.select(selectionIndex); |
| 467 | } |
| 468 | resetSelection(); |
| 469 | } |
| 470 | |
| 471 | // ------------------------------------------------------------------------ |
| 472 | // File Selection Group (forked WizardFileSystemResourceImportPage1) |
| 473 | // ------------------------------------------------------------------------ |
| 474 | private void resetSelection() { |
| 475 | TraceFileSystemElement root = getFileSystemTree(); |
| 476 | selectionGroup.setRoot(root); |
| 477 | } |
| 478 | |
| 479 | private TraceFileSystemElement getFileSystemTree() { |
| 480 | File sourceDirectory = getSourceDirectory(); |
| 481 | if (sourceDirectory == null) { |
| 482 | return null; |
| 483 | } |
| 484 | return selectFiles(sourceDirectory, FileSystemStructureProvider.INSTANCE); |
| 485 | } |
| 486 | |
| 487 | private TraceFileSystemElement selectFiles(final Object rootFileSystemObject, |
| 488 | final IImportStructureProvider structureProvider) { |
| 489 | final TraceFileSystemElement[] results = new TraceFileSystemElement[1]; |
| 490 | BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { |
| 491 | @Override |
| 492 | public void run() { |
| 493 | // Create the root element from the supplied file system object |
| 494 | results[0] = createRootElement(rootFileSystemObject, structureProvider); |
| 495 | } |
| 496 | }); |
| 497 | return results[0]; |
| 498 | } |
| 499 | |
| 500 | private static TraceFileSystemElement createRootElement(Object fileSystemObject, |
| 501 | IImportStructureProvider provider) { |
| 502 | |
| 503 | boolean isContainer = provider.isFolder(fileSystemObject); |
| 504 | String elementLabel = provider.getLabel(fileSystemObject); |
| 505 | |
| 506 | // Use an empty label so that display of the element's full name |
| 507 | // doesn't include a confusing label |
| 508 | TraceFileSystemElement dummyParent = new TraceFileSystemElement("", null, true);//$NON-NLS-1$ |
| 509 | dummyParent.setFileSystemObject(((File)fileSystemObject).getParentFile()); |
| 510 | dummyParent.setPopulated(); |
| 511 | TraceFileSystemElement result = new TraceFileSystemElement( |
| 512 | elementLabel, dummyParent, isContainer); |
| 513 | result.setFileSystemObject(fileSystemObject); |
| 514 | |
| 515 | //Get the files for the element so as to build the first level |
| 516 | result.getFiles(); |
| 517 | |
| 518 | return dummyParent; |
| 519 | } |
| 520 | |
| 521 | // ------------------------------------------------------------------------ |
| 522 | // Trace Type Group |
| 523 | // ------------------------------------------------------------------------ |
| 524 | private final void createTraceTypeGroup(Composite parent) { |
| 525 | Composite composite = new Composite(parent, SWT.NONE); |
| 526 | GridLayout layout = new GridLayout(); |
| 527 | layout.numColumns = 3; |
| 528 | layout.makeColumnsEqualWidth = false; |
| 529 | composite.setLayout(layout); |
| 530 | composite.setFont(parent.getFont()); |
| 531 | GridData buttonData = new GridData(SWT.FILL, SWT.FILL, true, false); |
| 532 | composite.setLayoutData(buttonData); |
| 533 | |
| 534 | // Trace type label ("Trace Type:") |
| 535 | Label typeLabel = new Label(composite, SWT.NONE); |
| 536 | typeLabel.setText(Messages.ImportTraceWizard_TraceType); |
| 537 | typeLabel.setFont(parent.getFont()); |
| 538 | |
| 539 | // Trace type combo |
| 540 | fTraceTypes = new Combo(composite, SWT.BORDER | SWT.READ_ONLY); |
| 541 | GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1); |
| 542 | fTraceTypes.setLayoutData(data); |
| 543 | fTraceTypes.setFont(parent.getFont()); |
| 544 | |
| 545 | String[] availableTraceTypes = TmfTraceType.getInstance().getAvailableTraceTypes(); |
| 546 | String[] traceTypeList = new String[availableTraceTypes.length + 1]; |
| 547 | traceTypeList[0] = AUTO_DETECT; |
| 548 | for (int i = 0; i < availableTraceTypes.length; i++) { |
| 549 | traceTypeList[i + 1] = availableTraceTypes[i]; |
| 550 | } |
| 551 | fTraceTypes.setItems(traceTypeList); |
| 552 | fTraceTypes.addSelectionListener(new SelectionAdapter() { |
| 553 | @Override |
| 554 | public void widgetSelected(SelectionEvent e) { |
| 555 | updateWidgetEnablements(); |
| 556 | boolean enabled = fTraceTypes.getText().equals(AUTO_DETECT); |
| 557 | fImportUnrecognizedButton.setEnabled(enabled); |
| 558 | } |
| 559 | }); |
| 560 | fTraceTypes.select(0); |
| 561 | |
| 562 | // Unrecognized checkbox |
| 563 | fImportUnrecognizedButton = new Button(composite, SWT.CHECK); |
| 564 | fImportUnrecognizedButton.setSelection(true); |
| 565 | fImportUnrecognizedButton.setText(Messages.ImportTraceWizard_ImportUnrecognized); |
| 566 | |
| 567 | IDialogSettings settings = getDialogSettings(); |
| 568 | boolean value; |
| 569 | if (settings.get(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID) == null) { |
| 570 | value = true; |
| 571 | } else { |
| 572 | value = settings.getBoolean(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID); |
| 573 | } |
| 574 | fImportUnrecognizedButton.setSelection(value); |
| 575 | } |
| 576 | |
| 577 | // ------------------------------------------------------------------------ |
| 578 | // Options |
| 579 | // ------------------------------------------------------------------------ |
| 580 | |
| 581 | @Override |
| 582 | protected void createOptionsGroupButtons(Group optionsGroup) { |
| 583 | |
| 584 | // Overwrite checkbox |
| 585 | fOverwriteExistingResourcesCheckbox = new Button(optionsGroup, SWT.CHECK); |
| 586 | fOverwriteExistingResourcesCheckbox.setFont(optionsGroup.getFont()); |
| 587 | fOverwriteExistingResourcesCheckbox.setText(Messages.ImportTraceWizard_OverwriteExistingTrace); |
| 588 | fOverwriteExistingResourcesCheckbox.setSelection(false); |
| 589 | |
| 590 | // Create links checkbox |
| 591 | fCreateLinksInWorkspaceButton = new Button(optionsGroup, SWT.CHECK); |
| 592 | fCreateLinksInWorkspaceButton.setFont(optionsGroup.getFont()); |
| 593 | fCreateLinksInWorkspaceButton.setText(Messages.ImportTraceWizard_CreateLinksInWorkspace); |
| 594 | fCreateLinksInWorkspaceButton.setSelection(true); |
| 595 | |
| 596 | fCreateLinksInWorkspaceButton.addSelectionListener(new SelectionAdapter() { |
| 597 | @Override |
| 598 | public void widgetSelected(SelectionEvent e) { |
| 599 | updateWidgetEnablements(); |
| 600 | } |
| 601 | }); |
| 602 | |
| 603 | fPreserveFolderStructureButton = new Button(optionsGroup, SWT.CHECK); |
| 604 | fPreserveFolderStructureButton.setFont(optionsGroup.getFont()); |
| 605 | fPreserveFolderStructureButton.setText(Messages.ImportTraceWizard_PreserveFolderStructure); |
| 606 | fPreserveFolderStructureButton.setSelection(true); |
| 607 | |
| 608 | updateWidgetEnablements(); |
| 609 | } |
| 610 | |
| 611 | // ------------------------------------------------------------------------ |
| 612 | // Determine if the finish button can be enabled |
| 613 | // ------------------------------------------------------------------------ |
| 614 | @Override |
| 615 | public boolean validateSourceGroup() { |
| 616 | |
| 617 | File sourceDirectory = getSourceDirectory(); |
| 618 | if (sourceDirectory == null) { |
| 619 | setMessage(Messages.ImportTraceWizard_SelectTraceSourceEmpty); |
| 620 | return false; |
| 621 | } |
| 622 | |
| 623 | if (sourceConflictsWithDestination(new Path(sourceDirectory.getPath()))) { |
| 624 | setMessage(null); |
| 625 | setErrorMessage(getSourceConflictMessage()); |
| 626 | return false; |
| 627 | } |
| 628 | |
| 629 | if (selectionGroup.getCheckedElementCount() == 0) { |
| 630 | setMessage(null); |
| 631 | setErrorMessage(Messages.ImportTraceWizard_SelectTraceNoneSelected); |
| 632 | return false; |
| 633 | } |
| 634 | |
| 635 | IContainer container = getSpecifiedContainer(); |
| 636 | if (container != null && container.isVirtual()) { |
| 637 | if (Platform.getPreferencesService().getBoolean(Activator.PLUGIN_ID, ResourcesPlugin.PREF_DISABLE_LINKING, false, null)) { |
| 638 | setMessage(null); |
| 639 | setErrorMessage(Messages.ImportTraceWizard_CannotImportFilesUnderAVirtualFolder); |
| 640 | return false; |
| 641 | } |
| 642 | if (fCreateLinksInWorkspaceButton == null || !fCreateLinksInWorkspaceButton.getSelection()) { |
| 643 | setMessage(null); |
| 644 | setErrorMessage(Messages.ImportTraceWizard_HaveToCreateLinksUnderAVirtualFolder); |
| 645 | return false; |
| 646 | } |
| 647 | } |
| 648 | |
| 649 | setErrorMessage(null); |
| 650 | return true; |
| 651 | } |
| 652 | |
| 653 | // ------------------------------------------------------------------------ |
| 654 | // Import the trace(s) |
| 655 | // ------------------------------------------------------------------------ |
| 656 | |
| 657 | /** |
| 658 | * Finish the import. |
| 659 | * |
| 660 | * @return <code>true</code> if successful else <code>false</code> |
| 661 | */ |
| 662 | public boolean finish() { |
| 663 | IDialogSettings settings = getDialogSettings(); |
| 664 | settings.put(IMPORT_WIZARD_IMPORT_UNRECOGNIZED_ID, fImportUnrecognizedButton.getSelection()); |
| 665 | |
| 666 | String traceTypeName = fTraceTypes.getText(); |
| 667 | String traceId = null; |
| 668 | if (!AUTO_DETECT.equals(traceTypeName)) { |
| 669 | String tokens[] = traceTypeName.split(SEPARATOR, 2); |
| 670 | if (tokens.length < 2) { |
| 671 | return false; |
| 672 | } |
| 673 | traceId = TmfTraceType.getInstance().getTraceTypeId(tokens[0], tokens[1]); |
| 674 | } |
| 675 | |
| 676 | // Save directory for next import operation |
| 677 | fRootDirectory = getSourceDirectoryName(); |
| 678 | |
| 679 | IPath baseSourceContainerPath = new Path(getSourceDirectory().getAbsolutePath()); |
| 680 | final TraceValidateAndImportOperation operation = new TraceValidateAndImportOperation(traceId, baseSourceContainerPath, getContainerFullPath(), |
| 681 | fImportUnrecognizedButton.getSelection(), fOverwriteExistingResourcesCheckbox.getSelection(), fCreateLinksInWorkspaceButton.getSelection(), fPreserveFolderStructureButton.getSelection()); |
| 682 | |
| 683 | IStatus status = Status.OK_STATUS; |
| 684 | try { |
| 685 | getContainer().run(true, true, new IRunnableWithProgress() { |
| 686 | @Override |
| 687 | public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { |
| 688 | operation.run(monitor); |
| 689 | monitor.done(); |
| 690 | } |
| 691 | }); |
| 692 | |
| 693 | status = operation.getStatus(); |
| 694 | } catch (InvocationTargetException e) { |
| 695 | status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportTraceWizard_ImportProblem, e); |
| 696 | } catch (InterruptedException e) { |
| 697 | status = Status.CANCEL_STATUS; |
| 698 | } finally { |
| 699 | if (!status.isOK()) { |
| 700 | if (status.getSeverity() == IStatus.CANCEL) { |
| 701 | setMessage(Messages.ImportTraceWizard_ImportOperationCancelled); |
| 702 | setErrorMessage(null); |
| 703 | } else { |
| 704 | if (status.getException() != null) { |
| 705 | displayErrorDialog(status.getMessage() + ": " + status.getException()); //$NON-NLS-1$ |
| 706 | } |
| 707 | setMessage(null); |
| 708 | setErrorMessage(Messages.ImportTraceWizard_ImportProblem); |
| 709 | } |
| 710 | return false; |
| 711 | } |
| 712 | } |
| 713 | setErrorMessage(null); |
| 714 | return true; |
| 715 | } |
| 716 | |
| 717 | |
| 718 | // ------------------------------------------------------------------------ |
| 719 | // Classes |
| 720 | // ------------------------------------------------------------------------ |
| 721 | |
| 722 | private class TraceValidateAndImportOperation { |
| 723 | private IStatus fStatus; |
| 724 | private String fTraceType; |
| 725 | private IPath fDestinationContainerPath; |
| 726 | private IPath fBaseSourceContainerPath; |
| 727 | private boolean fImportUnrecognizedTraces; |
| 728 | private boolean fLink; |
| 729 | private boolean fPreserveFolderStructure; |
| 730 | private ImportConfirmation fConfirmationMode = ImportConfirmation.SKIP; |
| 731 | |
| 732 | private TraceValidateAndImportOperation(String traceId, IPath baseSourceContainerPath, IPath destinationContainerPath, boolean doImport, boolean overwrite, boolean link, boolean preserveFolderStructure) { |
| 733 | fTraceType = traceId; |
| 734 | fBaseSourceContainerPath = baseSourceContainerPath; |
| 735 | fDestinationContainerPath = destinationContainerPath; |
| 736 | fImportUnrecognizedTraces = doImport; |
| 737 | if (overwrite) { |
| 738 | fConfirmationMode = ImportConfirmation.OVERWRITE_ALL; |
| 739 | } |
| 740 | fLink = link; |
| 741 | fPreserveFolderStructure = preserveFolderStructure; |
| 742 | } |
| 743 | |
| 744 | public void run(IProgressMonitor progressMonitor) { |
| 745 | String currentPath = null; |
| 746 | final Map<String, TraceFileSystemElement> folderElements = new HashMap<>(); |
| 747 | try { |
| 748 | |
| 749 | final ArrayList<TraceFileSystemElement> fileSystemElements = new ArrayList<>(); |
| 750 | IElementFilter passThroughFilter = new IElementFilter() { |
| 751 | |
| 752 | @Override |
| 753 | public void filterElements(Collection elements, IProgressMonitor monitor) { |
| 754 | fileSystemElements.addAll(elements); |
| 755 | } |
| 756 | @Override |
| 757 | public void filterElements(Object[] elements, IProgressMonitor monitor) { |
| 758 | for (int i = 0; i < elements.length; i++) { |
| 759 | fileSystemElements.add((TraceFileSystemElement)elements[i]); |
| 760 | } |
| 761 | } |
| 762 | }; |
| 763 | |
| 764 | // List fileSystemElements will be filled using the passThroughFilter |
| 765 | SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 1); |
| 766 | getSelectedResources(passThroughFilter, subMonitor); |
| 767 | |
| 768 | // Check if operation was cancelled. |
| 769 | ModalContext.checkCanceled(subMonitor); |
| 770 | |
| 771 | Iterator<TraceFileSystemElement> fileSystemElementsIter = fileSystemElements.iterator(); |
| 772 | subMonitor = SubMonitor.convert(progressMonitor, fileSystemElements.size()); |
| 773 | |
| 774 | while (fileSystemElementsIter.hasNext()) { |
| 775 | ModalContext.checkCanceled(progressMonitor); |
| 776 | currentPath = null; |
| 777 | TraceFileSystemElement element = fileSystemElementsIter.next(); |
| 778 | File fileResource = (File) element.getFileSystemObject(); |
| 779 | String resourcePath = fileResource.getAbsolutePath(); |
| 780 | element.setDestinationContainerPath(computeDestinationContainerPath(new Path(resourcePath))); |
| 781 | |
| 782 | currentPath = resourcePath; |
| 783 | SubMonitor sub = subMonitor.newChild(1); |
| 784 | if (element.isDirectory()) { |
| 785 | if (!folderElements.containsKey(resourcePath)) { |
| 786 | if (isDirectoryTrace(element)) { |
| 787 | folderElements.put(resourcePath, element); |
| 788 | validateAndImportTrace(element, sub); |
| 789 | } |
| 790 | } |
| 791 | } else { |
| 792 | TraceFileSystemElement parentElement = (TraceFileSystemElement)element.getParent(); |
| 793 | File parentFile = (File) parentElement.getFileSystemObject(); |
| 794 | String parentPath = parentFile.getAbsolutePath(); |
| 795 | parentElement.setDestinationContainerPath(computeDestinationContainerPath(new Path(parentPath))); |
| 796 | currentPath = parentPath; |
| 797 | if (!folderElements.containsKey(parentPath)) { |
| 798 | if (isDirectoryTrace(parentElement)) { |
| 799 | folderElements.put(parentPath, parentElement); |
| 800 | validateAndImportTrace(parentElement, sub); |
| 801 | } else { |
| 802 | if (fileResource.exists()) { |
| 803 | validateAndImportTrace(element, sub); |
| 804 | } |
| 805 | } |
| 806 | } |
| 807 | } |
| 808 | } |
| 809 | setStatus(Status.OK_STATUS); |
| 810 | } catch (InterruptedException e) { |
| 811 | setStatus(Status.CANCEL_STATUS); |
| 812 | } catch (Exception e) { |
| 813 | String errorMessage = Messages.ImportTraceWizard_ImportProblem + ": " + //$NON-NLS-1$ |
| 814 | (currentPath != null ? currentPath : ""); //$NON-NLS-1$ |
| 815 | Activator.getDefault().logError(errorMessage, e); |
| 816 | setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage , e)); |
| 817 | } |
| 818 | } |
| 819 | |
| 820 | private IPath computeDestinationContainerPath(Path resourcePath) { |
| 821 | IPath destinationContainerPath = fDestinationContainerPath; |
| 822 | |
| 823 | // We need to figure out the new destination path relative to the selected "base" source directory. |
| 824 | // Here for example, the selected source directory is /home/user |
| 825 | if (fPreserveFolderStructure) { |
| 826 | // /home/user/bar/foo/trace -> /home/user/bar/foo |
| 827 | IPath sourceContainerPath = resourcePath.removeLastSegments(1); |
| 828 | if (fBaseSourceContainerPath.equals(resourcePath)) { |
| 829 | // Use resourcePath directory if fBaseSourceContainerPath points to a directory trace |
| 830 | sourceContainerPath = resourcePath; |
| 831 | } |
| 832 | // /home/user/bar/foo, /home/user -> bar/foo |
| 833 | IPath relativeContainerPath = sourceContainerPath.makeRelativeTo(fBaseSourceContainerPath); |
| 834 | // project/Traces + bar/foo -> project/Traces/bar/foo |
| 835 | destinationContainerPath = fDestinationContainerPath.append(relativeContainerPath); |
| 836 | } |
| 837 | return destinationContainerPath; |
| 838 | } |
| 839 | |
| 840 | private void validateAndImportTrace(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) |
| 841 | throws TmfTraceImportException, CoreException, InvocationTargetException, InterruptedException { |
| 842 | File file = (File) fileSystemElement.getFileSystemObject(); |
| 843 | String path = file.getAbsolutePath(); |
| 844 | TraceTypeHelper traceTypeHelper = null; |
| 845 | |
| 846 | if (fTraceType == null) { |
| 847 | // Auto Detection |
| 848 | try { |
| 849 | traceTypeHelper = TmfTraceTypeUIUtils.selectTraceType(path, null, null); |
| 850 | } catch (TmfTraceImportException e) { |
| 851 | // the trace did not match any trace type |
| 852 | } |
| 853 | if (traceTypeHelper == null) { |
| 854 | if (fImportUnrecognizedTraces) { |
| 855 | importResource(fileSystemElement, monitor); |
| 856 | } |
| 857 | return; |
| 858 | } |
| 859 | } else { |
| 860 | boolean isDirectoryTraceType = TmfTraceType.getInstance().isDirectoryTraceType(fTraceType); |
| 861 | if (fileSystemElement.isDirectory() != isDirectoryTraceType) { |
| 862 | return; |
| 863 | } |
| 864 | traceTypeHelper = TmfTraceType.getInstance().getTraceType(fTraceType); |
| 865 | |
| 866 | if (traceTypeHelper == null) { |
| 867 | // Trace type not found |
| 868 | throw new TmfTraceImportException(Messages.ImportTraceWizard_TraceTypeNotFound); |
| 869 | } |
| 870 | |
| 871 | if (!traceTypeHelper.validate(path).isOK()) { |
| 872 | // Trace type exist but doesn't validate for given trace. |
| 873 | return; |
| 874 | } |
| 875 | } |
| 876 | |
| 877 | // Finally import trace |
| 878 | IResource importedResource = importResource(fileSystemElement, monitor); |
| 879 | if (importedResource != null) { |
| 880 | TmfTraceTypeUIUtils.setTraceType(importedResource, traceTypeHelper); |
| 881 | } |
| 882 | |
| 883 | } |
| 884 | |
| 885 | /** |
| 886 | * Imports a trace resource to project. In case of name collision the |
| 887 | * user will be asked to confirm overwriting the existing trace, |
| 888 | * overwriting or skipping the trace to be imported. |
| 889 | * |
| 890 | * @param fileSystemElement |
| 891 | * trace file system object to import |
| 892 | * @param monitor |
| 893 | * a progress monitor |
| 894 | * @return the imported resource or null if no resource was imported |
| 895 | * |
| 896 | * @throws InvocationTargetException |
| 897 | * if problems during import operation |
| 898 | * @throws InterruptedException |
| 899 | * if cancelled |
| 900 | * @throws CoreException |
| 901 | * if problems with workspace |
| 902 | */ |
| 903 | private IResource importResource(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) |
| 904 | throws InvocationTargetException, InterruptedException, CoreException { |
| 905 | |
| 906 | ImportConfirmation mode = checkForNameClashes(fileSystemElement); |
| 907 | switch (mode) { |
| 908 | case RENAME: |
| 909 | case RENAME_ALL: |
| 910 | rename(fileSystemElement); |
| 911 | break; |
| 912 | case OVERWRITE: |
| 913 | case OVERWRITE_ALL: |
| 914 | delete(fileSystemElement, monitor); |
| 915 | break; |
| 916 | case CONTINUE: |
| 917 | break; |
| 918 | case SKIP: |
| 919 | case SKIP_ALL: |
| 920 | default: |
| 921 | return null; |
| 922 | } |
| 923 | |
| 924 | List<TraceFileSystemElement> subList = new ArrayList<>(); |
| 925 | |
| 926 | FileSystemElement parentFolder = fileSystemElement.getParent(); |
| 927 | |
| 928 | IPath containerPath = fileSystemElement.getDestinationContainerPath(); |
| 929 | IPath tracePath = containerPath.addTrailingSeparator().append(fileSystemElement.getLabel()); |
| 930 | if (fileSystemElement.isDirectory() && (!fLink)) { |
| 931 | containerPath = tracePath; |
| 932 | |
| 933 | Object[] array = fileSystemElement.getFiles().getChildren(); |
| 934 | for (int i = 0; i < array.length; i++) { |
| 935 | subList.add((TraceFileSystemElement)array[i]); |
| 936 | } |
| 937 | parentFolder = fileSystemElement; |
| 938 | |
| 939 | } else { |
| 940 | subList.add(fileSystemElement); |
| 941 | } |
| 942 | |
| 943 | |
| 944 | ImportProvider fileSystemStructureProvider = new ImportProvider(); |
| 945 | |
| 946 | IOverwriteQuery myQueryImpl = new IOverwriteQuery() { |
| 947 | @Override |
| 948 | public String queryOverwrite(String file) { |
| 949 | return IOverwriteQuery.NO_ALL; |
| 950 | } |
| 951 | }; |
| 952 | |
| 953 | monitor.setTaskName(Messages.ImportTraceWizard_ImportOperationTaskName + " " + ((File)fileSystemElement.getFileSystemObject()).getAbsolutePath()); //$NON-NLS-1$ |
| 954 | ImportOperation operation = new ImportOperation(containerPath, parentFolder, fileSystemStructureProvider, myQueryImpl, subList); |
| 955 | operation.setContext(getShell()); |
| 956 | |
| 957 | operation.setCreateContainerStructure(false); |
| 958 | operation.setOverwriteResources(false); |
| 959 | operation.setCreateLinks(fLink); |
| 960 | operation.setVirtualFolders(false); |
| 961 | |
| 962 | operation.run(new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); |
| 963 | |
| 964 | File file = (File) fileSystemElement.getFileSystemObject(); |
| 965 | String sourceLocation = null; |
| 966 | IResource sourceResource; |
| 967 | if (file.isDirectory()) { |
| 968 | sourceResource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(Path.fromOSString(file.getAbsolutePath())); |
| 969 | } else { |
| 970 | sourceResource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(file.getAbsolutePath())); |
| 971 | } |
| 972 | if (sourceResource != null && sourceResource.exists()) { |
| 973 | sourceLocation = sourceResource.getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION); |
| 974 | } |
| 975 | if (sourceLocation == null) { |
| 976 | sourceLocation = URIUtil.toUnencodedString(file.toURI()); |
| 977 | } |
| 978 | |
| 979 | IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(tracePath); |
| 980 | resource.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation); |
| 981 | |
| 982 | return resource; |
| 983 | } |
| 984 | |
| 985 | private boolean isDirectoryTrace(FileSystemElement fileSystemElement) { |
| 986 | File file = (File) fileSystemElement.getFileSystemObject(); |
| 987 | String path = file.getAbsolutePath(); |
| 988 | if (TmfTraceType.getInstance().isDirectoryTrace(path)) { |
| 989 | return true; |
| 990 | } |
| 991 | return false; |
| 992 | } |
| 993 | |
| 994 | private ImportConfirmation checkForNameClashes(TraceFileSystemElement fileSystemElement) throws InterruptedException { |
| 995 | IPath tracePath = getInitialDestinationPath(fileSystemElement); |
| 996 | |
| 997 | // handle rename |
| 998 | if (getExistingTrace(tracePath) != null) { |
| 999 | if ((fConfirmationMode == ImportConfirmation.RENAME_ALL) || |
| 1000 | (fConfirmationMode == ImportConfirmation.OVERWRITE_ALL) || |
| 1001 | (fConfirmationMode == ImportConfirmation.SKIP_ALL)) { |
| 1002 | return fConfirmationMode; |
| 1003 | } |
| 1004 | |
| 1005 | int returnCode = promptForOverwrite(tracePath); |
| 1006 | if (returnCode < 0) { |
| 1007 | // Cancel |
| 1008 | throw new InterruptedException(); |
| 1009 | } |
| 1010 | fConfirmationMode = ImportConfirmation.values()[returnCode]; |
| 1011 | return fConfirmationMode; |
| 1012 | } |
| 1013 | return ImportConfirmation.CONTINUE; |
| 1014 | } |
| 1015 | |
| 1016 | private int promptForOverwrite(IPath tracePath) { |
| 1017 | final MessageDialog dialog = new MessageDialog(getContainer() |
| 1018 | .getShell(), null, null, NLS.bind(Messages.ImportTraceWizard_TraceAlreadyExists, tracePath.makeRelativeTo(fTraceFolderElement.getProject().getPath())), |
| 1019 | MessageDialog.QUESTION, new String[] { |
| 1020 | ImportConfirmation.RENAME.getInName(), |
| 1021 | ImportConfirmation.RENAME_ALL.getInName(), |
| 1022 | ImportConfirmation.OVERWRITE.getInName(), |
| 1023 | ImportConfirmation.OVERWRITE_ALL.getInName(), |
| 1024 | ImportConfirmation.SKIP.getInName(), |
| 1025 | ImportConfirmation.SKIP_ALL.getInName(), |
| 1026 | }, 4) { |
| 1027 | @Override |
| 1028 | protected int getShellStyle() { |
| 1029 | return super.getShellStyle() | SWT.SHEET; |
| 1030 | } |
| 1031 | }; |
| 1032 | |
| 1033 | final int[] returnValue = new int[1]; |
| 1034 | getShell().getDisplay().syncExec(new Runnable() { |
| 1035 | |
| 1036 | @Override |
| 1037 | public void run() { |
| 1038 | returnValue[0] = dialog.open(); |
| 1039 | } |
| 1040 | }); |
| 1041 | return returnValue[0]; |
| 1042 | } |
| 1043 | |
| 1044 | /** |
| 1045 | * @return the initial destination path, before rename, if any |
| 1046 | */ |
| 1047 | private IPath getInitialDestinationPath(TraceFileSystemElement fileSystemElement) { |
| 1048 | IPath traceFolderPath = fileSystemElement.getDestinationContainerPath(); |
| 1049 | return traceFolderPath.append(((File)fileSystemElement.getFileSystemObject()).getName()); |
| 1050 | } |
| 1051 | |
| 1052 | private void rename(TraceFileSystemElement fileSystemElement) { |
| 1053 | IPath tracePath = getInitialDestinationPath(fileSystemElement); |
| 1054 | TmfTraceElement trace = getExistingTrace(tracePath); |
| 1055 | if (trace == null) { |
| 1056 | return; |
| 1057 | } |
| 1058 | |
| 1059 | // Not using IFolder on purpose to leave the door open to import directly into an IProject |
| 1060 | IContainer folder = (IContainer) trace.getParent().getResource(); |
| 1061 | int i = 2; |
| 1062 | while (true) { |
| 1063 | String name = trace.getName() + '(' + Integer.toString(i++) + ')'; |
| 1064 | IResource resource = folder.findMember(name); |
| 1065 | if (resource == null) { |
| 1066 | fileSystemElement.setLabel(name); |
| 1067 | return; |
| 1068 | } |
| 1069 | } |
| 1070 | } |
| 1071 | |
| 1072 | private void delete(TraceFileSystemElement fileSystemElement, IProgressMonitor monitor) throws CoreException { |
| 1073 | IPath tracePath = getInitialDestinationPath(fileSystemElement); |
| 1074 | TmfTraceElement trace = getExistingTrace(tracePath); |
| 1075 | if (trace == null) { |
| 1076 | return; |
| 1077 | } |
| 1078 | |
| 1079 | trace.delete(monitor); |
| 1080 | } |
| 1081 | |
| 1082 | private TmfTraceElement getExistingTrace(IPath tracePath) { |
| 1083 | List<TmfTraceElement> traces = fTraceFolderElement.getTraces(); |
| 1084 | for (TmfTraceElement t : traces) { |
| 1085 | if (t.getPath().equals(tracePath)) { |
| 1086 | return t; |
| 1087 | } |
| 1088 | } |
| 1089 | return null; |
| 1090 | } |
| 1091 | |
| 1092 | /** |
| 1093 | * Set the status for this operation |
| 1094 | * |
| 1095 | * @param status |
| 1096 | * the status |
| 1097 | */ |
| 1098 | protected void setStatus(IStatus status) { |
| 1099 | fStatus = status; |
| 1100 | } |
| 1101 | |
| 1102 | public IStatus getStatus() { |
| 1103 | return fStatus; |
| 1104 | } |
| 1105 | } |
| 1106 | |
| 1107 | /** |
| 1108 | * The <code>TraceFileSystemElement</code> is a <code>FileSystemElement</code> that knows |
| 1109 | * if it has been populated or not. |
| 1110 | */ |
| 1111 | private static class TraceFileSystemElement extends FileSystemElement { |
| 1112 | |
| 1113 | private boolean fIsPopulated = false; |
| 1114 | private String fLabel = null; |
| 1115 | private IPath fDestinationContainerPath; |
| 1116 | |
| 1117 | public TraceFileSystemElement(String name, FileSystemElement parent, boolean isDirectory) { |
| 1118 | super(name, parent, isDirectory); |
| 1119 | } |
| 1120 | |
| 1121 | public void setDestinationContainerPath(IPath destinationContainerPath) { |
| 1122 | fDestinationContainerPath = destinationContainerPath; |
| 1123 | } |
| 1124 | |
| 1125 | public void setPopulated() { |
| 1126 | fIsPopulated = true; |
| 1127 | } |
| 1128 | |
| 1129 | public boolean isPopulated() { |
| 1130 | return fIsPopulated; |
| 1131 | } |
| 1132 | |
| 1133 | @Override |
| 1134 | public AdaptableList getFiles() { |
| 1135 | if(!fIsPopulated) { |
| 1136 | populateElementChildren(); |
| 1137 | } |
| 1138 | return super.getFiles(); |
| 1139 | } |
| 1140 | |
| 1141 | @Override |
| 1142 | public AdaptableList getFolders() { |
| 1143 | if(!fIsPopulated) { |
| 1144 | populateElementChildren(); |
| 1145 | } |
| 1146 | return super.getFolders(); |
| 1147 | } |
| 1148 | |
| 1149 | /** |
| 1150 | * Sets the label for the trace to be used when importing at trace. |
| 1151 | * @param name |
| 1152 | * the label for the trace |
| 1153 | */ |
| 1154 | public void setLabel(String name) { |
| 1155 | fLabel = name; |
| 1156 | } |
| 1157 | |
| 1158 | /** |
| 1159 | * Returns the label for the trace to be used when importing at trace. |
| 1160 | * |
| 1161 | * @return the label of trace resource |
| 1162 | */ |
| 1163 | public String getLabel() { |
| 1164 | if (fLabel == null) { |
| 1165 | //Get the name - if it is empty then return the path as it is a file root |
| 1166 | File file = (File) getFileSystemObject(); |
| 1167 | String name = file.getName(); |
| 1168 | if (name.length() == 0) { |
| 1169 | return file.getPath(); |
| 1170 | } |
| 1171 | return name; |
| 1172 | } |
| 1173 | return fLabel; |
| 1174 | } |
| 1175 | |
| 1176 | /** |
| 1177 | * The full path to the container that will contain the trace |
| 1178 | * |
| 1179 | * @return the destination container path |
| 1180 | */ |
| 1181 | public IPath getDestinationContainerPath() { |
| 1182 | return fDestinationContainerPath; |
| 1183 | } |
| 1184 | |
| 1185 | /** |
| 1186 | * Populates the children of the specified parent <code>FileSystemElement</code> |
| 1187 | */ |
| 1188 | private void populateElementChildren() { |
| 1189 | FileSystemStructureProvider provider = FileSystemStructureProvider.INSTANCE; |
| 1190 | List<File> allchildren = provider.getChildren(this.getFileSystemObject()); |
| 1191 | File child = null; |
| 1192 | TraceFileSystemElement newelement = null; |
| 1193 | Iterator<File> iter = allchildren.iterator(); |
| 1194 | while(iter.hasNext()) { |
| 1195 | child = iter.next(); |
| 1196 | newelement = new TraceFileSystemElement(provider.getLabel(child), this, provider.isFolder(child)); |
| 1197 | newelement.setFileSystemObject(child); |
| 1198 | } |
| 1199 | setPopulated(); |
| 1200 | } |
| 1201 | } |
| 1202 | |
| 1203 | private class ImportProvider implements IImportStructureProvider { |
| 1204 | |
| 1205 | private FileSystemStructureProvider provider = FileSystemStructureProvider.INSTANCE; |
| 1206 | |
| 1207 | ImportProvider() { |
| 1208 | } |
| 1209 | |
| 1210 | @Override |
| 1211 | public String getLabel(Object element) { |
| 1212 | TraceFileSystemElement resource = (TraceFileSystemElement)element; |
| 1213 | return resource.getLabel(); |
| 1214 | } |
| 1215 | |
| 1216 | @Override |
| 1217 | public List getChildren(Object element) { |
| 1218 | TraceFileSystemElement resource = (TraceFileSystemElement)element; |
| 1219 | Object[] array = resource.getFiles().getChildren(); |
| 1220 | List<Object> list = new ArrayList<>(); |
| 1221 | for (int i = 0; i < array.length; i++) { |
| 1222 | list.add(array[i]); |
| 1223 | } |
| 1224 | return list; |
| 1225 | } |
| 1226 | |
| 1227 | @Override |
| 1228 | public InputStream getContents(Object element) { |
| 1229 | TraceFileSystemElement resource = (TraceFileSystemElement)element; |
| 1230 | return provider.getContents(resource.getFileSystemObject()); |
| 1231 | } |
| 1232 | |
| 1233 | @Override |
| 1234 | public String getFullPath(Object element) { |
| 1235 | TraceFileSystemElement resource = (TraceFileSystemElement)element; |
| 1236 | return provider.getFullPath(resource.getFileSystemObject()); |
| 1237 | } |
| 1238 | |
| 1239 | @Override |
| 1240 | public boolean isFolder(Object element) { |
| 1241 | TraceFileSystemElement resource = (TraceFileSystemElement)element; |
| 1242 | return resource.isDirectory(); |
| 1243 | } |
| 1244 | } |
| 1245 | |
| 1246 | private enum ImportConfirmation { |
| 1247 | // ------------------------------------------------------------------------ |
| 1248 | // Enum definition |
| 1249 | // ------------------------------------------------------------------------ |
| 1250 | RENAME(Messages.ImportTraceWizard_ImportConfigurationRename), |
| 1251 | RENAME_ALL(Messages.ImportTraceWizard_ImportConfigurationRenameAll), |
| 1252 | OVERWRITE(Messages.ImportTraceWizard_ImportConfigurationOverwrite), |
| 1253 | OVERWRITE_ALL(Messages.ImportTraceWizard_ImportConfigurationOverwriteAll), |
| 1254 | SKIP(Messages.ImportTraceWizard_ImportConfigurationSkip), |
| 1255 | SKIP_ALL(Messages.ImportTraceWizard_ImportConfigurationSkipAll), |
| 1256 | CONTINUE("CONTINUE"); //$NON-NLS-1$ |
| 1257 | |
| 1258 | // ------------------------------------------------------------------------ |
| 1259 | // Attributes |
| 1260 | // ------------------------------------------------------------------------ |
| 1261 | /** |
| 1262 | * Name of enum |
| 1263 | */ |
| 1264 | private final String fInName; |
| 1265 | |
| 1266 | // ------------------------------------------------------------------------ |
| 1267 | // Constuctors |
| 1268 | // ------------------------------------------------------------------------ |
| 1269 | |
| 1270 | /** |
| 1271 | * Private constructor |
| 1272 | * @param name the name of state |
| 1273 | */ |
| 1274 | private ImportConfirmation(String name) { |
| 1275 | fInName = name; |
| 1276 | } |
| 1277 | |
| 1278 | // ------------------------------------------------------------------------ |
| 1279 | // Accessors |
| 1280 | // ------------------------------------------------------------------------ |
| 1281 | /** |
| 1282 | * @return state name |
| 1283 | */ |
| 1284 | public String getInName() { |
| 1285 | return fInName; |
| 1286 | } |
| 1287 | } |
| 1288 | } |