Commit | Line | Data |
---|---|---|
4bf17f4a | 1 | /******************************************************************************* |
661b21a1 | 2 | * Copyright (c) 2011, 2013 Ericsson |
cfd22ad0 | 3 | * |
4bf17f4a | 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 | |
cfd22ad0 | 8 | * |
4bf17f4a | 9 | * Contributors: |
10 | * Patrick Tasse - Initial API and implementation | |
d04ec5a7 | 11 | * Matthew Khouzam - Added import functionalities |
4bf17f4a | 12 | *******************************************************************************/ |
13 | ||
bfc779a0 | 14 | package org.eclipse.linuxtools.tmf.ui.project.model; |
4bf17f4a | 15 | |
d04ec5a7 MK |
16 | import java.io.File; |
17 | import java.util.ArrayList; | |
18 | import java.util.Collections; | |
19 | import java.util.HashMap; | |
20 | import java.util.Iterator; | |
21 | import java.util.LinkedHashMap; | |
4bf17f4a | 22 | import java.util.LinkedList; |
23 | import java.util.List; | |
d04ec5a7 | 24 | import java.util.Map; |
76fccfb0 | 25 | import java.util.Set; |
4bf17f4a | 26 | |
05627bda | 27 | import org.eclipse.core.resources.IResource; |
76fccfb0 | 28 | import org.eclipse.core.resources.ResourcesPlugin; |
05627bda | 29 | import org.eclipse.core.runtime.CoreException; |
4bf17f4a | 30 | import org.eclipse.core.runtime.IConfigurationElement; |
76fccfb0 MK |
31 | import org.eclipse.core.runtime.IPath; |
32 | import org.eclipse.core.runtime.IStatus; | |
4bf17f4a | 33 | import org.eclipse.core.runtime.Platform; |
76fccfb0 | 34 | import org.eclipse.core.runtime.Status; |
05627bda | 35 | import org.eclipse.linuxtools.internal.tmf.ui.Activator; |
76fccfb0 | 36 | import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomTxtTrace; |
d04ec5a7 | 37 | import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomTxtTraceDefinition; |
76fccfb0 | 38 | import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTrace; |
d04ec5a7 | 39 | import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTraceDefinition; |
76fccfb0 | 40 | import org.eclipse.linuxtools.internal.tmf.ui.project.model.TmfTraceImportException; |
05627bda | 41 | import org.eclipse.linuxtools.tmf.core.TmfCommonConstants; |
72807127 | 42 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager; |
d04ec5a7 | 43 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; |
76fccfb0 MK |
44 | import org.eclipse.swt.SWT; |
45 | import org.eclipse.swt.events.SelectionEvent; | |
46 | import org.eclipse.swt.events.SelectionListener; | |
47 | import org.eclipse.swt.layout.RowLayout; | |
48 | import org.eclipse.swt.widgets.Button; | |
49 | import org.eclipse.swt.widgets.Display; | |
50 | import org.eclipse.swt.widgets.Shell; | |
d04ec5a7 | 51 | import org.eclipse.ui.dialogs.FileSystemElement; |
4bf17f4a | 52 | |
b544077e | 53 | /** |
d04ec5a7 MK |
54 | * Utility class for accessing TMF trace type extensions from the platform's |
55 | * extensions registry. | |
cfd22ad0 | 56 | * |
b544077e BH |
57 | * @version 1.0 |
58 | * @author Patrick Tasse | |
d04ec5a7 | 59 | * @author Matthew Khouzam |
b544077e | 60 | */ |
d04ec5a7 | 61 | public final class TmfTraceType { |
4bf17f4a | 62 | |
76fccfb0 MK |
63 | private static final String DEFAULT_TRACE_ICON_PATH = "icons" + File.separator + "elcl16" + File.separator + "trace.gif"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
64 | ||
a2d29ca1 MK |
65 | private static final char SEPARATOR = ':'; |
66 | ||
b544077e | 67 | /** |
d04ec5a7 | 68 | * Extension point ID |
b544077e | 69 | */ |
bfc779a0 | 70 | public static final String TMF_TRACE_TYPE_ID = "org.eclipse.linuxtools.tmf.ui.tracetype"; //$NON-NLS-1$ |
4bf17f4a | 71 | |
b544077e | 72 | /** |
d04ec5a7 | 73 | * Extension point element 'Category' |
b544077e | 74 | */ |
4bf17f4a | 75 | public static final String CATEGORY_ELEM = "category"; //$NON-NLS-1$ |
b544077e | 76 | /** |
d04ec5a7 | 77 | * Extension point element 'Type' |
b544077e | 78 | */ |
4bf17f4a | 79 | public static final String TYPE_ELEM = "type"; //$NON-NLS-1$ |
b544077e | 80 | /** |
cfd22ad0 | 81 | * Extension point element 'Default editor' |
b544077e | 82 | */ |
4bf17f4a | 83 | public static final String DEFAULT_EDITOR_ELEM = "defaultEditor"; //$NON-NLS-1$ |
b544077e BH |
84 | /** |
85 | * Extension point element 'Events table type' | |
86 | */ | |
4bf17f4a | 87 | public static final String EVENTS_TABLE_TYPE_ELEM = "eventsTableType"; //$NON-NLS-1$ |
cfd22ad0 MD |
88 | /** |
89 | * Extension point element 'Statistics viewer type' | |
90 | * | |
91 | * @since 2.0 | |
92 | */ | |
93 | public static final String STATISTICS_VIEWER_ELEM = "statisticsViewerType"; //$NON-NLS-1$ | |
4bf17f4a | 94 | |
b544077e | 95 | /** |
d04ec5a7 | 96 | * Extension point attribute 'ID' |
b544077e | 97 | */ |
4bf17f4a | 98 | public static final String ID_ATTR = "id"; //$NON-NLS-1$ |
b544077e BH |
99 | /** |
100 | * Extension point attribute 'name' | |
101 | */ | |
4bf17f4a | 102 | public static final String NAME_ATTR = "name"; //$NON-NLS-1$ |
b544077e BH |
103 | /** |
104 | * Extension point attribute 'category' | |
105 | */ | |
4bf17f4a | 106 | public static final String CATEGORY_ATTR = "category"; //$NON-NLS-1$ |
b544077e BH |
107 | /** |
108 | * Extension point attribute 'trace_type' | |
109 | */ | |
4bf17f4a | 110 | public static final String TRACE_TYPE_ATTR = "trace_type"; //$NON-NLS-1$ |
b544077e BH |
111 | /** |
112 | * Extension point attribute 'event_type' | |
113 | */ | |
4bf17f4a | 114 | public static final String EVENT_TYPE_ATTR = "event_type"; //$NON-NLS-1$ |
b544077e BH |
115 | /** |
116 | * Extension point attribute 'icon' | |
117 | */ | |
4bf17f4a | 118 | public static final String ICON_ATTR = "icon"; //$NON-NLS-1$ |
b544077e BH |
119 | /** |
120 | * Extension point attribute 'class' | |
121 | */ | |
4bf17f4a | 122 | public static final String CLASS_ATTR = "class"; //$NON-NLS-1$ |
123 | ||
b544077e | 124 | /** |
d04ec5a7 MK |
125 | * Custom text label used internally and therefore should not be |
126 | * externalized | |
127 | * | |
128 | * @since 2.0 | |
129 | */ | |
130 | public static final String CUSTOM_TXT_CATEGORY = "Custom Text"; //$NON-NLS-1$ | |
131 | /** | |
132 | * Custom XML label used internally and therefore should not be externalized | |
133 | * | |
134 | * @since 2.0 | |
135 | */ | |
136 | public static final String CUSTOM_XML_CATEGORY = "Custom XML"; //$NON-NLS-1$ | |
137 | ||
138 | // The mapping of available trace type IDs to their corresponding | |
139 | // configuration element | |
507b1336 AM |
140 | private final Map<String, IConfigurationElement> fTraceTypeAttributes = new HashMap<>(); |
141 | private final Map<String, IConfigurationElement> fTraceCategories = new HashMap<>(); | |
142 | private final Map<String, TraceTypeHelper> fTraceTypes = new LinkedHashMap<>(); | |
d04ec5a7 MK |
143 | |
144 | private static TmfTraceType fInstance = null; | |
145 | ||
146 | /** | |
147 | * Retrieves the category name from the platform extension registry based on | |
148 | * the category ID | |
149 | * | |
150 | * @param categoryId | |
151 | * The category ID | |
b544077e BH |
152 | * @return the category name or empty string if not found |
153 | */ | |
4bf17f4a | 154 | public static String getCategoryName(String categoryId) { |
155 | IConfigurationElement[] elements = Platform.getExtensionRegistry() | |
156 | .getConfigurationElementsFor(TMF_TRACE_TYPE_ID); | |
157 | for (IConfigurationElement element : elements) { | |
158 | if (element.getName().equals(CATEGORY_ELEM) && categoryId.equals(element.getAttribute(ID_ATTR))) { | |
159 | return element.getAttribute(NAME_ATTR); | |
160 | } | |
161 | } | |
162 | return ""; //$NON-NLS-1$ | |
163 | } | |
164 | ||
05627bda MD |
165 | /** |
166 | * Retrieves and instantiates an element's object based on his plug-in | |
167 | * definition for a specific trace type. | |
168 | * | |
169 | * The element's object is instantiated using its 0-argument constructor. | |
170 | * | |
171 | * @param resource | |
172 | * The resource where to find the information about the trace | |
173 | * properties | |
174 | * @param element | |
175 | * The name of the element to find under the trace type | |
176 | * definition | |
177 | * @return a new Object based on his definition in plugin.xml, or null if no | |
178 | * definition was found | |
179 | * @since 2.0 | |
180 | */ | |
181 | public static Object getTraceTypeElement(IResource resource, String element) { | |
182 | try { | |
183 | if (resource != null) { | |
184 | String traceType = resource.getPersistentProperty(TmfCommonConstants.TRACETYPE); | |
185 | /* | |
186 | * Search in the configuration if there is any viewer specified | |
187 | * for this kind of trace type. | |
188 | */ | |
189 | for (IConfigurationElement ce : TmfTraceType.getTypeElements()) { | |
190 | if (ce.getAttribute(TmfTraceType.ID_ATTR).equals(traceType)) { | |
191 | IConfigurationElement[] viewerCE = ce.getChildren(element); | |
192 | if (viewerCE.length != 1) { | |
193 | break; | |
194 | } | |
195 | return viewerCE[0].createExecutableExtension(TmfTraceType.CLASS_ATTR); | |
196 | } | |
197 | } | |
198 | } | |
199 | } catch (CoreException e) { | |
200 | Activator.getDefault().logError("Error creating the element from the resource", e); //$NON-NLS-1$ | |
201 | } | |
202 | return null; | |
203 | } | |
204 | ||
b544077e | 205 | /** |
cfd22ad0 | 206 | * Retrieves all configuration elements from the platform extension registry |
b544077e | 207 | * for the trace type extension. |
cfd22ad0 MD |
208 | * |
209 | * @return an array of trace type configuration elements | |
b544077e | 210 | */ |
4bf17f4a | 211 | public static IConfigurationElement[] getTypeElements() { |
212 | IConfigurationElement[] elements = Platform.getExtensionRegistry() | |
213 | .getConfigurationElementsFor(TMF_TRACE_TYPE_ID); | |
507b1336 | 214 | List<IConfigurationElement> typeElements = new LinkedList<>(); |
4bf17f4a | 215 | for (IConfigurationElement element : elements) { |
216 | if (element.getName().equals(TYPE_ELEM)) { | |
217 | typeElements.add(element); | |
218 | } | |
219 | } | |
beae214a | 220 | return typeElements.toArray(new IConfigurationElement[typeElements.size()]); |
4bf17f4a | 221 | } |
d04ec5a7 MK |
222 | |
223 | private TmfTraceType() { | |
224 | init(); | |
225 | } | |
226 | ||
227 | /** | |
228 | * The import utils instance | |
229 | * | |
230 | * @return the import utils instance | |
231 | * @since 2.0 | |
232 | */ | |
233 | public static TmfTraceType getInstance() { | |
234 | if (fInstance == null) { | |
235 | fInstance = new TmfTraceType(); | |
236 | } | |
237 | return fInstance; | |
238 | } | |
239 | ||
240 | // ------------------------------------------------------------------ | |
241 | // Get trace types | |
242 | // ------------------------------------------------------------------ | |
243 | ||
244 | /** | |
a2d29ca1 | 245 | * Returns a list of "category:tracetype , ..." |
d04ec5a7 | 246 | * |
a2d29ca1 | 247 | * @return returns a list of "category:tracetype , ..." |
d04ec5a7 MK |
248 | * @since 2.0 |
249 | */ | |
250 | public String[] getAvailableTraceTypes() { | |
251 | ||
252 | // Generate the list of Category:TraceType to populate the ComboBox | |
507b1336 | 253 | List<String> traceTypes = new ArrayList<>(); |
d04ec5a7 | 254 | |
d04ec5a7 MK |
255 | for (String key : this.fTraceTypes.keySet()) { |
256 | TraceTypeHelper tt = this.fTraceTypes.get(key); | |
a2d29ca1 | 257 | traceTypes.add(tt.getCategoryName() + SEPARATOR + tt.getName()); |
d04ec5a7 | 258 | } |
d04ec5a7 MK |
259 | |
260 | // Format result | |
261 | return traceTypes.toArray(new String[traceTypes.size()]); | |
262 | } | |
263 | ||
264 | /** | |
265 | * Gets the custom trace types (custom text and friends) | |
266 | * | |
267 | * @param type | |
268 | * the type to get (Text, xml or other...) | |
269 | * @return the list of custom trace types | |
270 | * @since 2.0 | |
271 | */ | |
272 | public static List<String> getCustomTraceTypes(String type) { | |
507b1336 | 273 | List<String> traceTypes = new ArrayList<>(); |
d04ec5a7 MK |
274 | if (type.equals(CUSTOM_TXT_CATEGORY)) { |
275 | for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) { | |
276 | String traceTypeName = def.definitionName; | |
277 | traceTypes.add(traceTypeName); | |
278 | } | |
279 | } | |
280 | if (type.equals(CUSTOM_XML_CATEGORY)) { | |
281 | for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) { | |
282 | String traceTypeName = def.definitionName; | |
283 | traceTypes.add(traceTypeName); | |
284 | } | |
285 | } | |
286 | return traceTypes; | |
287 | } | |
288 | ||
289 | /** | |
290 | * Gets all the custom trace types | |
291 | * | |
292 | * @return the list of custom trace types | |
293 | * @since 2.0 | |
294 | */ | |
52885aeb PT |
295 | public static List<String> getCustomTraceTypes() { |
296 | ||
507b1336 | 297 | List<String> traceTypes = new ArrayList<>(); |
52885aeb PT |
298 | for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) { |
299 | String traceTypeName = def.definitionName; | |
300 | traceTypes.add(traceTypeName); | |
301 | } | |
302 | for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) { | |
303 | String traceTypeName = def.definitionName; | |
304 | traceTypes.add(traceTypeName); | |
d04ec5a7 | 305 | } |
52885aeb PT |
306 | return traceTypes; |
307 | } | |
d04ec5a7 | 308 | |
52885aeb | 309 | private void populateCustomTraceTypes() { |
d04ec5a7 MK |
310 | // add the custom trace types |
311 | for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) { | |
26e33e67 | 312 | String traceTypeId = CustomTxtTrace.class.getCanonicalName() + SEPARATOR + def.definitionName; |
72807127 BH |
313 | ITmfTrace trace = new CustomTxtTrace(def); |
314 | TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, CUSTOM_TXT_CATEGORY, def.definitionName, trace); | |
26e33e67 | 315 | fTraceTypes.put(traceTypeId, tt); |
72807127 BH |
316 | // Deregister trace as signal handler because it is only used for validation |
317 | TmfSignalManager.deregister(trace); | |
d04ec5a7 MK |
318 | } |
319 | for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) { | |
26e33e67 | 320 | String traceTypeId = CustomXmlTrace.class.getCanonicalName() + SEPARATOR + def.definitionName; |
72807127 BH |
321 | ITmfTrace trace = new CustomXmlTrace(def); |
322 | TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, CUSTOM_XML_CATEGORY, def.definitionName, trace); | |
26e33e67 | 323 | fTraceTypes.put(traceTypeId, tt); |
72807127 BH |
324 | // Deregister trace as signal handler because it is only used for validation |
325 | TmfSignalManager.deregister(trace); | |
d04ec5a7 | 326 | } |
52885aeb PT |
327 | } |
328 | ||
329 | /** | |
330 | * Add or replace a custom trace type | |
331 | * | |
332 | * @param category | |
333 | * The custom parser category | |
334 | * @param definitionName | |
335 | * The custom parser definition name to add or replace | |
336 | * @since 3.0 | |
337 | */ | |
338 | public void addCustomTraceType(String category, String definitionName) { | |
339 | String traceTypeId = null; | |
340 | ITmfTrace trace = null; | |
341 | ||
342 | if (category.equals(CUSTOM_TXT_CATEGORY)) { | |
343 | traceTypeId = CustomTxtTrace.class.getCanonicalName() + SEPARATOR + definitionName; | |
344 | CustomTxtTraceDefinition def = CustomTxtTraceDefinition.load(definitionName); | |
345 | if (def != null) { | |
346 | trace = new CustomTxtTrace(def); | |
347 | } | |
348 | } else if (category.equals(CUSTOM_XML_CATEGORY)) { | |
349 | traceTypeId = CustomXmlTrace.class.getCanonicalName() + SEPARATOR + definitionName; | |
350 | CustomXmlTraceDefinition def = CustomXmlTraceDefinition.load(definitionName); | |
351 | if (def != null) { | |
352 | trace = new CustomXmlTrace(def); | |
353 | } | |
354 | } | |
355 | ||
356 | if (traceTypeId != null && trace != null) { | |
357 | TraceTypeHelper helper = fTraceTypes.get(traceTypeId); | |
358 | if (helper != null) { | |
359 | helper.getTrace().dispose(); | |
360 | } | |
361 | TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, category, definitionName, trace); | |
362 | fTraceTypes.put(traceTypeId, tt); | |
363 | // Deregister trace as signal handler because it is only used for validation | |
364 | TmfSignalManager.deregister(trace); | |
365 | } | |
366 | } | |
367 | ||
368 | /** | |
369 | * Remove a custom trace type | |
370 | * | |
371 | * @param category | |
372 | * The custom parser category | |
373 | * @param definitionName | |
374 | * The custom parser definition name to add or replace | |
375 | * @since 3.0 | |
376 | */ | |
377 | public void removeCustomTraceType(String category, String definitionName) { | |
378 | if (category.equals(CUSTOM_TXT_CATEGORY)) { | |
379 | String traceTypeId = CustomTxtTrace.class.getCanonicalName() + SEPARATOR + definitionName; | |
380 | TraceTypeHelper helper = fTraceTypes.remove(traceTypeId); | |
381 | if (helper != null) { | |
382 | helper.getTrace().dispose(); | |
383 | } | |
384 | } else if (category.equals(CUSTOM_XML_CATEGORY)) { | |
385 | String traceTypeId = CustomXmlTrace.class.getCanonicalName() + SEPARATOR + definitionName; | |
386 | TraceTypeHelper helper = fTraceTypes.remove(traceTypeId); | |
387 | if (helper != null) { | |
388 | helper.getTrace().dispose(); | |
389 | } | |
390 | } | |
d04ec5a7 MK |
391 | } |
392 | ||
393 | /** | |
394 | * Gets a trace type for a given canonical id | |
395 | * | |
396 | * @param id | |
397 | * the ID of the trace | |
398 | * @return the return type | |
399 | * @since 2.0 | |
400 | */ | |
401 | public TraceTypeHelper getTraceType(String id) { | |
402 | return fTraceTypes.get(id); | |
403 | } | |
404 | ||
405 | private void populateCategoriesAndTraceTypes() { | |
406 | if (fTraceTypes.isEmpty()) { | |
407 | // Populate the Categories and Trace Types | |
408 | IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType.TMF_TRACE_TYPE_ID); | |
409 | for (IConfigurationElement ce : config) { | |
410 | String elementName = ce.getName(); | |
411 | if (elementName.equals(TmfTraceType.TYPE_ELEM)) { | |
412 | String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR); | |
413 | fTraceTypeAttributes.put(traceTypeId, ce); | |
414 | } else if (elementName.equals(TmfTraceType.CATEGORY_ELEM)) { | |
415 | String categoryId = ce.getAttribute(TmfTraceType.ID_ATTR); | |
416 | fTraceCategories.put(categoryId, ce); | |
417 | } | |
418 | } | |
419 | // create the trace types | |
420 | for (String typeId : fTraceTypeAttributes.keySet()) { | |
421 | IConfigurationElement ce = fTraceTypeAttributes.get(typeId); | |
422 | final String category = getCategory(ce); | |
423 | final String attribute = ce.getAttribute(TmfTraceType.NAME_ATTR); | |
424 | ITmfTrace trace = null; | |
425 | try { | |
426 | trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.TRACE_TYPE_ATTR); | |
72807127 BH |
427 | // Deregister trace as signal handler because it is only used for validation |
428 | TmfSignalManager.deregister(trace); | |
d04ec5a7 MK |
429 | } catch (CoreException e) { |
430 | } | |
431 | TraceTypeHelper tt = new TraceTypeHelper(typeId, category, attribute, trace); | |
432 | fTraceTypes.put(typeId, tt); | |
433 | } | |
434 | } | |
435 | } | |
436 | ||
437 | private String getCategory(IConfigurationElement ce) { | |
438 | final String categoryId = ce.getAttribute(TmfTraceType.CATEGORY_ATTR); | |
439 | if (categoryId != null) { | |
440 | IConfigurationElement category = fTraceCategories.get(categoryId); | |
441 | if (category != null && !category.getName().equals("")) { //$NON-NLS-1$ | |
442 | return category.getAttribute(TmfTraceType.NAME_ATTR); | |
443 | } | |
444 | } | |
445 | return "[no category]"; //$NON-NLS-1$ | |
446 | } | |
447 | ||
448 | /** | |
449 | * Returns the list of trace categories | |
450 | * | |
451 | * @return the list of trace categories | |
452 | * @since 2.0 | |
453 | */ | |
454 | public List<String> getTraceCategories() { | |
507b1336 | 455 | List<String> categoryNames = new ArrayList<>(); |
d04ec5a7 MK |
456 | for (String key : fTraceTypes.keySet()) { |
457 | final String categoryName = fTraceTypes.get(key).getCategoryName(); | |
458 | if (!categoryNames.contains(categoryName)) { | |
459 | categoryNames.add(categoryName); | |
460 | } | |
461 | } | |
462 | return categoryNames; | |
463 | } | |
464 | ||
465 | /** | |
cd9821de | 466 | * Get the trace type helper classes from category name |
d04ec5a7 | 467 | * |
cd9821de BH |
468 | * @param categoryName |
469 | * the categoryName to lookup | |
470 | * @return a list of trace type helper classes {@link TraceTypeHelper} | |
d04ec5a7 MK |
471 | * @since 2.0 |
472 | */ | |
473 | ||
cd9821de | 474 | public List<TraceTypeHelper> getTraceTypes(String categoryName) { |
507b1336 | 475 | List<TraceTypeHelper> traceNames = new ArrayList<>(); |
d04ec5a7 | 476 | for (String key : fTraceTypes.keySet()) { |
cd9821de BH |
477 | final String storedCategoryName = fTraceTypes.get(key).getCategoryName(); |
478 | if (storedCategoryName.equals(categoryName)) { | |
d04ec5a7 MK |
479 | traceNames.add(fTraceTypes.get(key)); |
480 | } | |
481 | } | |
482 | return traceNames; | |
483 | } | |
484 | ||
485 | private void init() { | |
486 | populateCategoriesAndTraceTypes(); | |
52885aeb | 487 | populateCustomTraceTypes(); |
d04ec5a7 MK |
488 | |
489 | } | |
490 | ||
491 | private static List<File> isolateTraces(List<FileSystemElement> selectedResources) { | |
492 | ||
507b1336 | 493 | List<File> traces = new ArrayList<>(); |
d04ec5a7 MK |
494 | |
495 | // Get the selection | |
496 | Iterator<FileSystemElement> resources = selectedResources.iterator(); | |
497 | ||
498 | // Get the sorted list of unique entries | |
507b1336 | 499 | Map<String, File> fileSystemObjects = new HashMap<>(); |
d04ec5a7 MK |
500 | while (resources.hasNext()) { |
501 | File resource = (File) resources.next().getFileSystemObject(); | |
502 | String key = resource.getAbsolutePath(); | |
503 | fileSystemObjects.put(key, resource); | |
504 | } | |
507b1336 | 505 | List<String> files = new ArrayList<>(fileSystemObjects.keySet()); |
d04ec5a7 MK |
506 | Collections.sort(files); |
507 | ||
508 | // After sorting, traces correspond to the unique prefixes | |
509 | String prefix = null; | |
510 | for (int i = 0; i < files.size(); i++) { | |
511 | File file = fileSystemObjects.get(files.get(i)); | |
512 | String name = file.getAbsolutePath(); | |
513 | if (prefix == null || !name.startsWith(prefix)) { | |
514 | prefix = name; // new prefix | |
515 | traces.add(file); | |
516 | } | |
517 | } | |
518 | ||
519 | return traces; | |
520 | } | |
521 | ||
522 | /** | |
523 | * Validate a trace type | |
524 | * | |
525 | * @param traceTypeName | |
526 | * the trace category (canonical name) | |
527 | * @param fileName | |
528 | * the file name (and path) | |
529 | * @return true if the trace is of a valid type | |
530 | * @since 2.0 | |
531 | */ | |
532 | public boolean validate(String traceTypeName, String fileName) { | |
76fccfb0 | 533 | if (traceTypeName != null && !traceTypeName.isEmpty()) { |
de2501f8 MK |
534 | final TraceTypeHelper traceTypeHelper = fTraceTypes.get(traceTypeName); |
535 | if (!traceTypeHelper.validate(fileName)) { | |
d04ec5a7 MK |
536 | return false; |
537 | } | |
538 | } | |
539 | return true; | |
540 | } | |
541 | ||
542 | /** | |
543 | * Validate a trace | |
544 | * | |
545 | * @param traceToValidate | |
546 | * the trace category (canonical name) | |
547 | * @return true if the trace is of a valid type | |
548 | * @since 2.0 | |
549 | */ | |
550 | public boolean validate(TraceValidationHelper traceToValidate) { | |
551 | return validate(traceToValidate.getTraceType(), traceToValidate.getTraceToScan()); | |
552 | } | |
553 | ||
554 | /** | |
555 | * validate list of traces with a tracetype | |
556 | * | |
557 | * @param traceTypeName | |
558 | * the trace category (canonical name) | |
559 | * @param selectedResources | |
560 | * List of traces to validate | |
561 | * @return true if all the traces are valid | |
562 | * @since 2.0 | |
563 | */ | |
564 | public boolean validateTrace(String traceTypeName, List<FileSystemElement> selectedResources) { | |
565 | List<File> traces = isolateTraces(selectedResources); | |
566 | return validateTraceFiles(traceTypeName, traces); | |
567 | } | |
568 | ||
569 | /** | |
570 | * Validate a list of files with a tracetype | |
571 | * | |
572 | * @param traceTypeName | |
573 | * the trace category (canonical name) | |
574 | * @param traces | |
575 | * the list of files to check if they are trace | |
576 | * @return true if all the traces are valid | |
577 | * @since 2.0 | |
578 | */ | |
579 | public boolean validateTraceFiles(String traceTypeName, List<File> traces) { | |
580 | if (traceTypeName != null && !"".equals(traceTypeName) && //$NON-NLS-1$ | |
581 | !traceTypeName.startsWith(TmfTraceType.CUSTOM_TXT_CATEGORY) && !traceTypeName.startsWith(TmfTraceType.CUSTOM_XML_CATEGORY)) { | |
582 | for (File trace : traces) { | |
edd51555 MK |
583 | if (!validate(traceTypeName, trace.getAbsolutePath())) { |
584 | return false; | |
585 | } | |
d04ec5a7 MK |
586 | } |
587 | } | |
588 | return true; | |
589 | } | |
590 | ||
591 | /** | |
592 | * Get a configuration element for a given name | |
593 | * | |
594 | * @param traceType | |
595 | * the name canonical | |
596 | * @return the configuration element, can be null | |
597 | * @since 2.0 | |
598 | */ | |
599 | public IConfigurationElement getTraceAttributes(String traceType) { | |
600 | return fTraceTypeAttributes.get(traceType); | |
601 | } | |
602 | ||
603 | /** | |
604 | * Find the id of a trace type by its parameters | |
605 | * | |
606 | * @param category | |
607 | * like "ctf" or "custom text" | |
608 | * @param traceType | |
609 | * like "kernel" | |
610 | * @return an id like "org.eclipse.linuxtools.blabla... | |
611 | * @since 2.0 | |
612 | */ | |
613 | public String getTraceTypeId(String category, String traceType) { | |
614 | for (String key : fTraceTypes.keySet()) { | |
615 | if (fTraceTypes.get(key).getCategoryName().equals(category.trim()) && fTraceTypes.get(key).getName().equals(traceType.trim())) { | |
616 | return key; | |
617 | } | |
618 | } | |
619 | return null; | |
620 | } | |
76fccfb0 MK |
621 | |
622 | /** | |
623 | * Is the trace a custom (user-defined) trace type. These are the traces | |
624 | * like : text and xml defined by the custom trace wizard. | |
625 | * | |
626 | * @param traceType | |
627 | * the trace type in human form (category:name) | |
628 | * @return true if the trace is a custom type | |
629 | * @since 2.1 | |
630 | */ | |
631 | public static boolean isCustomTrace(String traceType) { | |
632 | final boolean startsWithTxt = traceType.startsWith(TmfTraceType.CUSTOM_TXT_CATEGORY); | |
633 | final boolean startsWithXML = traceType.startsWith(TmfTraceType.CUSTOM_XML_CATEGORY); | |
634 | return (startsWithTxt || startsWithXML); | |
635 | } | |
636 | ||
26e33e67 | 637 | /** |
4958a213 MK |
638 | * Is the trace type id a custom (user-defined) trace type. These are the |
639 | * traces like : text and xml defined by the custom trace wizard. | |
26e33e67 MAL |
640 | * |
641 | * @param traceTypeId | |
642 | * the trace type id | |
643 | * @return true if the trace is a custom type | |
644 | */ | |
645 | private static boolean isCustomTraceId(String traceTypeId) { | |
646 | TraceTypeHelper traceType = getInstance().getTraceType(traceTypeId); | |
647 | if (traceType != null) { | |
648 | return isCustomTrace(traceType.getCategoryName() + SEPARATOR + traceType.getName()); | |
649 | } | |
650 | ||
651 | return false; | |
652 | } | |
653 | ||
76fccfb0 MK |
654 | /** |
655 | * Gets the custom trace type ID from the custom trace name | |
656 | * | |
657 | * @param traceType | |
658 | * The trace type in human form (category:name) | |
659 | * @return the trace type ID or null if the trace is not a custom one | |
660 | * @since 2.1 | |
661 | */ | |
662 | public static String getCustomTraceTypeId(String traceType) { | |
663 | String traceTypeId = null; | |
664 | ||
665 | // do custom trace stuff here | |
666 | String traceTypeToken[] = traceType.split(":", 2); //$NON-NLS-1$ | |
667 | if (traceTypeToken.length == 2) { | |
668 | final boolean startsWithTxt = traceType.startsWith(TmfTraceType.CUSTOM_TXT_CATEGORY); | |
669 | final boolean startsWithXML = traceType.startsWith(TmfTraceType.CUSTOM_XML_CATEGORY); | |
670 | if (startsWithTxt) { | |
671 | traceTypeId = CustomTxtTrace.class.getCanonicalName() + SEPARATOR + traceTypeToken[1]; | |
672 | } else if (startsWithXML) { | |
673 | traceTypeId = CustomXmlTrace.class.getCanonicalName() + SEPARATOR + traceTypeToken[1]; | |
674 | } | |
675 | } | |
676 | return traceTypeId; | |
677 | } | |
678 | ||
4958a213 MK |
679 | TraceTypeHelper selectTraceType(String path, Shell shell) throws TmfTraceImportException { |
680 | return selectTraceType(path, shell, null); | |
681 | } | |
682 | ||
76fccfb0 | 683 | /** |
4958a213 MK |
684 | * This member figures out the trace type of a given file. It will prompt |
685 | * the user if it needs more information to properly pick the trace type. | |
76fccfb0 MK |
686 | * |
687 | * @param path | |
688 | * The path of file to import | |
689 | * @param shell | |
690 | * a shell to display the message to. If it is null, it is | |
691 | * assumed to be cancelled. | |
4958a213 MK |
692 | * @param traceTypeHint the ID of a trace (like "o.e.l.specifictrace" ) |
693 | * @return null if the request is cancelled or a TraceTypeHelper if it passes. | |
76fccfb0 MK |
694 | * @throws TmfTraceImportException |
695 | * if the traces don't match or there are errors in the trace | |
696 | * file | |
f7885d6d | 697 | * @since 2.2 |
76fccfb0 | 698 | */ |
f7885d6d | 699 | public TraceTypeHelper selectTraceType(String path, Shell shell, String traceTypeHint) throws TmfTraceImportException { |
507b1336 | 700 | List<TraceTypeHelper> validCandidates = new ArrayList<>(); |
76fccfb0 MK |
701 | final Set<String> traceTypes = fTraceTypes.keySet(); |
702 | for (String traceType : traceTypes) { | |
703 | if (validate(traceType, path)) { | |
704 | validCandidates.add(fTraceTypes.get(traceType)); | |
705 | } | |
706 | } | |
707 | ||
4958a213 | 708 | TraceTypeHelper traceTypeToSet = null; |
76fccfb0 MK |
709 | if (validCandidates.isEmpty()) { |
710 | final String errorMsg = Messages.TmfOpenTraceHelper_NoTraceTypeMatch + path; | |
711 | throw new TmfTraceImportException(errorMsg); | |
712 | } else if (validCandidates.size() != 1) { | |
713 | List<TraceTypeHelper> reducedCandidates = reduce(validCandidates); | |
4958a213 MK |
714 | for (TraceTypeHelper tth : reducedCandidates) { |
715 | if (tth.getCanonicalName().equals(traceTypeHint)) { | |
716 | traceTypeToSet = tth; | |
717 | } | |
718 | } | |
719 | if (traceTypeToSet == null) { | |
720 | if (reducedCandidates.size() == 0) { | |
721 | throw new TmfTraceImportException(Messages.TmfOpenTraceHelper_ReduceError); | |
722 | } else if (reducedCandidates.size() == 1) { | |
723 | traceTypeToSet = reducedCandidates.get(0); | |
724 | } else { | |
725 | if (shell == null) { | |
726 | return null; | |
727 | } | |
728 | traceTypeToSet = getTraceTypeToSet(reducedCandidates, shell); | |
76fccfb0 | 729 | } |
76fccfb0 | 730 | } |
76fccfb0 MK |
731 | } else { |
732 | traceTypeToSet = validCandidates.get(0); | |
733 | } | |
734 | return traceTypeToSet; | |
735 | } | |
736 | ||
737 | private static List<TraceTypeHelper> reduce(List<TraceTypeHelper> candidates) { | |
507b1336 | 738 | List<TraceTypeHelper> retVal = new ArrayList<>(); |
76fccfb0 MK |
739 | |
740 | // get all the tracetypes that are unique in that stage | |
741 | for (TraceTypeHelper trace : candidates) { | |
742 | if (isUnique(trace, candidates)) { | |
743 | retVal.add(trace); | |
744 | } | |
745 | } | |
746 | return retVal; | |
747 | } | |
748 | ||
749 | /* | |
750 | * Only return the leaves of the trace types. Ignore custom trace types. | |
751 | */ | |
752 | private static boolean isUnique(TraceTypeHelper trace, List<TraceTypeHelper> set) { | |
26e33e67 | 753 | if (TmfTraceType.isCustomTraceId(trace.getCanonicalName())) { |
76fccfb0 MK |
754 | return true; |
755 | } | |
756 | // check if the trace type is the leaf. we make an instance of the trace | |
757 | // type and if it is only an instance of itself, it is a leaf | |
758 | final ITmfTrace tmfTrace = trace.getTrace(); | |
759 | int count = -1; | |
760 | for (TraceTypeHelper child : set) { | |
761 | final ITmfTrace traceCandidate = child.getTrace(); | |
762 | if (tmfTrace.getClass().isInstance(traceCandidate)) { | |
763 | count++; | |
764 | } | |
765 | } | |
766 | return count == 0; | |
767 | } | |
768 | ||
769 | private TraceTypeHelper getTraceTypeToSet(List<TraceTypeHelper> candidates, Shell shell) { | |
507b1336 | 770 | final Map<String, String> names = new HashMap<>(); |
76fccfb0 | 771 | Shell shellToShow = new Shell(shell); |
043ad4df | 772 | shellToShow.setText(Messages.TmfTraceType_SelectTraceType); |
76fccfb0 MK |
773 | final String candidatesToSet[] = new String[1]; |
774 | for (TraceTypeHelper candidate : candidates) { | |
775 | Button b = new Button(shellToShow, SWT.RADIO); | |
776 | final String displayName = candidate.getCategoryName() + ':' + candidate.getName(); | |
777 | b.setText(displayName); | |
778 | names.put(displayName, candidate.getCanonicalName()); | |
779 | ||
780 | b.addSelectionListener(new SelectionListener() { | |
781 | ||
782 | @Override | |
783 | public void widgetSelected(SelectionEvent e) { | |
784 | final Button source = (Button) e.getSource(); | |
785 | candidatesToSet[0] = (names.get(source.getText())); | |
786 | source.getParent().dispose(); | |
787 | } | |
788 | ||
789 | @Override | |
790 | public void widgetDefaultSelected(SelectionEvent e) { | |
791 | ||
792 | } | |
793 | }); | |
794 | } | |
795 | shellToShow.setLayout(new RowLayout(SWT.VERTICAL)); | |
796 | shellToShow.pack(); | |
797 | shellToShow.open(); | |
798 | ||
799 | Display display = shellToShow.getDisplay(); | |
800 | while (!shellToShow.isDisposed()) { | |
801 | if (!display.readAndDispatch()) { | |
802 | display.sleep(); | |
803 | } | |
804 | } | |
805 | return fTraceTypes.get(candidatesToSet[0]); | |
806 | } | |
807 | ||
808 | /** | |
809 | * Set the trace type of a {@Link TraceTypeHelper}. Should only be | |
810 | * used internally by this project. | |
811 | * | |
812 | * @param path | |
813 | * the {@link IPath} path of the resource to set | |
814 | * @param traceType | |
815 | * the {@link TraceTypeHelper} to set the trace type to. | |
816 | * @return Status.OK_Status if successful, error is otherwise. | |
817 | * @throws CoreException | |
818 | * An exception caused by accessing eclipse project items. | |
ef9f0c61 | 819 | * @since 2.1 |
76fccfb0 | 820 | */ |
cd9821de | 821 | public static IStatus setTraceType(IPath path, TraceTypeHelper traceType) throws CoreException { |
76fccfb0 | 822 | IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path); |
76fccfb0 | 823 | String traceBundle = null, traceTypeId = traceType.getCanonicalName(), traceIcon = null; |
26e33e67 | 824 | if (TmfTraceType.isCustomTraceId(traceTypeId)) { |
76fccfb0 MK |
825 | traceBundle = Activator.getDefault().getBundle().getSymbolicName(); |
826 | traceIcon = DEFAULT_TRACE_ICON_PATH; | |
827 | } else { | |
828 | IConfigurationElement ce = TmfTraceType.getInstance().getTraceAttributes(traceTypeId); | |
829 | traceBundle = ce.getContributor().getName(); | |
830 | traceIcon = ce.getAttribute(TmfTraceType.ICON_ATTR); | |
831 | } | |
832 | ||
833 | resource.setPersistentProperty(TmfCommonConstants.TRACEBUNDLE, traceBundle); | |
834 | resource.setPersistentProperty(TmfCommonConstants.TRACETYPE, traceTypeId); | |
835 | resource.setPersistentProperty(TmfCommonConstants.TRACEICON, traceIcon); | |
836 | ||
f537c959 PT |
837 | TmfProjectElement tmfProject = TmfProjectRegistry.getProject(resource.getProject(), true); |
838 | final TmfTraceFolder tracesFolder = tmfProject.getTracesFolder(); | |
839 | List<TmfTraceElement> traces = tracesFolder.getTraces(); | |
840 | for (TmfTraceElement traceElement : traces) { | |
841 | if (traceElement.getName().equals(resource.getName())) { | |
842 | traceElement.refreshTraceType(); | |
843 | break; | |
76fccfb0 MK |
844 | } |
845 | } | |
f537c959 | 846 | tmfProject.refresh(); |
76fccfb0 MK |
847 | return Status.OK_STATUS; |
848 | } | |
849 | ||
4bf17f4a | 850 | } |