533d91e692fb77a7a5c96f05c21839debfbda9d4
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / internal / tmf / ui / project / handlers / DropAdapterAssistant.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Patrick Tasse - Initial API and implementation
11 * Patrick Tasse - Add support for DROP_LINK and rename prompt on name clash
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.internal.tmf.ui.project.handlers;
15
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileNotFoundException;
19 import java.io.InputStream;
20 import java.lang.reflect.InvocationTargetException;
21 import java.util.Arrays;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.core.resources.IFolder;
27 import org.eclipse.core.resources.IProject;
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.resources.IWorkspace;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.IProgressMonitor;
34 import org.eclipse.core.runtime.IStatus;
35 import org.eclipse.core.runtime.NullProgressMonitor;
36 import org.eclipse.core.runtime.Path;
37 import org.eclipse.core.runtime.QualifiedName;
38 import org.eclipse.core.runtime.Status;
39 import org.eclipse.jface.operation.IRunnableWithProgress;
40 import org.eclipse.jface.viewers.IStructuredSelection;
41 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
42 import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
43 import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
44 import org.eclipse.linuxtools.tmf.ui.project.model.ITmfProjectModelElement;
45 import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement;
46 import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement;
47 import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectRegistry;
48 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
49 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
50 import org.eclipse.osgi.util.NLS;
51 import org.eclipse.swt.SWT;
52 import org.eclipse.swt.dnd.DND;
53 import org.eclipse.swt.dnd.DropTargetEvent;
54 import org.eclipse.swt.dnd.FileTransfer;
55 import org.eclipse.swt.dnd.TransferData;
56 import org.eclipse.swt.widgets.MessageBox;
57 import org.eclipse.ui.PlatformUI;
58 import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
59 import org.eclipse.ui.dialogs.IOverwriteQuery;
60 import org.eclipse.ui.navigator.CommonDropAdapter;
61 import org.eclipse.ui.navigator.CommonDropAdapterAssistant;
62 import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
63 import org.eclipse.ui.wizards.datatransfer.ImportOperation;
64
65 /**
66 * Drop adapter assistant for project explorer
67 */
68 public class DropAdapterAssistant extends CommonDropAdapterAssistant {
69
70 /**
71 * Default constructor
72 */
73 public DropAdapterAssistant() {
74 }
75
76 @Override
77 public boolean isSupportedType(TransferData aTransferType) {
78 return super.isSupportedType(aTransferType) || FileTransfer.getInstance().isSupportedType(aTransferType);
79 }
80
81 @Override
82 public IStatus validateDrop(Object target, int operation, TransferData transferType) {
83 if (target instanceof TmfTraceFolder) {
84 return Status.OK_STATUS;
85 }
86 if (target instanceof TmfExperimentElement) {
87 return Status.OK_STATUS;
88 }
89 if (target instanceof TmfTraceElement) {
90 ITmfProjectModelElement parent = ((TmfTraceElement) target).getParent();
91 if (parent instanceof TmfTraceFolder) {
92 return Status.OK_STATUS;
93 }
94 if (parent instanceof TmfExperimentElement) {
95 return Status.OK_STATUS;
96 }
97 }
98 if (target instanceof IProject) {
99 return Status.OK_STATUS;
100 }
101 return Status.CANCEL_STATUS;
102 }
103
104 @Override
105 public IStatus handleDrop(CommonDropAdapter aDropAdapter, DropTargetEvent aDropTargetEvent, Object aTarget) {
106 boolean ok = false;
107
108 // Use local variable to avoid parameter assignment
109 Object targetToUse = aTarget;
110
111 int operation = aDropTargetEvent.detail;
112 if (operation != DND.DROP_LINK) {
113 operation = DND.DROP_COPY;
114 }
115
116 // If target is a trace, use its parent (either trace folder or experiment)
117 if (targetToUse instanceof TmfTraceElement) {
118 targetToUse = ((TmfTraceElement) targetToUse).getParent();
119 }
120
121 // If target is a project, use its trace folder
122 if (targetToUse instanceof IProject) {
123 TmfProjectElement projectElement = TmfProjectRegistry.getProject((IProject) targetToUse);
124 if (projectElement != null) {
125 targetToUse = projectElement.getTracesFolder();
126 }
127 }
128
129 if (aDropTargetEvent.data instanceof IStructuredSelection) {
130 IStructuredSelection selection = (IStructuredSelection) aDropTargetEvent.data;
131 for (Object source : selection.toArray()) {
132 if (source instanceof IResource) {
133 // If source resource is a trace, use the trace element
134 IResource sourceResource = (IResource) source;
135 TmfProjectElement projectElement = TmfProjectRegistry.getProject(sourceResource.getProject());
136 if (projectElement != null && projectElement.getTracesFolder() != null) {
137 for (TmfTraceElement trace : projectElement.getTracesFolder().getTraces()) {
138 if (trace.getResource().equals(sourceResource)) {
139 source = trace;
140 break;
141 }
142 }
143 }
144 }
145 if (source instanceof TmfTraceElement) {
146 TmfTraceElement sourceTrace = (TmfTraceElement) source;
147 // If source trace is under an experiment, use the original trace from the traces folder
148 sourceTrace = sourceTrace.getElementUnderTraceFolder();
149 if (targetToUse instanceof TmfExperimentElement) {
150 TmfExperimentElement targetExperiment = (TmfExperimentElement) targetToUse;
151 ok |= drop(sourceTrace, targetExperiment, operation);
152 } else if (targetToUse instanceof TmfTraceFolder) {
153 TmfTraceFolder traceFolder = (TmfTraceFolder) targetToUse;
154 ok |= drop(sourceTrace, traceFolder, operation);
155 }
156 } else if (source instanceof IResource) {
157 IResource sourceResource = (IResource) source;
158 if (sourceResource.getType() != IResource.FILE && sourceResource.getType() != IResource.FOLDER) {
159 continue;
160 }
161 if (targetToUse instanceof TmfExperimentElement) {
162 TmfExperimentElement targetExperiment = (TmfExperimentElement) targetToUse;
163 ok |= (drop(sourceResource, targetExperiment, operation) != null);
164 } else if (targetToUse instanceof TmfTraceFolder) {
165 TmfTraceFolder traceFolder = (TmfTraceFolder) targetToUse;
166 ok |= (drop(sourceResource, traceFolder, operation) != null);
167 }
168 }
169 }
170 } else if (aDropTargetEvent.data instanceof String[]) {
171 String[] sources = (String[]) aDropTargetEvent.data;
172 for (String source : sources) {
173 Path path = new Path(source);
174 if (targetToUse instanceof TmfExperimentElement) {
175 TmfExperimentElement targetExperiment = (TmfExperimentElement) targetToUse;
176 ok |= drop(path, targetExperiment, operation);
177 } else if (targetToUse instanceof TmfTraceFolder) {
178 TmfTraceFolder traceFolder = (TmfTraceFolder) targetToUse;
179 ok |= drop(path, traceFolder, operation);
180 }
181 }
182 }
183 return (ok ? Status.OK_STATUS : Status.CANCEL_STATUS);
184 }
185
186
187 /**
188 * Drop a trace by copying/linking a trace element in a target experiment
189 *
190 * @param sourceTrace the source trace element to copy
191 * @param targetExperiment the target experiment
192 * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
193 * @return true if successful
194 */
195 private static boolean drop(TmfTraceElement sourceTrace,
196 TmfExperimentElement targetExperiment,
197 int operation) {
198
199 IResource sourceResource = sourceTrace.getResource();
200 IResource targetResource = drop(sourceResource, targetExperiment, operation);
201
202 if (targetResource != null) {
203 if (! sourceTrace.getProject().equals(targetExperiment.getProject())) {
204 IFolder destinationSupplementaryFolder = targetExperiment.getTraceSupplementaryFolder(targetResource.getName());
205 sourceTrace.copySupplementaryFolder(destinationSupplementaryFolder);
206 }
207 return true;
208 }
209 return false;
210 }
211
212 /**
213 * Drop a trace by copying/linking a resource in a target experiment
214 *
215 * @param sourceResource the source resource
216 * @param targetExperiment the target experiment
217 * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
218 * @return the target resource or null if unsuccessful
219 */
220 private static IResource drop(IResource sourceResource,
221 TmfExperimentElement targetExperiment,
222 int operation) {
223
224 IResource traceResource = sourceResource;
225
226 TmfProjectElement projectElement = TmfProjectRegistry.getProject(sourceResource.getProject());
227 for (TmfTraceElement trace : targetExperiment.getTraces()) {
228 if (trace.getName().equals(sourceResource.getName()) && targetExperiment.getProject().equals(projectElement)) {
229 return null;
230 }
231 }
232 if (!targetExperiment.getProject().equals(projectElement)) {
233 String targetName = sourceResource.getName();
234 for (TmfTraceElement trace : targetExperiment.getProject().getTracesFolder().getTraces()) {
235 if (trace.getName().equals(targetName)) {
236 targetName = promptRename(trace);
237 if (targetName == null) {
238 return null;
239 }
240 break;
241 }
242 }
243 try {
244 if (operation == DND.DROP_COPY) {
245 IPath destination = targetExperiment.getProject().getTracesFolder().getResource().getFullPath().addTrailingSeparator().append(targetName);
246 sourceResource.copy(destination, false, null);
247 cleanupBookmarks(destination);
248 } else {
249 createLink(targetExperiment.getProject().getTracesFolder().getResource(), sourceResource, targetName);
250 }
251 // use the copied resource for the experiment
252 if (sourceResource.getType() == IResource.FILE) {
253 traceResource = targetExperiment.getProject().getTracesFolder().getResource().getFile(targetName);
254 } else if (sourceResource.getType() == IResource.FOLDER) {
255 traceResource = targetExperiment.getProject().getTracesFolder().getResource().getFolder(targetName);
256 }
257 } catch (CoreException e) {
258 displayException(e);
259 return null;
260 }
261 }
262 if (traceResource != null && traceResource.exists()) {
263 createLink(targetExperiment.getResource(), traceResource, traceResource.getName());
264 targetExperiment.closeEditors();
265 return traceResource;
266 }
267 return null;
268 }
269
270 /**
271 * Drop a trace by copying/linking a trace element in a trace folder
272 *
273 * @param sourceTrace the source trace
274 * @param traceFolder the target trace folder
275 * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
276 * @return true if successful
277 */
278 private static boolean drop(TmfTraceElement sourceTrace,
279 TmfTraceFolder traceFolder,
280 int operation) {
281
282 IResource sourceResource = sourceTrace.getResource();
283 IResource targetResource = drop(sourceResource, traceFolder, operation);
284
285 if (targetResource != null) {
286 IFolder destinationSupplementaryFolder = traceFolder.getTraceSupplementaryFolder(targetResource.getName());
287 sourceTrace.copySupplementaryFolder(destinationSupplementaryFolder);
288 return true;
289 }
290 return false;
291 }
292
293 /**
294 * Drop a trace by copying/linking a resource in a trace folder
295 *
296 * @param sourceResource the source resource
297 * @param traceFolder the target trace folder
298 * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
299 * @return the target resource or null if unsuccessful
300 */
301 private static IResource drop(IResource sourceResource,
302 TmfTraceFolder traceFolder,
303 int operation) {
304
305 if (sourceResource.getProject().equals(traceFolder.getResource().getProject())) {
306 return null;
307 }
308 String targetName = sourceResource.getName();
309 for (TmfTraceElement trace : traceFolder.getTraces()) {
310 if (trace.getName().equals(targetName)) {
311 targetName = promptRename(trace);
312 if (targetName == null) {
313 return null;
314 }
315 break;
316 }
317 }
318 try {
319 if (operation == DND.DROP_COPY) {
320 IPath destination = traceFolder.getResource().getFullPath().addTrailingSeparator().append(targetName);
321 sourceResource.copy(destination, false, null);
322 cleanupBookmarks(destination);
323 } else {
324 createLink(traceFolder.getResource(), sourceResource, targetName);
325 }
326 return traceFolder.getResource().findMember(targetName);
327 } catch (CoreException e) {
328 displayException(e);
329 }
330 return null;
331 }
332
333 /**
334 * Drop a trace by importing/linking a path in a target experiment
335 *
336 * @param path the source path
337 * @param targetExperiment the target experiment
338 * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
339 * @return true if successful
340 */
341 private static boolean drop(Path path,
342 TmfExperimentElement targetExperiment,
343 int operation) {
344
345 // Use local variable to avoid parameter assignment
346 Path pathToUse = path;
347
348 for (TmfTraceElement trace : targetExperiment.getTraces()) {
349 if (trace.getName().equals(pathToUse.lastSegment()) && pathToUse.toString().startsWith(targetExperiment.getProject().getResource().getLocation().toString())) {
350 return false;
351 }
352 }
353 if (!pathToUse.toString().startsWith(targetExperiment.getProject().getResource().getLocation().toString())) {
354 String targetName = pathToUse.lastSegment();
355 for (TmfTraceElement trace : targetExperiment.getProject().getTracesFolder().getTraces()) {
356 if (trace.getName().equals(targetName)) {
357 targetName = promptRename(trace);
358 if (targetName == null) {
359 return false;
360 }
361 break;
362 }
363 }
364 if (operation == DND.DROP_COPY) {
365 importTrace(targetExperiment.getProject().getTracesFolder().getResource(), pathToUse, targetName);
366 } else {
367 createLink(targetExperiment.getProject().getTracesFolder().getResource(), pathToUse, targetName);
368 }
369 // use the copied resource for the experiment
370 IResource resource = null;
371 File file = new File(pathToUse.toString());
372 if (file.exists() && file.isFile()) {
373 resource = targetExperiment.getProject().getTracesFolder().getResource().getFile(targetName);
374 } else if (file.exists() && file.isDirectory()) {
375 resource = targetExperiment.getProject().getTracesFolder().getResource().getFolder(targetName);
376 }
377 if (resource != null && resource.exists()) {
378 createLink(targetExperiment.getResource(), resource, resource.getName());
379 targetExperiment.closeEditors();
380 return true;
381 }
382 }
383 return false;
384 }
385
386 /**
387 * Drop a trace by importing/linking a path in a trace folder
388 *
389 * @param path the source path
390 * @param traceFolder the target trace folder
391 * @param operation the drop operation (DND.DROP_COPY | DND.DROP_LINK)
392 * @return true if successful
393 */
394 private static boolean drop(Path path,
395 TmfTraceFolder traceFolder,
396 int operation) {
397
398 String targetName = path.lastSegment();
399 for (TmfTraceElement trace : traceFolder.getTraces()) {
400 if (trace.getName().equals(targetName)) {
401 targetName = promptRename(trace);
402 if (targetName == null) {
403 return false;
404 }
405 break;
406 }
407 }
408 if (operation == DND.DROP_COPY) {
409 importTrace(traceFolder.getResource(), path, targetName);
410 } else {
411 createLink(traceFolder.getResource(), path, targetName);
412 }
413 return true;
414 }
415
416 /**
417 * Import a trace to the trace folder
418 *
419 * @param folder the trace folder resource
420 * @param path the path to the trace to import
421 * @param targetName the target name
422 */
423 private static void importTrace(final IFolder folder, final Path path, final String targetName) {
424 final File source = new File(path.toString());
425 if (source.isDirectory()) {
426 IPath containerPath = folder.getFullPath().addTrailingSeparator().append(targetName);
427 IOverwriteQuery overwriteImplementor = new IOverwriteQuery() {
428 @Override
429 public String queryOverwrite(String pathString) {
430 return IOverwriteQuery.NO_ALL;
431 }
432 };
433 List<File> filesToImport = Arrays.asList(source.listFiles());
434 ImportOperation operation = new ImportOperation(
435 containerPath,
436 source,
437 FileSystemStructureProvider.INSTANCE,
438 overwriteImplementor,
439 filesToImport);
440 operation.setCreateContainerStructure(false);
441 try {
442 operation.run(new NullProgressMonitor());
443 } catch (InvocationTargetException e) {
444 displayException(e);
445 } catch (InterruptedException e) {
446 displayException(e);
447 }
448 } else {
449 IRunnableWithProgress runnable = new IRunnableWithProgress() {
450 @Override
451 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
452 try {
453 InputStream inputStream = new FileInputStream(source);
454 IFile targetFile = folder.getFile(targetName);
455 targetFile.create(inputStream, IResource.NONE, monitor);
456 } catch (CoreException e) {
457 displayException(e);
458 } catch (FileNotFoundException e) {
459 displayException(e);
460 }
461 }
462 };
463 WorkspaceModifyDelegatingOperation operation = new WorkspaceModifyDelegatingOperation(runnable);
464 try {
465 operation.run(new NullProgressMonitor());
466 } catch (InvocationTargetException e) {
467 displayException(e);
468 } catch (InterruptedException e) {
469 displayException(e);
470 }
471 }
472 }
473
474 /**
475 * Create a link to the actual trace and set the trace type
476 *
477 * @param parentFolder the parent folder
478 * @param resource the resource
479 * @param targetName the target name
480 */
481 private static void createLink(IFolder parentFolder, IResource resource, String targetName) {
482 IPath location = resource.getLocation();
483 IWorkspace workspace = ResourcesPlugin.getWorkspace();
484 try {
485 Map<QualifiedName, String> properties = resource.getPersistentProperties();
486 String bundleName = properties.get(TmfCommonConstants.TRACEBUNDLE);
487 String traceType = properties.get(TmfCommonConstants.TRACETYPE);
488 String iconUrl = properties.get(TmfCommonConstants.TRACEICON);
489 String supplFolder = properties.get(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
490
491 if (resource instanceof IFolder) {
492 IFolder folder = parentFolder.getFolder(targetName);
493 if (workspace.validateLinkLocation(folder, location).isOK()) {
494 folder.createLink(location, IResource.REPLACE, null);
495 setProperties(folder, bundleName, traceType, iconUrl, supplFolder);
496
497 } else {
498 Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
499 }
500 } else {
501 IFile file = parentFolder.getFile(targetName);
502 if (workspace.validateLinkLocation(file, location).isOK()) {
503 file.createLink(location, IResource.REPLACE, null);
504 setProperties(file, bundleName, traceType, iconUrl, supplFolder);
505 } else {
506 Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
507 }
508 }
509 } catch (CoreException e) {
510 displayException(e);
511 }
512 }
513
514 /**
515 * Create a link to a file or folder
516 *
517 * @param parentFolder the parent folder
518 * @param source the file or folder
519 * @param targetName the target name
520 */
521 private static void createLink(IFolder parentFolder, IPath location, String targetName) {
522 File source = new File(location.toString());
523 IWorkspace workspace = ResourcesPlugin.getWorkspace();
524 try {
525
526 if (source.isDirectory()) {
527 IFolder folder = parentFolder.getFolder(targetName);
528 if (workspace.validateLinkLocation(folder, location).isOK()) {
529 folder.createLink(location, IResource.REPLACE, null);
530 } else {
531 Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
532 }
533 } else {
534 IFile file = parentFolder.getFile(targetName);
535 if (workspace.validateLinkLocation(file, location).isOK()) {
536 file.createLink(location, IResource.REPLACE, null);
537 } else {
538 Activator.getDefault().logError("Invalid Trace Location"); //$NON-NLS-1$
539 }
540 }
541 } catch (CoreException e) {
542 displayException(e);
543 }
544 }
545
546 /**
547 * Prompts the user to rename a trace
548 *
549 * @param trace the existing trace
550 * @return the new name to use or null if rename is canceled
551 */
552 private static String promptRename(TmfTraceElement trace) {
553 MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.ICON_QUESTION | SWT.CANCEL | SWT.OK);
554 mb.setText(Messages.DropAdapterAssistant_RenameTraceTitle);
555 mb.setMessage(NLS.bind(Messages.DropAdapterAssistant_RenameTraceMessage, trace.getName()));
556 if (mb.open() != SWT.OK) {
557 return null;
558 }
559 IFolder folder = trace.getProject().getTracesFolder().getResource();
560 int i = 2;
561 while (true) {
562 String name = trace.getName() + '-' + Integer.toString(i++);
563 IResource resource = folder.findMember(name);
564 if (resource == null) {
565 return name;
566 }
567 }
568 }
569
570 /**
571 * Cleanup bookmarks file in copied trace
572 */
573 private static void cleanupBookmarks(IPath path) {
574 IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(path);
575 if (folder.exists()) {
576 try {
577 for (IResource member : folder.members()) {
578 if (TmfTrace.class.getCanonicalName().equals(member.getPersistentProperty(TmfCommonConstants.TRACETYPE))) {
579 member.delete(true, null);
580 }
581 }
582 } catch (CoreException e) {
583 displayException(e);
584 }
585 }
586 }
587
588 /**
589 * Set the trace persistent properties
590 *
591 * @param resource the trace resource
592 * @param bundleName the bundle name
593 * @param traceType the trace type
594 * @param iconUrl the icon URL
595 * @param supplFolder the directory of the directory for supplementary information or null to ignore the property
596 * @throws CoreException
597 */
598 private static void setProperties(IResource resource, String bundleName,
599 String traceType, String iconUrl, String supplFolder)
600 throws CoreException {
601 resource.setPersistentProperty(TmfCommonConstants.TRACEBUNDLE, bundleName);
602 resource.setPersistentProperty(TmfCommonConstants.TRACETYPE, traceType);
603 resource.setPersistentProperty(TmfCommonConstants.TRACEICON, iconUrl);
604 resource.setPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, supplFolder);
605 }
606
607 /**
608 * Display an exception in a message box
609 *
610 * @param e the exception
611 */
612 private static void displayException(Exception e) {
613 MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
614 mb.setText(e.getClass().getName());
615 mb.setMessage(e.getMessage());
616 mb.open();
617 }
618
619 }
This page took 0.043153 seconds and 4 git commands to generate.