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