1 /*******************************************************************************
2 * Copyright (c) 2011, 2013 Ericsson
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 * Patrick Tasse - Initial API and implementation
11 * Matthew Khouzam - Added import functionalities
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.core
.project
.model
;
17 import java
.util
.ArrayList
;
18 import java
.util
.HashMap
;
19 import java
.util
.LinkedHashMap
;
20 import java
.util
.LinkedList
;
21 import java
.util
.List
;
24 import org
.eclipse
.core
.resources
.IResource
;
25 import org
.eclipse
.core
.runtime
.CoreException
;
26 import org
.eclipse
.core
.runtime
.IConfigurationElement
;
27 import org
.eclipse
.core
.runtime
.Platform
;
28 import org
.eclipse
.linuxtools
.internal
.tmf
.core
.Activator
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.TmfCommonConstants
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomTxtTrace
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomTxtTraceDefinition
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomXmlTrace
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
.CustomXmlTraceDefinition
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalManager
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
38 * Utility class for accessing TMF trace type extensions from the platform's
39 * extensions registry.
42 * @author Patrick Tasse
43 * @author Matthew Khouzam
46 public final class TmfTraceType
{
48 private static final char SEPARATOR
= ':';
50 /** Extension point ID */
51 public static final String TMF_TRACE_TYPE_ID
= "org.eclipse.linuxtools.tmf.ui.tracetype"; //$NON-NLS-1$
53 /** Extension point element 'Category' */
54 public static final String CATEGORY_ELEM
= "category"; //$NON-NLS-1$
56 /** Extension point element 'Type' */
57 public static final String TYPE_ELEM
= "type"; //$NON-NLS-1$
59 /** Extension point element 'Default editor' */
60 public static final String DEFAULT_EDITOR_ELEM
= "defaultEditor"; //$NON-NLS-1$
62 /** Extension point element 'Events table type' */
63 public static final String EVENTS_TABLE_TYPE_ELEM
= "eventsTableType"; //$NON-NLS-1$
65 /** Extension point element 'Statistics viewer type' */
66 public static final String STATISTICS_VIEWER_ELEM
= "statisticsViewerType"; //$NON-NLS-1$
68 /** Extension point attribute 'ID' */
69 public static final String ID_ATTR
= "id"; //$NON-NLS-1$
71 /** Extension point attribute 'name' */
72 public static final String NAME_ATTR
= "name"; //$NON-NLS-1$
74 /** Extension point attribute 'category' */
75 public static final String CATEGORY_ATTR
= "category"; //$NON-NLS-1$
77 /** Extension point attribute 'trace_type' */
78 public static final String TRACE_TYPE_ATTR
= "trace_type"; //$NON-NLS-1$
80 /** Extension point attribute 'event_type' */
81 public static final String EVENT_TYPE_ATTR
= "event_type"; //$NON-NLS-1$
83 /** Extension point attribute 'icon' */
84 public static final String ICON_ATTR
= "icon"; //$NON-NLS-1$
86 /** Extension point attribute 'class' */
87 public static final String CLASS_ATTR
= "class"; //$NON-NLS-1$
90 * Custom text label used internally and therefore should not be
93 public static final String CUSTOM_TXT_CATEGORY
= "Custom Text"; //$NON-NLS-1$
96 * Custom XML label used internally and therefore should not be externalized
98 public static final String CUSTOM_XML_CATEGORY
= "Custom XML"; //$NON-NLS-1$
100 // The mapping of available trace type IDs to their corresponding
101 // configuration element
102 private final Map
<String
, IConfigurationElement
> fTraceTypeAttributes
= new HashMap
<>();
103 private final Map
<String
, IConfigurationElement
> fTraceCategories
= new HashMap
<>();
104 private final Map
<String
, TraceTypeHelper
> fTraceTypes
= new LinkedHashMap
<>();
106 private static TmfTraceType fInstance
= null;
109 * Retrieves the category name from the platform extension registry based on
114 * @return the category name or empty string if not found
116 public static String
getCategoryName(String categoryId
) {
117 IConfigurationElement
[] elements
= Platform
.getExtensionRegistry()
118 .getConfigurationElementsFor(TMF_TRACE_TYPE_ID
);
119 for (IConfigurationElement element
: elements
) {
120 if (element
.getName().equals(CATEGORY_ELEM
) && categoryId
.equals(element
.getAttribute(ID_ATTR
))) {
121 return element
.getAttribute(NAME_ATTR
);
124 return ""; //$NON-NLS-1$
128 * Retrieves and instantiates an element's object based on his plug-in
129 * definition for a specific trace type.
131 * The element's object is instantiated using its 0-argument constructor.
134 * The resource where to find the information about the trace
137 * The name of the element to find under the trace type
139 * @return a new Object based on his definition in plugin.xml, or null if no
140 * definition was found
142 public static Object
getTraceTypeElement(IResource resource
, String element
) {
144 if (resource
!= null) {
145 String traceType
= resource
.getPersistentProperty(TmfCommonConstants
.TRACETYPE
);
147 * Search in the configuration if there is any viewer specified
148 * for this kind of trace type.
150 for (IConfigurationElement ce
: TmfTraceType
.getTypeElements()) {
151 if (ce
.getAttribute(TmfTraceType
.ID_ATTR
).equals(traceType
)) {
152 IConfigurationElement
[] viewerCE
= ce
.getChildren(element
);
153 if (viewerCE
.length
!= 1) {
156 return viewerCE
[0].createExecutableExtension(TmfTraceType
.CLASS_ATTR
);
160 } catch (CoreException e
) {
161 Activator
.logError("Error creating the element from the resource", e
); //$NON-NLS-1$
167 * Retrieves all configuration elements from the platform extension registry
168 * for the trace type extension.
170 * @return an array of trace type configuration elements
172 public static IConfigurationElement
[] getTypeElements() {
173 IConfigurationElement
[] elements
= Platform
.getExtensionRegistry()
174 .getConfigurationElementsFor(TMF_TRACE_TYPE_ID
);
175 List
<IConfigurationElement
> typeElements
= new LinkedList
<>();
176 for (IConfigurationElement element
: elements
) {
177 if (element
.getName().equals(TYPE_ELEM
)) {
178 typeElements
.add(element
);
181 return typeElements
.toArray(new IConfigurationElement
[typeElements
.size()]);
184 private TmfTraceType() {
189 * The import utils instance
191 * @return the import utils instance
193 public static TmfTraceType
getInstance() {
194 if (fInstance
== null) {
195 fInstance
= new TmfTraceType();
200 // ------------------------------------------------------------------
202 // ------------------------------------------------------------------
205 * Retrieve the TraceTypeHelper for a given trace type ID
209 * @return The corresponding TraceTypeHelper, or null if there is none for
212 public TraceTypeHelper
getTraceTypeHelper(String id
) {
213 return fTraceTypes
.get(id
);
217 * Get an iterable view of the existing trace type IDs.
219 * @return The currently registered trace type IDs
221 public Iterable
<String
> getTraceTypeIDs() {
222 return fTraceTypes
.keySet();
226 * Returns a list of "category:tracetype , ..."
228 * @return returns a list of "category:tracetype , ..."
230 public String
[] getAvailableTraceTypes() {
232 // Generate the list of Category:TraceType to populate the ComboBox
233 List
<String
> traceTypes
= new ArrayList
<>();
235 for (String key
: this.fTraceTypes
.keySet()) {
236 TraceTypeHelper tt
= this.fTraceTypes
.get(key
);
237 traceTypes
.add(tt
.getCategoryName() + SEPARATOR
+ tt
.getName());
241 return traceTypes
.toArray(new String
[traceTypes
.size()]);
245 * Gets the custom trace types (custom text and friends)
248 * the type to get (Text, xml or other...)
249 * @return the list of custom trace types
251 public static List
<String
> getCustomTraceTypes(String type
) {
252 List
<String
> traceTypes
= new ArrayList
<>();
253 if (type
.equals(CUSTOM_TXT_CATEGORY
)) {
254 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
255 String traceTypeName
= def
.definitionName
;
256 traceTypes
.add(traceTypeName
);
259 if (type
.equals(CUSTOM_XML_CATEGORY
)) {
260 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
261 String traceTypeName
= def
.definitionName
;
262 traceTypes
.add(traceTypeName
);
269 * Gets all the custom trace types
271 * @return the list of custom trace types
273 public static List
<String
> getCustomTraceTypes() {
275 List
<String
> traceTypes
= new ArrayList
<>();
276 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
277 String traceTypeName
= def
.definitionName
;
278 traceTypes
.add(traceTypeName
);
280 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
281 String traceTypeName
= def
.definitionName
;
282 traceTypes
.add(traceTypeName
);
287 private void populateCustomTraceTypes() {
288 // add the custom trace types
289 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
290 String traceTypeId
= CustomTxtTrace
.class.getCanonicalName() + SEPARATOR
+ def
.definitionName
;
291 ITmfTrace trace
= new CustomTxtTrace(def
);
292 TraceTypeHelper tt
= new TraceTypeHelper(traceTypeId
, CUSTOM_TXT_CATEGORY
, def
.definitionName
, trace
);
293 fTraceTypes
.put(traceTypeId
, tt
);
294 // Deregister trace as signal handler because it is only used for validation
295 TmfSignalManager
.deregister(trace
);
297 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
298 String traceTypeId
= CustomXmlTrace
.class.getCanonicalName() + SEPARATOR
+ def
.definitionName
;
299 ITmfTrace trace
= new CustomXmlTrace(def
);
300 TraceTypeHelper tt
= new TraceTypeHelper(traceTypeId
, CUSTOM_XML_CATEGORY
, def
.definitionName
, trace
);
301 fTraceTypes
.put(traceTypeId
, tt
);
302 // Deregister trace as signal handler because it is only used for validation
303 TmfSignalManager
.deregister(trace
);
308 * Add or replace a custom trace type
311 * The custom parser category
312 * @param definitionName
313 * The custom parser definition name to add or replace
315 public void addCustomTraceType(String category
, String definitionName
) {
316 String traceTypeId
= null;
317 ITmfTrace trace
= null;
319 if (category
.equals(CUSTOM_TXT_CATEGORY
)) {
320 traceTypeId
= CustomTxtTrace
.class.getCanonicalName() + SEPARATOR
+ definitionName
;
321 CustomTxtTraceDefinition def
= CustomTxtTraceDefinition
.load(definitionName
);
323 trace
= new CustomTxtTrace(def
);
325 } else if (category
.equals(CUSTOM_XML_CATEGORY
)) {
326 traceTypeId
= CustomXmlTrace
.class.getCanonicalName() + SEPARATOR
+ definitionName
;
327 CustomXmlTraceDefinition def
= CustomXmlTraceDefinition
.load(definitionName
);
329 trace
= new CustomXmlTrace(def
);
333 if (traceTypeId
!= null && trace
!= null) {
334 TraceTypeHelper helper
= fTraceTypes
.get(traceTypeId
);
335 if (helper
!= null) {
336 helper
.getTrace().dispose();
338 TraceTypeHelper tt
= new TraceTypeHelper(traceTypeId
, category
, definitionName
, trace
);
339 fTraceTypes
.put(traceTypeId
, tt
);
340 // Deregister trace as signal handler because it is only used for validation
341 TmfSignalManager
.deregister(trace
);
346 * Remove a custom trace type
349 * The custom parser category
350 * @param definitionName
351 * The custom parser definition name to add or replace
353 public void removeCustomTraceType(String category
, String definitionName
) {
354 if (category
.equals(CUSTOM_TXT_CATEGORY
)) {
355 String traceTypeId
= CustomTxtTrace
.class.getCanonicalName() + SEPARATOR
+ definitionName
;
356 TraceTypeHelper helper
= fTraceTypes
.remove(traceTypeId
);
357 if (helper
!= null) {
358 helper
.getTrace().dispose();
360 } else if (category
.equals(CUSTOM_XML_CATEGORY
)) {
361 String traceTypeId
= CustomXmlTrace
.class.getCanonicalName() + SEPARATOR
+ definitionName
;
362 TraceTypeHelper helper
= fTraceTypes
.remove(traceTypeId
);
363 if (helper
!= null) {
364 helper
.getTrace().dispose();
370 * Gets a trace type for a given canonical id
373 * the ID of the trace
374 * @return the return type
376 public TraceTypeHelper
getTraceType(String id
) {
377 return fTraceTypes
.get(id
);
380 private void populateCategoriesAndTraceTypes() {
381 if (fTraceTypes
.isEmpty()) {
382 // Populate the Categories and Trace Types
383 IConfigurationElement
[] config
= Platform
.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType
.TMF_TRACE_TYPE_ID
);
384 for (IConfigurationElement ce
: config
) {
385 String elementName
= ce
.getName();
386 if (elementName
.equals(TmfTraceType
.TYPE_ELEM
)) {
387 String traceTypeId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
388 fTraceTypeAttributes
.put(traceTypeId
, ce
);
389 } else if (elementName
.equals(TmfTraceType
.CATEGORY_ELEM
)) {
390 String categoryId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
391 fTraceCategories
.put(categoryId
, ce
);
394 // create the trace types
395 for (String typeId
: fTraceTypeAttributes
.keySet()) {
396 IConfigurationElement ce
= fTraceTypeAttributes
.get(typeId
);
397 final String category
= getCategory(ce
);
398 final String attribute
= ce
.getAttribute(TmfTraceType
.NAME_ATTR
);
399 ITmfTrace trace
= null;
401 trace
= (ITmfTrace
) ce
.createExecutableExtension(TmfTraceType
.TRACE_TYPE_ATTR
);
402 // Deregister trace as signal handler because it is only used for validation
403 TmfSignalManager
.deregister(trace
);
404 } catch (CoreException e
) {
406 TraceTypeHelper tt
= new TraceTypeHelper(typeId
, category
, attribute
, trace
);
407 fTraceTypes
.put(typeId
, tt
);
412 private String
getCategory(IConfigurationElement ce
) {
413 final String categoryId
= ce
.getAttribute(TmfTraceType
.CATEGORY_ATTR
);
414 if (categoryId
!= null) {
415 IConfigurationElement category
= fTraceCategories
.get(categoryId
);
416 if (category
!= null && !category
.getName().equals("")) { //$NON-NLS-1$
417 return category
.getAttribute(TmfTraceType
.NAME_ATTR
);
420 return "[no category]"; //$NON-NLS-1$
424 * Returns the list of trace categories
426 * @return the list of trace categories
428 public List
<String
> getTraceCategories() {
429 List
<String
> categoryNames
= new ArrayList
<>();
430 for (String key
: fTraceTypes
.keySet()) {
431 final String categoryName
= fTraceTypes
.get(key
).getCategoryName();
432 if (!categoryNames
.contains(categoryName
)) {
433 categoryNames
.add(categoryName
);
436 return categoryNames
;
440 * Get the trace type helper classes from category name
442 * @param categoryName
443 * the categoryName to lookup
444 * @return a list of trace type helper classes {@link TraceTypeHelper}
446 public List
<TraceTypeHelper
> getTraceTypes(String categoryName
) {
447 List
<TraceTypeHelper
> traceNames
= new ArrayList
<>();
448 for (String key
: fTraceTypes
.keySet()) {
449 final String storedCategoryName
= fTraceTypes
.get(key
).getCategoryName();
450 if (storedCategoryName
.equals(categoryName
)) {
451 traceNames
.add(fTraceTypes
.get(key
));
457 private void init() {
458 populateCategoriesAndTraceTypes();
459 populateCustomTraceTypes();
464 * Validate a trace type
466 * @param traceTypeName
467 * the trace category (canonical name)
469 * the file name (and path)
470 * @return true if the trace is of a valid type
472 public boolean validate(String traceTypeName
, String fileName
) {
473 if (traceTypeName
!= null && !traceTypeName
.isEmpty()) {
474 final TraceTypeHelper traceTypeHelper
= fTraceTypes
.get(traceTypeName
);
475 if (!traceTypeHelper
.validate(fileName
)) {
485 * @param traceToValidate
486 * the trace category (canonical name)
487 * @return true if the trace is of a valid type
489 public boolean validate(TraceValidationHelper traceToValidate
) {
490 return validate(traceToValidate
.getTraceType(), traceToValidate
.getTraceToScan());
494 * Validate a list of files with a tracetype
496 * @param traceTypeName
497 * the trace category (canonical name)
499 * the list of files to check if they are trace
500 * @return true if all the traces are valid
502 public boolean validateTraceFiles(String traceTypeName
, List
<File
> traces
) {
503 if (traceTypeName
!= null && !"".equals(traceTypeName
) && //$NON-NLS-1$
504 !traceTypeName
.startsWith(TmfTraceType
.CUSTOM_TXT_CATEGORY
) && !traceTypeName
.startsWith(TmfTraceType
.CUSTOM_XML_CATEGORY
)) {
505 for (File trace
: traces
) {
506 if (!validate(traceTypeName
, trace
.getAbsolutePath())) {
515 * Get a configuration element for a given name
519 * @return the configuration element, can be null
521 public IConfigurationElement
getTraceAttributes(String traceType
) {
522 return fTraceTypeAttributes
.get(traceType
);
526 * Find the id of a trace type by its parameters
529 * like "ctf" or "custom text"
532 * @return an id like "org.eclipse.linuxtools.blabla...
534 public String
getTraceTypeId(String category
, String traceType
) {
535 for (String key
: fTraceTypes
.keySet()) {
536 if (fTraceTypes
.get(key
).getCategoryName().equals(category
.trim()) && fTraceTypes
.get(key
).getName().equals(traceType
.trim())) {
544 * Gets the custom trace type ID from the custom trace name
547 * The trace type in human form (category:name)
548 * @return the trace type ID or null if the trace is not a custom one
550 public static String
getCustomTraceTypeId(String traceType
) {
551 String traceTypeId
= null;
553 // do custom trace stuff here
554 String traceTypeToken
[] = traceType
.split(":", 2); //$NON-NLS-1$
555 if (traceTypeToken
.length
== 2) {
556 final boolean startsWithTxt
= traceType
.startsWith(TmfTraceType
.CUSTOM_TXT_CATEGORY
);
557 final boolean startsWithXML
= traceType
.startsWith(TmfTraceType
.CUSTOM_XML_CATEGORY
);
559 traceTypeId
= CustomTxtTrace
.class.getCanonicalName() + SEPARATOR
+ traceTypeToken
[1];
560 } else if (startsWithXML
) {
561 traceTypeId
= CustomXmlTrace
.class.getCanonicalName() + SEPARATOR
+ traceTypeToken
[1];
568 * Is the trace a custom (user-defined) trace type. These are the traces
569 * like : text and xml defined by the custom trace wizard.
572 * the trace type in human form (category:name)
573 * @return true if the trace is a custom type
575 public static boolean isCustomTrace(String traceType
) {
576 final boolean startsWithTxt
= traceType
.startsWith(TmfTraceType
.CUSTOM_TXT_CATEGORY
);
577 final boolean startsWithXML
= traceType
.startsWith(TmfTraceType
.CUSTOM_XML_CATEGORY
);
578 return (startsWithTxt
|| startsWithXML
);