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