1 /**********************************************************************
2 * Copyright (c) 2013, 2014 Ericsson, École Polytechnique de Montréal
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
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 **********************************************************************/
16 package org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
;
19 import java
.io
.IOException
;
20 import java
.util
.List
;
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
;
63 * Helper class for opening trace resources and loading them to a tracing
66 * @author Matthew Khouzam
68 public class TmfOpenTraceHelper
{
70 private TmfOpenTraceHelper() {
73 private static final String ENDL
= System
.getProperty("line.separator"); //$NON-NLS-1$
76 * Opens a trace from a path while importing it to the destination folder.
77 * The trace is linked as a resource.
79 * @param destinationFolder
80 * The destination trace folder
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
90 public static IStatus
openTraceFromPath(TmfTraceFolder destinationFolder
, String path
, Shell shell
) throws CoreException
{
91 return openTraceFromPath(destinationFolder
, path
, shell
, null);
95 * Opens a trace from a path while importing it to the destination folder.
96 * The trace is linked as a resource.
98 * @param destinationFolder
99 * The destination trace folder
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
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;
115 traceTypeToSet
= TmfTraceTypeUIUtils
.selectTraceType(pathToUse
, null, tracetypeHint
);
116 } catch (TmfTraceImportException e
) {
117 MessageBox mb
= new MessageBox(shell
);
118 mb
.setMessage(e
.getMessage());
120 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, e
.getMessage());
123 IFolder folder
= destinationFolder
.getResource();
124 String traceName
= getTraceName(pathToUse
, folder
);
125 if (traceExists(pathToUse
, folder
)) {
126 return openTraceFromFolder(destinationFolder
, traceName
);
128 final IPath pathString
= Path
.fromOSString(pathToUse
);
129 IResource linkedTrace
= TmfImportHelper
.createLink(folder
, pathString
, traceName
);
131 if (linkedTrace
== null || !linkedTrace
.exists()) {
132 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
,
133 Messages
.TmfOpenTraceHelper_LinkFailed
);
136 String sourceLocation
= URIUtil
.toUnencodedString(pathString
.toFile().toURI());
137 linkedTrace
.setPersistentProperty(TmfCommonConstants
.SOURCE_LOCATION
, sourceLocation
);
139 // No trace type was determined.
140 if (traceTypeToSet
== null) {
141 return Status
.OK_STATUS
;
144 IStatus ret
= TmfTraceTypeUIUtils
.setTraceType(linkedTrace
, traceTypeToSet
);
146 ret
= openTraceFromFolder(destinationFolder
, traceName
);
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.
158 * @return path to use for trace type validation.
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
)) {
169 // Second check grandparent
170 File grandParent
= parent
.getParentFile();
171 if (grandParent
!= null) {
172 pathToUse
= grandParent
.getAbsolutePath();
173 if (TmfTraceType
.isDirectoryTrace(pathToUse
)) {
181 private static boolean traceExists(String path
, IFolder folder
) {
182 String val
= getTraceName(path
, folder
);
183 return (folder
.findMember(val
) != null);
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();
192 file
= file
.getCanonicalFile();
193 } catch (IOException e
) {
194 /* just use original file path */
196 return !file
.equals(traceFile
);
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
209 * the folder to import to
210 * @return the filename
212 private static String
getTraceName(String path
, IFolder folder
) {
214 File traceFile
= new File(path
);
216 traceFile
= traceFile
.getCanonicalFile();
217 } catch (IOException e
) {
218 /* just use original file path */
220 name
= traceFile
.getName();
221 for (int i
= 2; isWrongMember(folder
, name
, traceFile
); i
++) {
222 name
= traceFile
.getName() + '(' + i
+ ')';
228 * Open a trace from a trace folder
230 * @param destinationFolder
231 * The destination trace folder
234 * @return success or error
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
;
244 if (traceElement
== null) {
245 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, NLS
.bind(Messages
.TmfOpenTraceHelper_TraceNotFound
, traceName
));
247 openTraceFromElement(traceElement
);
248 return Status
.OK_STATUS
;
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
);
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
);
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()));
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
);
290 // Since trace is under an experiment, use the original trace from
292 element
= element
.getElementUnderTraceFolder();
294 ITmfTrace trace
= openTraceElement(element
);
297 for (int j
= 0; j
< i
; j
++) {
302 cacheSize
= Math
.min(cacheSize
, trace
.getCacheSize());
307 // Create the experiment
308 experiment
.initExperiment(ITmfEvent
.class, experimentElement
.getName(), traces
, cacheSize
, experimentElement
.getResource());
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
);
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.
327 * @param traceElement
328 * the {@link TmfTraceElement} to open
330 public static void openTraceFromElement(final TmfCommonProjectElement traceElement
) {
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());
342 final IWorkbench wb
= PlatformUI
.getWorkbench();
343 IWorkbenchWindow window
= wb
.getActiveWorkbenchWindow();
344 if (window
== null) {
347 final IWorkbenchPage activePage
= window
.getActivePage();
348 final IEditorPart editor
= findEditor(new FileEditorInput(file
), true);
349 if (editor
!= null) {
350 activePage
.activate(editor
);
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)) {
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());
367 Thread thread
= new Thread() {
370 final ITmfTrace trace
= openProjectElement(traceElement
);
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
);
381 Display
.getDefault().asyncExec(new Runnable() {
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());
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.
409 * true if the editor should be restored
410 * @return an editor with input equals to <code>input</code>
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()) {
417 IEditorInput editorInput
= editorReference
.getEditorInput();
418 if (editorInput
.equals(input
)) {
419 return editorReference
.getEditor(restore
);
421 } catch (PartInitException e
) {
428 * Reopen a trace or experiment from a project element in the provided
431 * @param traceElement
432 * the {@link TmfTraceElement} to open
434 * the reusable editor
436 public static void reopenTraceFromElement(final TmfCommonProjectElement traceElement
, final IReusableEditor editor
) {
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());
448 Thread thread
= new Thread() {
452 final ITmfTrace trace
= openProjectElement(traceElement
);
457 final IEditorInput editorInput
= new TmfEditorInput(file
, trace
);
459 Display
.getDefault().asyncExec(new Runnable() {
462 final IWorkbench wb
= PlatformUI
.getWorkbench();
463 final IWorkbenchPage activePage
= wb
.getActiveWorkbenchWindow().getActivePage();
464 activePage
.reuseEditor(editor
, editorInput
);
465 activePage
.activate(editor
);