tmf: Add Export Time Selection action and related interface
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / project / model / TmfOpenTraceHelper.java
1 /**********************************************************************
2 * Copyright (c) 2013, 2014 Ericsson, École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Patrick Tasse - Update open trace and add open experiment
12 * Geneviève Bastien - Merge methods to open trace and experiments
13 * Bernd Hufmann - Updated handling of directory traces
14 **********************************************************************/
15
16 package org.eclipse.tracecompass.tmf.ui.project.model;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.util.List;
21
22 import org.eclipse.core.resources.IFile;
23 import org.eclipse.core.resources.IFolder;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.Path;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.core.runtime.URIUtil;
31 import org.eclipse.jface.util.OpenStrategy;
32 import org.eclipse.osgi.util.NLS;
33 import org.eclipse.swt.widgets.Display;
34 import org.eclipse.swt.widgets.MessageBox;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
37 import org.eclipse.tracecompass.internal.tmf.ui.project.model.TmfImportHelper;
38 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
39 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
40 import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
41 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
42 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
43 import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
44 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
45 import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
46 import org.eclipse.tracecompass.tmf.ui.editors.TmfEditorInput;
47 import org.eclipse.tracecompass.tmf.ui.editors.TmfEventsEditor;
48 import org.eclipse.ui.IEditorInput;
49 import org.eclipse.ui.IEditorPart;
50 import org.eclipse.ui.IEditorReference;
51 import org.eclipse.ui.IReusableEditor;
52 import org.eclipse.ui.IWorkbench;
53 import org.eclipse.ui.IWorkbenchPage;
54 import org.eclipse.ui.IWorkbenchWindow;
55 import org.eclipse.ui.PartInitException;
56 import org.eclipse.ui.PlatformUI;
57 import org.eclipse.ui.ide.IDE;
58 import org.eclipse.ui.part.FileEditorInput;
59
60 /**
61 * Open trace helper
62 *
63 * Helper class for opening trace resources and loading them to a tracing
64 * project.
65 *
66 * @author Matthew Khouzam
67 */
68 public class TmfOpenTraceHelper {
69
70 private TmfOpenTraceHelper() {
71 }
72
73 private static final String ENDL = System.getProperty("line.separator"); //$NON-NLS-1$
74
75 /**
76 * Opens a trace from a path while importing it to the destination folder.
77 * The trace is linked as a resource.
78 *
79 * @param destinationFolder
80 * The destination trace folder
81 * @param path
82 * the file to import
83 * @param shell
84 * the shell to use for dialogs
85 * @return IStatus OK if successful
86 * @throws CoreException
87 * core exceptions if something is not well set up in the back
88 * end
89 */
90 public static IStatus openTraceFromPath(TmfTraceFolder destinationFolder, String path, Shell shell) throws CoreException {
91 return openTraceFromPath(destinationFolder, path, shell, null);
92 }
93
94 /**
95 * Opens a trace from a path while importing it to the destination folder.
96 * The trace is linked as a resource.
97 *
98 * @param destinationFolder
99 * The destination trace folder
100 * @param path
101 * the file to import
102 * @param shell
103 * the shell to use for dialogs
104 * @param tracetypeHint
105 * The trace type id, can be null
106 * @return IStatus OK if successful
107 * @throws CoreException
108 * core exceptions if something is not well set up in the back
109 * end
110 */
111 public static IStatus openTraceFromPath(TmfTraceFolder destinationFolder, String path, Shell shell, String tracetypeHint) throws CoreException {
112 final String pathToUse = checkTracePath(path);
113 TraceTypeHelper traceTypeToSet = null;
114 try {
115 traceTypeToSet = TmfTraceTypeUIUtils.selectTraceType(pathToUse, null, tracetypeHint);
116 } catch (TmfTraceImportException e) {
117 MessageBox mb = new MessageBox(shell);
118 mb.setMessage(e.getMessage());
119 mb.open();
120 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage());
121 }
122
123 IFolder folder = destinationFolder.getResource();
124 String traceName = getTraceName(pathToUse, folder);
125 if (traceExists(pathToUse, folder)) {
126 return openTraceFromFolder(destinationFolder, traceName);
127 }
128 final IPath pathString = Path.fromOSString(pathToUse);
129 IResource linkedTrace = TmfImportHelper.createLink(folder, pathString, traceName);
130
131 if (linkedTrace == null || !linkedTrace.exists()) {
132 return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
133 Messages.TmfOpenTraceHelper_LinkFailed);
134 }
135
136 String sourceLocation = URIUtil.toUnencodedString(pathString.toFile().toURI());
137 linkedTrace.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
138
139 // No trace type was determined.
140 if (traceTypeToSet == null) {
141 return Status.OK_STATUS;
142 }
143
144 IStatus ret = TmfTraceTypeUIUtils.setTraceType(linkedTrace, traceTypeToSet);
145 if (ret.isOK()) {
146 ret = openTraceFromFolder(destinationFolder, traceName);
147 }
148 return ret;
149 }
150
151 /**
152 * Checks whether the parent or grandparent of given path to a file is a
153 * valid directory trace. If it is a directory trace then return the parent
154 * or grandparent path.
155 *
156 * @param path
157 * the path to check
158 * @return path to use for trace type validation.
159 */
160 private static String checkTracePath(String path) {
161 File file = new File(path);
162 if (file.exists() && !file.isDirectory()) {
163 // First check parent
164 File parent = file.getParentFile();
165 String pathToUse = parent.getAbsolutePath();
166 if (TmfTraceType.isDirectoryTrace(pathToUse)) {
167 return pathToUse;
168 }
169 // Second check grandparent
170 File grandParent = parent.getParentFile();
171 if (grandParent != null) {
172 pathToUse = grandParent.getAbsolutePath();
173 if (TmfTraceType.isDirectoryTrace(pathToUse)) {
174 return pathToUse;
175 }
176 }
177 }
178 return path;
179 }
180
181 private static boolean traceExists(String path, IFolder folder) {
182 String val = getTraceName(path, folder);
183 return (folder.findMember(val) != null);
184 }
185
186 private static boolean isWrongMember(IFolder folder, String name, final File traceFile) {
187 final IResource candidate = folder.findMember(name);
188 if (candidate != null) {
189 final IPath rawLocation = candidate.getRawLocation();
190 File file = rawLocation.toFile();
191 try {
192 file = file.getCanonicalFile();
193 } catch (IOException e) {
194 /* just use original file path */
195 }
196 return !file.equals(traceFile);
197 }
198 return false;
199 }
200
201 /**
202 * Gets the display name, either "filename" or "filename(n)" if there is
203 * already a filename existing where n is the next unused integer starting
204 * from 2
205 *
206 * @param path
207 * the file path
208 * @param folder
209 * the folder to import to
210 * @return the filename
211 */
212 private static String getTraceName(String path, IFolder folder) {
213 String name;
214 File traceFile = new File(path);
215 try {
216 traceFile = traceFile.getCanonicalFile();
217 } catch (IOException e) {
218 /* just use original file path */
219 }
220 name = traceFile.getName();
221 for (int i = 2; isWrongMember(folder, name, traceFile); i++) {
222 name = traceFile.getName() + '(' + i + ')';
223 }
224 return name;
225 }
226
227 /**
228 * Open a trace from a trace folder
229 *
230 * @param destinationFolder
231 * The destination trace folder
232 * @param traceName
233 * the trace name
234 * @return success or error
235 */
236 private static IStatus openTraceFromFolder(TmfTraceFolder destinationFolder, String traceName) {
237 final List<ITmfProjectModelElement> elements = destinationFolder.getChildren();
238 TmfTraceElement traceElement = null;
239 for (ITmfProjectModelElement element : elements) {
240 if (element instanceof TmfTraceElement && element.getName().equals(traceName)) {
241 traceElement = (TmfTraceElement) element;
242 }
243 }
244 if (traceElement == null) {
245 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, NLS.bind(Messages.TmfOpenTraceHelper_TraceNotFound, traceName));
246 }
247 openTraceFromElement(traceElement);
248 return Status.OK_STATUS;
249 }
250
251 private static ITmfTrace openTraceElement(final TmfTraceElement traceElement) {
252 final ITmfTrace trace = traceElement.instantiateTrace();
253 final ITmfEvent traceEvent = traceElement.instantiateEvent();
254 if ((trace == null) || (traceEvent == null)) {
255 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
256 Messages.TmfOpenTraceHelper_NoTraceType);
257 if (trace != null) {
258 trace.dispose();
259 }
260 return null;
261 }
262
263 try {
264 trace.initTrace(traceElement.getResource(), traceElement.getResource().getLocation().toOSString(), traceEvent.getClass(), traceElement.getElementPath(), traceElement.getTraceType());
265 } catch (final TmfTraceException e) {
266 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
267 Messages.TmfOpenTraceHelper_InitError + ENDL + ENDL + e, e);
268 trace.dispose();
269 return null;
270 }
271 return trace;
272 }
273
274 private static ITmfTrace openExperimentElement(final TmfExperimentElement experimentElement) {
275 /* Experiment element now has an experiment type associated with it */
276 final TmfExperiment experiment = experimentElement.instantiateTrace();
277 if (experiment == null) {
278 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, experimentElement.getTypeName()),
279 NLS.bind(Messages.TmfOpenTraceHelper_NoTraceOrExperimentType, experimentElement.getTypeName()));
280 return null;
281 }
282
283 // Instantiate the experiment's traces
284 final List<TmfTraceElement> traceEntries = experimentElement.getTraces();
285 int cacheSize = Integer.MAX_VALUE;
286 final ITmfTrace[] traces = new ITmfTrace[traceEntries.size()];
287 for (int i = 0; i < traceEntries.size(); i++) {
288 TmfTraceElement element = traceEntries.get(i);
289
290 // Since trace is under an experiment, use the original trace from
291 // the traces folder
292 element = element.getElementUnderTraceFolder();
293
294 ITmfTrace trace = openTraceElement(element);
295
296 if (trace == null) {
297 for (int j = 0; j < i; j++) {
298 traces[j].dispose();
299 }
300 return null;
301 }
302 cacheSize = Math.min(cacheSize, trace.getCacheSize());
303
304 traces[i] = trace;
305 }
306
307 // Create the experiment
308 experiment.initExperiment(ITmfEvent.class, experimentElement.getName(), traces, cacheSize, experimentElement.getResource());
309
310 return experiment;
311 }
312
313 private static ITmfTrace openProjectElement(final TmfCommonProjectElement element) {
314 ITmfTrace trace = null;
315 if (element instanceof TmfTraceElement) {
316 trace = openTraceElement((TmfTraceElement) element);
317 } else if (element instanceof TmfExperimentElement) {
318 trace = openExperimentElement((TmfExperimentElement) element);
319 }
320 return trace;
321 }
322
323 /**
324 * Open a trace (or experiment) from a project element. If the trace is already opened, its
325 * editor is activated and brought to top.
326 *
327 * @param traceElement
328 * the {@link TmfTraceElement} to open
329 */
330 public static void openTraceFromElement(final TmfCommonProjectElement traceElement) {
331
332 final IFile file;
333 try {
334 file = traceElement.createBookmarksFile();
335 } catch (final CoreException e) {
336 Activator.getDefault().logError(NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ' ' + traceElement.getName());
337 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
338 NLS.bind(Messages.TmfOpenTraceHelper_ErrorElement, traceElement.getTypeName()) + ENDL + ENDL + e.getMessage());
339 return;
340 }
341
342 final IWorkbench wb = PlatformUI.getWorkbench();
343 IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
344 if (window == null) {
345 return;
346 }
347 final IWorkbenchPage activePage = window.getActivePage();
348 final IEditorPart editor = findEditor(new FileEditorInput(file), true);
349 if (editor != null) {
350 activePage.activate(editor);
351 return;
352 }
353
354 // If a trace type is not set then delegate it to the eclipse platform
355 if ((traceElement instanceof TmfTraceElement) && (traceElement.getResource() instanceof IFile) && (traceElement.getTraceType() == null)) {
356 try {
357 boolean activate = OpenStrategy.activateOnOpen();
358 // only local open is supported
359 IDE.openEditor(activePage, file, activate);
360 } catch (PartInitException e) {
361 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
362 NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getElementPath()) + ENDL + ENDL + e.getMessage());
363 }
364 return;
365 }
366
367 Thread thread = new Thread() {
368 @Override
369 public void run() {
370 final ITmfTrace trace = openProjectElement(traceElement);
371
372 if (trace == null) {
373 return;
374 }
375
376 // Get the editor id from the extension point
377 String traceEditorId = traceElement.getEditorId();
378 final String editorId = (traceEditorId != null) ? traceEditorId : TmfEventsEditor.ID;
379 final IEditorInput editorInput = new TmfEditorInput(file, trace);
380
381 Display.getDefault().asyncExec(new Runnable() {
382 @Override
383 public void run() {
384 try {
385 activePage.openEditor(editorInput, editorId);
386 IDE.setDefaultEditor(file, editorId);
387 // editor should dispose the trace on close
388 } catch (final PartInitException e) {
389 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
390 NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ENDL + ENDL + e.getMessage());
391 Activator.getDefault().logError(NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ' ' + traceElement.getName());
392 trace.dispose();
393 }
394 }
395 });
396 }
397 };
398 thread.start();
399 }
400
401 /**
402 * Returns the editor with the specified input. Returns null if there is no
403 * opened editor with that input. If restore is requested, the method finds
404 * and returns the editor even if it is not restored yet after a restart.
405 *
406 * @param input
407 * the editor input
408 * @param restore
409 * true if the editor should be restored
410 * @return an editor with input equals to <code>input</code>
411 */
412 private static IEditorPart findEditor(IEditorInput input, boolean restore) {
413 final IWorkbench wb = PlatformUI.getWorkbench();
414 final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();
415 for (IEditorReference editorReference : activePage.getEditorReferences()) {
416 try {
417 IEditorInput editorInput = editorReference.getEditorInput();
418 if (editorInput.equals(input)) {
419 return editorReference.getEditor(restore);
420 }
421 } catch (PartInitException e) {
422 }
423 }
424 return null;
425 }
426
427 /**
428 * Reopen a trace or experiment from a project element in the provided
429 * editor
430 *
431 * @param traceElement
432 * the {@link TmfTraceElement} to open
433 * @param editor
434 * the reusable editor
435 */
436 public static void reopenTraceFromElement(final TmfCommonProjectElement traceElement, final IReusableEditor editor) {
437
438 final IFile file;
439 try {
440 file = traceElement.createBookmarksFile();
441 } catch (final CoreException e) {
442 Activator.getDefault().logError(NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ' ' + traceElement.getName());
443 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
444 NLS.bind(Messages.TmfOpenTraceHelper_ErrorElement, traceElement.getTypeName()) + ENDL + ENDL + e.getMessage());
445 return;
446 }
447
448 Thread thread = new Thread() {
449 @Override
450 public void run() {
451
452 final ITmfTrace trace = openProjectElement(traceElement);
453 if (trace == null) {
454 return;
455 }
456
457 final IEditorInput editorInput = new TmfEditorInput(file, trace);
458
459 Display.getDefault().asyncExec(new Runnable() {
460 @Override
461 public void run() {
462 final IWorkbench wb = PlatformUI.getWorkbench();
463 final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();
464 activePage.reuseEditor(editor, editorInput);
465 activePage.activate(editor);
466 }
467 });
468 }
469 };
470 thread.start();
471 }
472
473 }
This page took 0.041747 seconds and 5 git commands to generate.