Make Custom Parser trace type backwards compatible to Linux Tools
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / project / model / TmfTraceType.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 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 * Patrick Tasse - Initial API and implementation
11 * Matthew Khouzam - Added import functionalities
12 * Geneviève Bastien - Added support for experiment types
13 * Bernd Hufmann - Updated custom trace type ID handling
14 *******************************************************************************/
15
16 package org.eclipse.tracecompass.tmf.core.project.model;
17
18 import java.io.File;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.LinkedHashMap;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.IConfigurationElement;
31 import org.eclipse.core.runtime.Platform;
32 import org.eclipse.tracecompass.internal.tmf.core.Activator;
33 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
34 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTrace;
35 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition;
36 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace;
37 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition;
38 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
39 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
40
41 /**
42 * Utility class for accessing TMF trace type extensions from the platform's
43 * extensions registry.
44 *
45 * @version 1.0
46 * @author Patrick Tasse
47 * @author Matthew Khouzam
48 * @since 3.0
49 */
50 public final class TmfTraceType {
51
52 // ------------------------------------------------------------------
53 // Constants
54 // ------------------------------------------------------------------
55
56 /** Extension point ID */
57 public static final String TMF_TRACE_TYPE_ID = "org.eclipse.linuxtools.tmf.core.tracetype"; //$NON-NLS-1$
58
59 /** Extension point element 'Category' */
60 public static final String CATEGORY_ELEM = "category"; //$NON-NLS-1$
61
62 /** Extension point element 'Type' */
63 public static final String TYPE_ELEM = "type"; //$NON-NLS-1$
64
65 /** Extension point element 'Experiment' */
66 public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$
67
68 /** Extension point attribute 'ID' */
69 public static final String ID_ATTR = "id"; //$NON-NLS-1$
70
71 /** Extension point attribute 'name' */
72 public static final String NAME_ATTR = "name"; //$NON-NLS-1$
73
74 /** Extension point attribute 'category' */
75 public static final String CATEGORY_ATTR = "category"; //$NON-NLS-1$
76
77 /** Extension point attribute 'trace_type' */
78 public static final String TRACE_TYPE_ATTR = "trace_type"; //$NON-NLS-1$
79
80 /** Extension point attribute 'event_type' */
81 public static final String EVENT_TYPE_ATTR = "event_type"; //$NON-NLS-1$
82
83 /** Extension point attribute 'experiment_type' */
84 public static final String EXPERIMENT_TYPE_ATTR = "experiment_type"; //$NON-NLS-1$
85
86 /** Extension point attribute 'isDirectory' */
87 public static final String IS_DIR_ATTR = "isDirectory"; //$NON-NLS-1$
88
89 /** Default experiment type */
90 public static final String DEFAULT_EXPERIMENT_TYPE = "org.eclipse.linuxtools.tmf.core.experiment.generic"; //$NON-NLS-1$
91
92 // The mapping of available trace type IDs to their corresponding
93 // configuration element
94 private static final Map<String, IConfigurationElement> TRACE_TYPE_ATTRIBUTES = new HashMap<>();
95 private static final Map<String, IConfigurationElement> TRACE_CATEGORIES = new HashMap<>();
96 private static final Map<String, TraceTypeHelper> TRACE_TYPES = new LinkedHashMap<>();
97
98 static {
99 populateCategoriesAndTraceTypes();
100 populateCustomTraceTypes();
101 }
102
103 /**
104 * Enum to say whether a type applies to a trace or experiment
105 *
106 * @author Geneviève Bastien
107 */
108 public enum TraceElementType {
109 /** Trace type applies to trace */
110 TRACE,
111 /** Trace type applies to experiment */
112 EXPERIMENT,
113 }
114
115 // ------------------------------------------------------------------
116 // Constructor
117 // ------------------------------------------------------------------
118
119 private TmfTraceType() {
120 }
121
122 // ------------------------------------------------------------------
123 // Operations
124 // ------------------------------------------------------------------
125
126 /**
127 * Retrieves the category name from the platform extension registry based on
128 * the category ID
129 *
130 * @param categoryId
131 * The category ID
132 * @return the category name or empty string if not found
133 */
134 public static String getCategoryName(String categoryId) {
135 IConfigurationElement[] elements = Platform.getExtensionRegistry()
136 .getConfigurationElementsFor(TMF_TRACE_TYPE_ID);
137 for (IConfigurationElement element : elements) {
138 if (element.getName().equals(CATEGORY_ELEM) && element.getAttribute(ID_ATTR).equals(categoryId)) {
139 return element.getAttribute(NAME_ATTR);
140 }
141 }
142 return ""; //$NON-NLS-1$
143 }
144
145 /**
146 * Retrieves all configuration elements from the platform extension registry
147 * for the trace type extension that apply to traces and not experiments.
148 *
149 * @return an array of trace type configuration elements
150 */
151 public static IConfigurationElement[] getTypeElements() {
152 IConfigurationElement[] elements = Platform.getExtensionRegistry()
153 .getConfigurationElementsFor(TMF_TRACE_TYPE_ID);
154 List<IConfigurationElement> typeElements = new LinkedList<>();
155 for (IConfigurationElement element : elements) {
156 if (element.getName().equals(TYPE_ELEM)) {
157 typeElements.add(element);
158 }
159 }
160 return typeElements.toArray(new IConfigurationElement[typeElements.size()]);
161 }
162
163 /**
164 * Get an iterable view of the existing trace type IDs.
165 *
166 * @return The currently registered trace type IDs
167 */
168 public static Iterable<String> getTraceTypeIDs() {
169 return TRACE_TYPES.keySet();
170 }
171
172 /**
173 * Get an iterable view of the existing trace type helpers.
174 *
175 * @return The currently registered trace type helpers
176 */
177 public static Iterable<TraceTypeHelper> getTraceTypeHelpers() {
178 return TRACE_TYPES.values();
179 }
180
181 /**
182 * Returns a list of trace type labels "category : name", ...
183 *
184 * Returns only trace types, not experiment types
185 *
186 * @return a list of trace type labels
187 */
188 public static String[] getAvailableTraceTypes() {
189 return getAvailableTraceTypes(null);
190 }
191
192 /**
193 * Returns a list of trace type labels "category : name", ... sorted by given comparator.
194 *
195 * Returns only trace types, not experiment types
196 *
197 * @param comparator
198 * Comparator class (type String) or null for alphabetical order.
199 * @return a list of trace type labels sorted according to the given comparator
200 */
201 public static String[] getAvailableTraceTypes(Comparator<String> comparator) {
202
203 // Generate the list of Category:TraceType to populate the ComboBox
204 List<String> traceTypes = new ArrayList<>();
205
206 for (String key : TRACE_TYPES.keySet()) {
207 TraceTypeHelper tt = TRACE_TYPES.get(key);
208 if (!tt.isExperimentType()) {
209 traceTypes.add(tt.getLabel());
210 }
211 }
212
213 if (comparator == null) {
214 Collections.sort(traceTypes);
215 } else {
216 Collections.sort(traceTypes, comparator);
217 }
218
219 // Format result
220 return traceTypes.toArray(new String[traceTypes.size()]);
221 }
222
223 /**
224 * Gets the custom trace types (custom text and friends)
225 *
226 * @param type
227 * the type to get (Text, xml or other...)
228 * @return the list of custom trace types
229 */
230 public static List<String> getCustomTraceTypes(String type) {
231 List<String> traceTypes = new ArrayList<>();
232 if (type.equals(CustomTxtTraceDefinition.CUSTOM_TXT_CATEGORY)) {
233 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
234 String traceTypeName = def.definitionName;
235 traceTypes.add(traceTypeName);
236 }
237 }
238 if (type.equals(CustomXmlTraceDefinition.CUSTOM_XML_CATEGORY)) {
239 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
240 String traceTypeName = def.definitionName;
241 traceTypes.add(traceTypeName);
242 }
243 }
244 return traceTypes;
245 }
246
247 /**
248 * Gets all the custom trace types
249 *
250 * @return the list of custom trace types
251 */
252 public static List<String> getCustomTraceTypes() {
253
254 List<String> traceTypes = new ArrayList<>();
255 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
256 String traceTypeName = def.definitionName;
257 traceTypes.add(traceTypeName);
258 }
259 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
260 String traceTypeName = def.definitionName;
261 traceTypes.add(traceTypeName);
262 }
263 return traceTypes;
264 }
265
266 private static void populateCustomTraceTypes() {
267 // add the custom trace types
268 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
269 CustomTxtTrace trace = new CustomTxtTrace(def);
270 String traceTypeId = trace.getTraceTypeId();
271 TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, def.categoryName, def.definitionName, trace, false, TraceElementType.TRACE);
272 TRACE_TYPES.put(traceTypeId, tt);
273 // Deregister trace as signal handler because it is only used for validation
274 TmfSignalManager.deregister(trace);
275 }
276 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
277 CustomXmlTrace trace = new CustomXmlTrace(def);
278 String traceTypeId = trace.getTraceTypeId();
279 TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, def.categoryName, def.definitionName, trace, false, TraceElementType.TRACE);
280 TRACE_TYPES.put(traceTypeId, tt);
281 // Deregister trace as signal handler because it is only used for validation
282 TmfSignalManager.deregister(trace);
283 }
284 }
285
286 /**
287 * Add or replace a custom trace type
288 *
289 * @param category
290 * The custom parser category
291 * @param definitionName
292 * The custom parser definition name to add or replace
293 * @deprecated Use {@link #addCustomTraceType(Class, String, String)}
294 */
295 @Deprecated
296 public static void addCustomTraceType(String category, String definitionName) {
297 if (category.equals(CustomTxtTraceDefinition.CUSTOM_TXT_CATEGORY)) {
298 addCustomTraceType(CustomTxtTrace.class, category, definitionName);
299 } else if (category.equals(CustomXmlTraceDefinition.CUSTOM_XML_CATEGORY)) {
300 addCustomTraceType(CustomXmlTrace.class, category, definitionName);
301 }
302 }
303
304 /**
305 * Add or replace a custom trace type
306 *
307 * @param traceClass
308 * The custom trace class, either {@link CustomTxtTrace} or
309 * {@link CustomXmlTrace}
310 * @param category
311 * The custom parser category
312 * @param definitionName
313 * The custom parser definition name to add or replace
314 */
315 public static void addCustomTraceType(Class<? extends ITmfTrace> traceClass, String category, String definitionName) {
316 String traceTypeId = null;
317 ITmfTrace trace = null;
318
319 if (traceClass.equals(CustomTxtTrace.class)) {
320 CustomTxtTraceDefinition def = CustomTxtTraceDefinition.load(category, definitionName);
321 if (def != null) {
322 trace = new CustomTxtTrace(def);
323 traceTypeId = trace.getTraceTypeId();
324 }
325 } else if (traceClass.equals(CustomXmlTrace.class)) {
326 CustomXmlTraceDefinition def = CustomXmlTraceDefinition.load(category, definitionName);
327 if (def != null) {
328 trace = new CustomXmlTrace(def);
329 traceTypeId = trace.getTraceTypeId();
330 }
331 }
332
333 if (traceTypeId != null && trace != null) {
334 TraceTypeHelper helper = TRACE_TYPES.get(traceTypeId);
335 if (helper != null) {
336 helper.getTrace().dispose();
337 }
338 TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, category, definitionName, trace, false, TraceElementType.TRACE);
339 TRACE_TYPES.put(traceTypeId, tt);
340 // Deregister trace as signal handler because it is only used for validation
341 TmfSignalManager.deregister(trace);
342 }
343 }
344
345 /**
346 * Remove a custom trace type
347 *
348 * @param category
349 * The custom parser category
350 * @param definitionName
351 * The custom parser definition name to add or replace
352 * @deprecated Use {@link #removeCustomTraceType(Class, String, String)}
353 */
354 @Deprecated
355 public static void removeCustomTraceType(String category, String definitionName) {
356 if (category.equals(CustomTxtTraceDefinition.CUSTOM_TXT_CATEGORY)) {
357 removeCustomTraceType(CustomTxtTrace.class, category, definitionName);
358 } else if (category.equals(CustomXmlTraceDefinition.CUSTOM_XML_CATEGORY)) {
359 removeCustomTraceType(CustomXmlTrace.class, category, definitionName);
360 }
361 }
362
363 /**
364 * Remove a custom trace type
365 *
366 * @param traceClass
367 * The custom trace class, either {@link CustomTxtTrace} or
368 * {@link CustomXmlTrace}
369 * @param category
370 * The custom parser category
371 * @param definitionName
372 * The custom parser definition name to add or replace
373 */
374 public static void removeCustomTraceType(Class<? extends ITmfTrace> traceClass, String category, String definitionName) {
375 String traceTypeId = null;
376 if (traceClass.equals(CustomTxtTrace.class)) {
377 traceTypeId = CustomTxtTrace.buildTraceTypeId(category, definitionName);
378 } else if (traceClass.equals(CustomXmlTrace.class)) {
379 traceTypeId = CustomXmlTrace.buildTraceTypeId(category, definitionName);
380 }
381 if (traceTypeId != null) {
382 TraceTypeHelper helper = TRACE_TYPES.remove(traceTypeId);
383 if (helper != null) {
384 helper.getTrace().dispose();
385 }
386 }
387 }
388
389 /**
390 * Gets a trace type for a given canonical id
391 *
392 * @param id
393 * the ID of the trace
394 * @return the return type
395 */
396 public static TraceTypeHelper getTraceType(String id) {
397 return TRACE_TYPES.get(id);
398 }
399
400 private static void populateCategoriesAndTraceTypes() {
401 if (TRACE_TYPES.isEmpty()) {
402 // Populate the Categories and Trace Types
403 IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType.TMF_TRACE_TYPE_ID);
404 for (IConfigurationElement ce : config) {
405 String elementName = ce.getName();
406 if (elementName.equals(TmfTraceType.TYPE_ELEM)) {
407 String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
408 TRACE_TYPE_ATTRIBUTES.put(traceTypeId, ce);
409 } else if (elementName.equals(TmfTraceType.CATEGORY_ELEM)) {
410 String categoryId = ce.getAttribute(TmfTraceType.ID_ATTR);
411 TRACE_CATEGORIES.put(categoryId, ce);
412 } else if (elementName.equals(TmfTraceType.EXPERIMENT_ELEM)) {
413 String experimentTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
414 TRACE_TYPE_ATTRIBUTES.put(experimentTypeId, ce);
415 }
416 }
417 // create the trace types
418 for (String typeId : TRACE_TYPE_ATTRIBUTES.keySet()) {
419 IConfigurationElement ce = TRACE_TYPE_ATTRIBUTES.get(typeId);
420 final String category = getCategory(ce);
421 final String attribute = ce.getAttribute(TmfTraceType.NAME_ATTR);
422 ITmfTrace trace = null;
423 TraceElementType elementType = TraceElementType.TRACE;
424 try {
425 if (ce.getName().equals(TmfTraceType.TYPE_ELEM)) {
426 trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.TRACE_TYPE_ATTR);
427 } else if (ce.getName().equals(TmfTraceType.EXPERIMENT_ELEM)) {
428 trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.EXPERIMENT_TYPE_ATTR);
429 elementType = TraceElementType.EXPERIMENT;
430 }
431 if (trace == null) {
432 break;
433 }
434 // Deregister trace as signal handler because it is only
435 // used for validation
436 TmfSignalManager.deregister(trace);
437
438 final String dirString = ce.getAttribute(TmfTraceType.IS_DIR_ATTR);
439 boolean isDir = Boolean.parseBoolean(dirString);
440
441 TraceTypeHelper tt = new TraceTypeHelper(typeId, category, attribute, trace, isDir, elementType);
442 TRACE_TYPES.put(typeId, tt);
443 } catch (CoreException e) {
444 Activator.logError("Unexpected error during populating trace types", e); //$NON-NLS-1$
445 }
446
447 }
448 }
449 }
450
451 private static String getCategory(IConfigurationElement ce) {
452 final String categoryId = ce.getAttribute(TmfTraceType.CATEGORY_ATTR);
453 if (categoryId != null) {
454 IConfigurationElement category = TRACE_CATEGORIES.get(categoryId);
455 if (category != null && !category.getName().equals("")) { //$NON-NLS-1$
456 return category.getAttribute(TmfTraceType.NAME_ATTR);
457 }
458 }
459 return ""; //$NON-NLS-1$
460 }
461
462 /**
463 * Returns the list of trace categories
464 *
465 * @return the list of trace categories
466 */
467 public static List<String> getTraceCategories() {
468 List<String> categoryNames = new ArrayList<>();
469 for (String key : TRACE_TYPES.keySet()) {
470 final String categoryName = TRACE_TYPES.get(key).getCategoryName();
471 if (!categoryNames.contains(categoryName)) {
472 categoryNames.add(categoryName);
473 }
474 }
475 return categoryNames;
476 }
477
478 /**
479 * Get the trace type helper classes from category name. Return only the
480 * trace types, not the experiment types
481 *
482 * @param categoryName
483 * the categoryName to lookup
484 * @return a list of trace type helper classes {@link TraceTypeHelper}
485 */
486 public static List<TraceTypeHelper> getTraceTypes(String categoryName) {
487 List<TraceTypeHelper> traceNames = new ArrayList<>();
488 for (String key : TRACE_TYPES.keySet()) {
489 if (!TRACE_TYPES.get(key).isExperimentType()) {
490 final String storedCategoryName = TRACE_TYPES.get(key).getCategoryName();
491 if (storedCategoryName.equals(categoryName)) {
492 traceNames.add(TRACE_TYPES.get(key));
493 }
494 }
495 }
496 return traceNames;
497 }
498
499 /**
500 * Validate a trace type
501 *
502 * @param traceTypeName
503 * the trace category (canonical name)
504 * @param fileName
505 * the file name (and path)
506 * @return true if the trace is of a valid type
507 */
508 public static boolean validate(String traceTypeName, String fileName) {
509 if (traceTypeName != null && !traceTypeName.isEmpty()) {
510 final TraceTypeHelper traceTypeHelper = TRACE_TYPES.get(traceTypeName);
511 if (traceTypeHelper == null || !traceTypeHelper.validate(fileName).isOK()) {
512 return false;
513 }
514 }
515 return true;
516 }
517
518 /**
519 * Validate a trace
520 *
521 * @param traceToValidate
522 * the trace category (canonical name)
523 * @return true if the trace is of a valid type
524 */
525 public static boolean validate(TraceValidationHelper traceToValidate) {
526 return validate(traceToValidate.getTraceType(), traceToValidate.getTraceToScan());
527 }
528
529 /**
530 * Validate a list of files with a tracetype
531 *
532 * @param traceTypeName
533 * the trace category (canonical name)
534 * @param traces
535 * the list of files to check if they are trace
536 * @return true if all the traces are valid
537 */
538 public static boolean validateTraceFiles(String traceTypeName, List<File> traces) {
539 if (traceTypeName != null && !"".equals(traceTypeName) && //$NON-NLS-1$
540 !traceTypeName.startsWith(CustomTxtTraceDefinition.CUSTOM_TXT_CATEGORY) && !traceTypeName.startsWith(CustomXmlTraceDefinition.CUSTOM_XML_CATEGORY)) {
541 for (File trace : traces) {
542 if (!validate(traceTypeName, trace.getAbsolutePath())) {
543 return false;
544 }
545 }
546 }
547 return true;
548 }
549
550 /**
551 * Get a configuration element for a given name
552 *
553 * @param traceType
554 * the name canonical
555 * @return the configuration element, can be null
556 */
557 public static IConfigurationElement getTraceAttributes(String traceType) {
558 return TRACE_TYPE_ATTRIBUTES.get(traceType);
559 }
560
561 /**
562 * Find the id of a trace type by its label "category : name"
563 *
564 * @param label
565 * the trace type label
566 * @return the trace type id
567 */
568 public static String getTraceTypeId(String label) {
569 for (String key : TRACE_TYPES.keySet()) {
570 if (TRACE_TYPES.get(key).getLabel().equals(label)) {
571 return key;
572 }
573 }
574 return null;
575 }
576
577 /**
578 * Checks if a trace is a valid directory trace
579 * @param path
580 * the file name (and path)
581 * @return <code>true</code> if the trace is a valid directory trace else <code>false</code>
582 */
583 public static boolean isDirectoryTrace(String path) {
584 final Iterable<TraceTypeHelper> traceTypeHelpers = getTraceTypeHelpers();
585 for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) {
586 if (traceTypeHelper.isDirectoryTraceType() &&
587 traceTypeHelper.validate(path).isOK()) {
588 return true;
589 }
590 }
591 return false;
592 }
593
594 /**
595 * @param traceType
596 * the trace type
597 * @return <code>true</code> it is a directory trace type else else <code>false</code>
598 */
599 public static boolean isDirectoryTraceType(String traceType) {
600 if (traceType != null) {
601 TraceTypeHelper traceTypeHelper = getTraceType(traceType);
602 if (traceTypeHelper != null) {
603 return traceTypeHelper.isDirectoryTraceType();
604 }
605 return false;
606 }
607 throw new IllegalArgumentException("Invalid trace type string: " + traceType); //$NON-NLS-1$
608 }
609
610 /**
611 * Get the trace type id for a resource
612 *
613 * @param resource
614 * the resource
615 * @return the trace type id or null if it is not set
616 * @throws CoreException
617 * if the trace type id cannot be accessed
618 * @since 3.2
619 */
620 public static String getTraceTypeId(IResource resource) throws CoreException {
621 String traceTypeId = resource.getPersistentProperties().get(TmfCommonConstants.TRACETYPE);
622 // Fix custom trace type id with old class name or without category name for backward compatibility
623 if (traceTypeId != null) {
624 String newTraceType = CustomTxtTrace.buildCompatibilityTraceTypeId(traceTypeId);
625 if (newTraceType.equals(traceTypeId)) {
626 newTraceType = CustomXmlTrace.buildCompatibilityTraceTypeId(traceTypeId);
627 }
628 return newTraceType;
629 }
630 return traceTypeId;
631 }
632
633 }
This page took 0.07042 seconds and 5 git commands to generate.