1 /*******************************************************************************
2 * Copyright (c) 2010, 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 * Bernd Hufmann - Added supplementary files handling (in class TmfTraceElement)
11 * Geneviève Bastien - Copied supplementary files handling from TmfTracElement
12 * Moved to this class code to copy a model element
13 * Renamed from TmfWithFolderElement to TmfCommonProjectElement
14 *******************************************************************************/
16 package org
.eclipse
.linuxtools
.tmf
.ui
.project
.model
;
18 import java
.io
.ByteArrayInputStream
;
19 import java
.io
.InputStream
;
20 import java
.util
.ArrayList
;
21 import java
.util
.HashMap
;
22 import java
.util
.List
;
25 import org
.eclipse
.core
.resources
.IFile
;
26 import org
.eclipse
.core
.resources
.IFolder
;
27 import org
.eclipse
.core
.resources
.IResource
;
28 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
29 import org
.eclipse
.core
.runtime
.CoreException
;
30 import org
.eclipse
.core
.runtime
.IPath
;
31 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
32 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Activator
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.TmfCommonConstants
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.analysis
.IAnalysisModuleHelper
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.analysis
.TmfAnalysisManager
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomTxtTrace
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomTxtTraceDefinition
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomXmlTrace
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomXmlTraceDefinition
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.project
.model
.TmfTraceType
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.project
.model
.TraceTypeHelper
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalManager
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTraceManager
;
49 import org
.eclipse
.osgi
.util
.NLS
;
50 import org
.eclipse
.ui
.IEditorReference
;
51 import org
.eclipse
.ui
.IWorkbench
;
52 import org
.eclipse
.ui
.IWorkbenchPage
;
53 import org
.eclipse
.ui
.IWorkbenchWindow
;
54 import org
.eclipse
.ui
.PartInitException
;
55 import org
.eclipse
.ui
.PlatformUI
;
56 import org
.eclipse
.ui
.part
.FileEditorInput
;
59 * Base class for tracing project elements: it implements the common behavior of
60 * all project elements: supplementary files, analysis, types, etc.
62 * @author Geneviève Bastien
65 public abstract class TmfCommonProjectElement
extends TmfProjectModelElement
{
67 // ------------------------------------------------------------------------
69 // ------------------------------------------------------------------------
71 // This trace type ID as defined in plugin.xml
72 private String fTraceTypeId
= null;
74 private static final String BOOKMARKS_HIDDEN_FILE
= ".bookmarks"; //$NON-NLS-1$
76 // ------------------------------------------------------------------------
78 // ------------------------------------------------------------------------
81 * Constructor. Creates model element.
84 * The name of the element
90 public TmfCommonProjectElement(String name
, IResource resource
, TmfProjectModelElement parent
) {
91 super(name
, resource
, parent
);
92 parent
.addChild(this);
94 TmfSignalManager
.register(this);
97 // ------------------------------------------------------------------------
98 // TmfProjectModelElement
99 // ------------------------------------------------------------------------
102 void refreshChildren() {
104 /* Refreshes the analysis under this trace */
105 Map
<String
, TmfAnalysisElement
> childrenMap
= new HashMap
<>();
106 for (TmfAnalysisElement analysis
: getAvailableAnalysis()) {
107 childrenMap
.put(analysis
.getAnalysisId(), analysis
);
110 TraceTypeHelper helper
= TmfTraceType
.getInstance().getTraceType(getTraceType());
112 Class
<?
extends ITmfTrace
> traceClass
= null;
114 if (helper
== null && getTraceType() != null) {
115 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
116 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
117 if (fTraceTypeId
.equals(CustomTxtTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
118 traceClass
= CustomTxtTrace
.class;
122 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
123 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
124 if (fTraceTypeId
.equals(CustomXmlTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
125 traceClass
= CustomTxtTrace
.class;
129 } else if (helper
!= null) {
130 traceClass
= helper
.getTraceClass();
133 /* Remove all analysis and return */
134 if (traceClass
== null) {
135 for (TmfAnalysisElement analysis
: childrenMap
.values()) {
136 removeChild(analysis
);
141 /** Get the base path to put the resource to */
142 IPath path
= fResource
.getFullPath();
144 /* Add all new analysis modules or refresh outputs of existing ones */
145 for (IAnalysisModuleHelper module
: TmfAnalysisManager
.getAnalysisModules(traceClass
).values()) {
147 /* If the analysis is not a child of the trace, create it */
148 TmfAnalysisElement analysis
= childrenMap
.remove(module
.getId());
149 if (analysis
== null) {
151 * No need for the resource to exist, nothing will be done with
154 IFolder newresource
= ResourcesPlugin
.getWorkspace().getRoot().getFolder(path
.append(module
.getId()));
155 analysis
= new TmfAnalysisElement(module
.getName(), newresource
, this, module
.getId());
157 analysis
.refreshChildren();
160 /* Remove analysis that are not children of this trace anymore */
161 for (TmfAnalysisElement analysis
: childrenMap
.values()) {
162 removeChild(analysis
);
166 // ------------------------------------------------------------------------
168 // ------------------------------------------------------------------------
171 * Returns the trace type ID.
173 * @return trace type ID.
175 public String
getTraceType() {
180 * Refreshes the trace type filed by reading the trace type persistent
181 * property of the resource referenece.
183 public void refreshTraceType() {
185 fTraceTypeId
= getResource().getPersistentProperty(TmfCommonConstants
.TRACETYPE
);
186 } catch (CoreException e
) {
187 Activator
.getDefault().logError(NLS
.bind(Messages
.TmfCommonProjectElement_ErrorRefreshingProperty
, getName()), e
);
192 * Instantiate a <code>ITmfTrace</code> object based on the trace type and
193 * the corresponding extension.
195 * @return the <code>ITmfTrace</code> or <code>null</code> for an error
197 public abstract ITmfTrace
instantiateTrace();
200 * Return the resource name for this element
202 * @return The name of the resource for this element
204 protected String
getResourceName() {
205 return fResource
.getName() + getSuffix();
209 * @return The suffix for resource names
211 protected String
getSuffix() {
212 return ""; //$NON-NLS-1$
216 * Returns a list of TmfTraceElements contained in project element.
218 * @return a list of TmfTraceElements, empty list if none
220 public List
<TmfTraceElement
> getTraces() {
221 return new ArrayList
<>();
225 * Get the instantiated trace associated with this element.
227 * @return The instantiated trace or null if trace is not (yet) available
229 public ITmfTrace
getTrace() {
230 for (ITmfTrace trace
: TmfTraceManager
.getInstance().getOpenedTraces()) {
231 if (trace
.getResource().equals(getResource())) {
239 * Returns the file resource used to store bookmarks after creating it if
240 * necessary. If the trace resource is a file, it is returned directly. If
241 * the trace resource is a folder, a linked file is returned. The file will
242 * be created if it does not exist.
244 * @return the bookmarks file
245 * @throws CoreException
246 * if the bookmarks file cannot be created
248 public abstract IFile
createBookmarksFile() throws CoreException
;
251 * Actually returns the bookmark file or creates it in the project element's
254 * @param bookmarksFolder
255 * Folder where to put the bookmark file
257 * The canonical name to set as tracetype
258 * @return The bookmark file
259 * @throws CoreException
260 * if the bookmarks file cannot be created
262 protected IFile
createBookmarksFile(IFolder bookmarksFolder
, String traceType
) throws CoreException
{
263 IFile file
= getBookmarksFile();
264 if (!file
.exists()) {
265 final IFile bookmarksFile
= bookmarksFolder
.getFile(BOOKMARKS_HIDDEN_FILE
);
266 if (!bookmarksFile
.exists()) {
267 final InputStream source
= new ByteArrayInputStream(new byte[0]);
268 bookmarksFile
.create(source
, true, null);
270 bookmarksFile
.setHidden(true);
271 file
.createLink(bookmarksFile
.getLocation(), IResource
.REPLACE
, null);
272 file
.setHidden(true);
273 file
.setPersistentProperty(TmfCommonConstants
.TRACETYPE
, traceType
);
279 * Returns the optional editor ID from the trace type extension.
281 * @return the editor ID or <code>null</code> if not defined.
283 public abstract String
getEditorId();
286 * Returns the file resource used to store bookmarks. The file may not
289 * @return the bookmarks file
291 public IFile
getBookmarksFile() {
292 final IFolder folder
= (IFolder
) fResource
;
293 IFile file
= folder
.getFile(getName() + '_');
298 * Close open editors associated with this experiment.
300 public void closeEditors() {
301 IFile file
= getBookmarksFile();
302 FileEditorInput input
= new FileEditorInput(file
);
303 IWorkbench wb
= PlatformUI
.getWorkbench();
304 for (IWorkbenchWindow wbWindow
: wb
.getWorkbenchWindows()) {
305 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
306 for (IEditorReference editorReference
: wbPage
.getEditorReferences()) {
308 if (editorReference
.getEditorInput().equals(input
)) {
309 wbPage
.closeEditor(editorReference
.getEditor(false), false);
311 } catch (PartInitException e
) {
312 Activator
.getDefault().logError(NLS
.bind(Messages
.TmfCommonProjectElement_ErrorClosingEditor
, getName()), e
);
320 * Get a friendly name for the type of element this common project element
321 * is, to be displayed in UI messages.
323 * @return A string for the type of project element this object is, for
324 * example "trace" or "experiment"
326 public abstract String
getTypeName();
329 * Copy this model element
332 * The name of the new element
333 * @param copySuppFiles
334 * Whether to copy supplementary files or not
335 * @return the new Resource object
337 public IResource
copy(final String newName
, final boolean copySuppFiles
) {
339 final IPath newPath
= getParent().getResource().getFullPath().addTrailingSeparator().append(newName
);
341 /* Copy supplementary files first, only if needed */
343 copySupplementaryFolder(newName
);
347 getResource().copy(newPath
, IResource
.FORCE
| IResource
.SHALLOW
, null);
349 /* Delete any bookmarks file found in copied trace folder */
350 IFolder folder
= ((IFolder
) getParent().getResource()).getFolder(newName
);
351 if (folder
.exists()) {
352 for (IResource member
: folder
.members()) {
353 if (TmfTrace
.class.getCanonicalName().equals(member
.getPersistentProperty(TmfCommonConstants
.TRACETYPE
))) {
354 member
.delete(true, null);
355 } else if (TmfExperiment
.class.getCanonicalName().equals(member
.getPersistentProperty(TmfCommonConstants
.TRACETYPE
))) {
356 member
.delete(true, null);
361 } catch (CoreException e
) {
368 * Get the list of analysis elements
370 * @return Array of analysis elements
372 public List
<TmfAnalysisElement
> getAvailableAnalysis() {
373 List
<ITmfProjectModelElement
> children
= getChildren();
374 List
<TmfAnalysisElement
> analysis
= new ArrayList
<>();
375 for (ITmfProjectModelElement child
: children
) {
376 if (child
instanceof TmfAnalysisElement
) {
377 analysis
.add((TmfAnalysisElement
) child
);
383 // ------------------------------------------------------------------------
384 // Supplementary files operations
385 // ------------------------------------------------------------------------
388 * Deletes this element specific supplementary folder.
390 public void deleteSupplementaryFolder() {
391 IFolder supplFolder
= getTraceSupplementaryFolder(getResourceName());
392 if (supplFolder
.exists()) {
394 supplFolder
.delete(true, new NullProgressMonitor());
395 } catch (CoreException e
) {
396 Activator
.getDefault().logError("Error deleting supplementary folder " + supplFolder
, e
); //$NON-NLS-1$
402 * Renames the element specific supplementary folder according to the new
406 * The new element name
408 public void renameSupplementaryFolder(String newName
) {
409 IFolder oldSupplFolder
= getTraceSupplementaryFolder(getResourceName());
410 IFolder newSupplFolder
= getTraceSupplementaryFolder(newName
+ getSuffix());
412 // Rename supplementary folder
413 if (oldSupplFolder
.exists()) {
415 oldSupplFolder
.move(newSupplFolder
.getFullPath(), true, new NullProgressMonitor());
416 } catch (CoreException e
) {
417 Activator
.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder
, e
); //$NON-NLS-1$
423 * Copies the element specific supplementary folder to the new element name.
426 * The new element name
428 public void copySupplementaryFolder(String newName
) {
429 IFolder oldSupplFolder
= getTraceSupplementaryFolder(getResourceName());
430 IFolder newSupplFolder
= getTraceSupplementaryFolder(newName
+ getSuffix());
432 // copy supplementary folder
433 if (oldSupplFolder
.exists()) {
435 oldSupplFolder
.copy(newSupplFolder
.getFullPath(), true, new NullProgressMonitor());
436 } catch (CoreException e
) {
437 Activator
.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder
, e
); //$NON-NLS-1$
443 * Copies the element specific supplementary folder a new folder.
446 * The destination folder to copy to.
448 public void copySupplementaryFolder(IFolder destination
) {
449 IFolder oldSupplFolder
= getTraceSupplementaryFolder(getResourceName());
451 // copy supplementary folder
452 if (oldSupplFolder
.exists()) {
454 oldSupplFolder
.copy(destination
.getFullPath(), true, new NullProgressMonitor());
455 } catch (CoreException e
) {
456 Activator
.getDefault().logError("Error copying supplementary folder " + oldSupplFolder
, e
); //$NON-NLS-1$
462 * Refreshes the element specific supplementary folder information. It
463 * creates the folder if not exists. It sets the persistence property of the
466 public void refreshSupplementaryFolder() {
467 createSupplementaryDirectory();
471 * Checks if supplementary resource exist or not.
473 * @return <code>true</code> if one or more files are under the element
474 * supplementary folder
476 public boolean hasSupplementaryResources() {
477 IResource
[] resources
= getSupplementaryResources();
478 return (resources
.length
> 0);
482 * Returns the supplementary resources under the trace supplementary folder.
484 * @return array of resources under the trace supplementary folder.
486 public IResource
[] getSupplementaryResources() {
487 IFolder supplFolder
= getTraceSupplementaryFolder(getResourceName());
488 if (supplFolder
.exists()) {
490 return supplFolder
.members();
491 } catch (CoreException e
) {
492 Activator
.getDefault().logError("Error deleting supplementary folder " + supplFolder
, e
); //$NON-NLS-1$
495 return new IResource
[0];
499 * Deletes the given resources.
502 * array of resources to delete.
504 public void deleteSupplementaryResources(IResource
[] resources
) {
506 for (int i
= 0; i
< resources
.length
; i
++) {
508 resources
[i
].delete(true, new NullProgressMonitor());
509 } catch (CoreException e
) {
510 Activator
.getDefault().logError("Error deleting supplementary resource " + resources
[i
], e
); //$NON-NLS-1$
516 * Deletes all supplementary resources in the supplementary directory
518 public void deleteSupplementaryResources() {
519 deleteSupplementaryResources(getSupplementaryResources());
522 private void createSupplementaryDirectory() {
523 IFolder supplFolder
= getTraceSupplementaryFolder(getResourceName());
524 if (!supplFolder
.exists()) {
526 supplFolder
.create(true, true, new NullProgressMonitor());
527 } catch (CoreException e
) {
528 Activator
.getDefault().logError("Error creating resource supplementary file " + supplFolder
, e
); //$NON-NLS-1$
533 fResource
.setPersistentProperty(TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER
, supplFolder
.getLocationURI().getPath());
534 } catch (CoreException e
) {
535 Activator
.getDefault().logError("Error setting persistant property " + TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER
, e
); //$NON-NLS-1$
540 // -------------------------------------------------------
542 // -------------------------------------------------------
545 * Handler for the Trace Opened signal
548 * The incoming signal
551 public void traceOpened(TmfTraceOpenedSignal signal
) {
552 IResource resource
= signal
.getTrace().getResource();
553 if ((resource
== null) || !resource
.equals(getResource())) {
557 getParent().refresh();