custom.parsers: bug 494697 Define event names in custom parsers
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / parsers / custom / CustomXmlTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2010, 2016 Ericsson
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 * Bernd Hufmann - Add trace type id handling
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.tmf.core.parsers.custom;
15
16 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
18 import java.io.ByteArrayInputStream;
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.RandomAccessFile;
22 import java.nio.ByteBuffer;
23
24 import javax.xml.parsers.DocumentBuilder;
25 import javax.xml.parsers.DocumentBuilderFactory;
26 import javax.xml.parsers.ParserConfigurationException;
27
28 import org.eclipse.core.resources.IProject;
29 import org.eclipse.core.resources.IResource;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.Status;
32 import org.eclipse.jdt.annotation.NonNull;
33 import org.eclipse.tracecompass.internal.tmf.core.Activator;
34 import org.eclipse.tracecompass.internal.tmf.core.parsers.custom.CustomEventAspects;
35 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
36 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
37 import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
38 import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
39 import org.eclipse.tracecompass.tmf.core.io.BufferedRandomAccessFile;
40 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
41 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
42 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
43 import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
44 import org.eclipse.tracecompass.tmf.core.trace.TmfContext;
45 import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
46 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
47 import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
48 import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
49 import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer;
50 import org.eclipse.tracecompass.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
51 import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
52 import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
53 import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
54 import org.eclipse.tracecompass.tmf.core.trace.location.TmfLongLocation;
55 import org.w3c.dom.Document;
56 import org.w3c.dom.Element;
57 import org.w3c.dom.Node;
58 import org.w3c.dom.NodeList;
59 import org.xml.sax.EntityResolver;
60 import org.xml.sax.ErrorHandler;
61 import org.xml.sax.InputSource;
62 import org.xml.sax.SAXException;
63 import org.xml.sax.SAXParseException;
64
65 /**
66 * Trace object for custom XML trace parsers.
67 *
68 * @author Patrick Tassé
69 */
70 public class CustomXmlTrace extends TmfTrace implements ITmfPersistentlyIndexable {
71
72 private static final TmfLongLocation NULL_LOCATION = new TmfLongLocation(-1L);
73 private static final int DEFAULT_CACHE_SIZE = 100;
74 private static final int MAX_LINES = 100;
75 private static final int CONFIDENCE = 100;
76
77 private final CustomXmlTraceDefinition fDefinition;
78 private final ITmfEventField fRootField;
79 private final CustomXmlInputElement fRecordInputElement;
80 private BufferedRandomAccessFile fFile;
81 private final @NonNull String fTraceTypeId;
82
83 private static final char SEPARATOR = ':';
84 private static final String CUSTOM_XML_TRACE_TYPE_PREFIX = "custom.xml.trace" + SEPARATOR; //$NON-NLS-1$
85 private static final String LINUX_TOOLS_CUSTOM_XML_TRACE_TYPE_PREFIX = "org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTrace" + SEPARATOR; //$NON-NLS-1$
86 private static final String EARLY_TRACE_COMPASS_CUSTOM_XML_TRACE_TYPE_PREFIX = "org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace" + SEPARATOR; //$NON-NLS-1$
87
88 /**
89 * Basic constructor
90 *
91 * @param definition
92 * Trace definition
93 */
94 public CustomXmlTrace(final CustomXmlTraceDefinition definition) {
95 fDefinition = definition;
96 fRootField = CustomEventType.getRootField(definition);
97 fRecordInputElement = getRecordInputElement(fDefinition.rootInputElement);
98 fTraceTypeId = buildTraceTypeId(definition.categoryName, definition.definitionName);
99 setCacheSize(DEFAULT_CACHE_SIZE);
100 }
101
102 /**
103 * Full constructor
104 *
105 * @param resource
106 * Trace resource
107 * @param definition
108 * Trace definition
109 * @param path
110 * Path to the trace/log file
111 * @param pageSize
112 * Page size to use
113 * @throws TmfTraceException
114 * If the trace/log couldn't be opened
115 */
116 public CustomXmlTrace(final IResource resource,
117 final CustomXmlTraceDefinition definition, final String path,
118 final int pageSize) throws TmfTraceException {
119 this(definition);
120 setCacheSize((pageSize > 0) ? pageSize : DEFAULT_CACHE_SIZE);
121 initTrace(resource, path, CustomXmlEvent.class);
122 }
123
124 @Override
125 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType) throws TmfTraceException {
126 super.initTrace(resource, path, eventType);
127 initFile();
128 }
129
130 private void initFile() throws TmfTraceException {
131 closeFile();
132 try {
133 fFile = new BufferedRandomAccessFile(getPath(), "r"); //$NON-NLS-1$
134 } catch (IOException e) {
135 throw new TmfTraceException(e.getMessage(), e);
136 }
137 }
138
139 @Override
140 public synchronized void dispose() {
141 super.dispose();
142 closeFile();
143 }
144
145 private void closeFile() {
146 if (fFile != null) {
147 try {
148 fFile.close();
149 } catch (IOException e) {
150 } finally {
151 fFile = null;
152 }
153 }
154 }
155
156 @Override
157 public ITmfTraceIndexer getIndexer() {
158 return super.getIndexer();
159 }
160
161 @Override
162 public Iterable<ITmfEventAspect<?>> getEventAspects() {
163 return CustomEventAspects.generateAspects(fDefinition);
164 }
165
166 @Override
167 public synchronized TmfContext seekEvent(final ITmfLocation location) {
168 final CustomXmlTraceContext context = new CustomXmlTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
169 if (NULL_LOCATION.equals(location) || fFile == null) {
170 return context;
171 }
172 try {
173 if (location == null) {
174 fFile.seek(0);
175 } else if (location.getLocationInfo() instanceof Long) {
176 fFile.seek((Long) location.getLocationInfo());
177 }
178 long rawPos = fFile.getFilePointer();
179 String line = fFile.getNextLine();
180 while (line != null) {
181 final int idx = indexOfElement(fRecordInputElement.getElementName(), line, 0);
182 if (idx != -1) {
183 context.setLocation(new TmfLongLocation(rawPos + idx));
184 return context;
185 }
186 rawPos = fFile.getFilePointer();
187 line = fFile.getNextLine();
188 }
189 return context;
190 } catch (final IOException e) {
191 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
192 return context;
193 }
194
195 }
196
197 @Override
198 public synchronized TmfContext seekEvent(final double ratio) {
199 if (fFile == null) {
200 return new CustomTxtTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
201 }
202 try {
203 long pos = Math.round(ratio * fFile.length());
204 while (pos > 0) {
205 fFile.seek(pos - 1);
206 if (fFile.read() == '\n') {
207 break;
208 }
209 pos--;
210 }
211 final ITmfLocation location = new TmfLongLocation(pos);
212 final TmfContext context = seekEvent(location);
213 context.setRank(ITmfContext.UNKNOWN_RANK);
214 return context;
215 } catch (final IOException e) {
216 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
217 return new CustomXmlTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
218 }
219 }
220
221 @Override
222 public synchronized double getLocationRatio(final ITmfLocation location) {
223 if (fFile == null) {
224 return 0;
225 }
226 try {
227 if (location.getLocationInfo() instanceof Long) {
228 return ((Long) location.getLocationInfo()).doubleValue() / fFile.length();
229 }
230 } catch (final IOException e) {
231 Activator.logError("Error getting location ration. File: " + getPath(), e); //$NON-NLS-1$
232 }
233 return 0;
234 }
235
236 @Override
237 public ITmfLocation getCurrentLocation() {
238 // TODO Auto-generated method stub
239 return null;
240 }
241
242 @Override
243 public synchronized CustomXmlEvent parseEvent(final ITmfContext tmfContext) {
244 ITmfContext context = seekEvent(tmfContext.getLocation());
245 return parse(context);
246 }
247
248 @Override
249 public synchronized CustomXmlEvent getNext(final ITmfContext context) {
250 final ITmfContext savedContext = new TmfContext(context.getLocation(), context.getRank());
251 final CustomXmlEvent event = parse(context);
252 if (event != null) {
253 updateAttributes(savedContext, event);
254 context.increaseRank();
255 }
256 return event;
257 }
258
259 private synchronized CustomXmlEvent parse(final ITmfContext tmfContext) {
260 if (fFile == null) {
261 return null;
262 }
263 if (!(tmfContext instanceof CustomXmlTraceContext)) {
264 return null;
265 }
266
267 final CustomXmlTraceContext context = (CustomXmlTraceContext) tmfContext;
268 if (context.getLocation() == null || !(context.getLocation().getLocationInfo() instanceof Long) || NULL_LOCATION.equals(context.getLocation())) {
269 return null;
270 }
271
272 CustomXmlEvent event = null;
273 try {
274 // Below +1 for the <
275 if (fFile.getFilePointer() != (Long) context.getLocation().getLocationInfo() + 1) {
276 fFile.seek((Long) context.getLocation().getLocationInfo() + 1);
277 }
278 final StringBuffer elementBuffer = new StringBuffer("<"); //$NON-NLS-1$
279 readElement(elementBuffer, fFile);
280 final Element element = parseElementBuffer(elementBuffer);
281
282 event = extractEvent(element, fRecordInputElement);
283 ((StringBuffer) event.getContentValue()).append(elementBuffer);
284
285 long rawPos = fFile.getFilePointer();
286 String line = fFile.getNextLine();
287 while (line != null) {
288 final int idx = indexOfElement(fRecordInputElement.getElementName(), line, 0);
289 if (idx != -1) {
290 context.setLocation(new TmfLongLocation(rawPos + idx));
291 return event;
292 }
293 rawPos = fFile.getFilePointer();
294 line = fFile.getNextLine();
295 }
296 } catch (final IOException e) {
297 Activator.logError("Error parsing event. File: " + getPath(), e); //$NON-NLS-1$
298
299 }
300 context.setLocation(NULL_LOCATION);
301 return event;
302 }
303
304 private Element parseElementBuffer(final StringBuffer elementBuffer) {
305 try {
306 final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
307 final DocumentBuilder db = dbf.newDocumentBuilder();
308
309 // The following allows xml parsing without access to the dtd
310 final EntityResolver resolver = new EntityResolver() {
311 @Override
312 public InputSource resolveEntity(final String publicId, final String systemId) {
313 final String empty = ""; //$NON-NLS-1$
314 final ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
315 return new InputSource(bais);
316 }
317 };
318 db.setEntityResolver(resolver);
319
320 // The following catches xml parsing exceptions
321 db.setErrorHandler(new ErrorHandler() {
322 @Override
323 public void error(final SAXParseException saxparseexception) throws SAXException {
324 }
325
326 @Override
327 public void warning(final SAXParseException saxparseexception) throws SAXException {
328 }
329
330 @Override
331 public void fatalError(final SAXParseException saxparseexception) throws SAXException {
332 throw saxparseexception;
333 }
334 });
335
336 final Document doc = db.parse(new ByteArrayInputStream(elementBuffer.toString().getBytes()));
337 return doc.getDocumentElement();
338 } catch (final ParserConfigurationException e) {
339 Activator.logError("Error parsing element buffer. File:" + getPath(), e); //$NON-NLS-1$
340 } catch (final SAXException e) {
341 Activator.logError("Error parsing element buffer. File:" + getPath(), e); //$NON-NLS-1$
342 } catch (final IOException e) {
343 Activator.logError("Error parsing element buffer. File: " + getPath(), e); //$NON-NLS-1$
344 }
345 return null;
346 }
347
348 private static int indexOfElement(String elementName, String line, int fromIndex) {
349 final String recordElementStart = '<' + elementName;
350 int index = line.indexOf(recordElementStart, fromIndex);
351 if (index == -1) {
352 return index;
353 }
354 int nextCharIndex = index + recordElementStart.length();
355 if (nextCharIndex < line.length()) {
356 char c = line.charAt(nextCharIndex);
357 // Check that the match is not just a substring of another element
358 if (Character.isLetterOrDigit(c)) {
359 return indexOfElement(elementName, line, nextCharIndex);
360 }
361 }
362 return index;
363 }
364
365 private void readElement(final StringBuffer buffer, final RandomAccessFile raFile) {
366 try {
367 int numRead = 0;
368 boolean startTagClosed = false;
369 int i;
370 while ((i = raFile.read()) != -1) {
371 numRead++;
372 final char c = (char) i;
373 buffer.append(c);
374 if (c == '"') {
375 readQuote(buffer, raFile, '"');
376 } else if (c == '\'') {
377 readQuote(buffer, raFile, '\'');
378 } else if (c == '<') {
379 readElement(buffer, raFile);
380 } else if (c == '/' && numRead == 1) {
381 break; // found "</"
382 } else if (c == '-' && numRead == 3 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("!-")) { //$NON-NLS-1$
383 readComment(buffer, raFile); // found "<!--"
384 } else if (i == '>') {
385 if (buffer.charAt(buffer.length() - 2) == '/') {
386 break; // found "/>"
387 } else if (startTagClosed) {
388 break; // found "<...>...</...>"
389 }
390 else {
391 startTagClosed = true; // found "<...>"
392 }
393 }
394 }
395 return;
396 } catch (final IOException e) {
397 return;
398 }
399 }
400
401 private static void readQuote(final StringBuffer buffer,
402 final RandomAccessFile raFile, final char eq) {
403 try {
404 int i;
405 while ((i = raFile.read()) != -1) {
406 final char c = (char) i;
407 buffer.append(c);
408 if (c == eq)
409 {
410 break; // found matching end-quote
411 }
412 }
413 return;
414 } catch (final IOException e) {
415 return;
416 }
417 }
418
419 private static void readComment(final StringBuffer buffer,
420 final RandomAccessFile raFile) {
421 try {
422 int numRead = 0;
423 int i;
424 while ((i = raFile.read()) != -1) {
425 numRead++;
426 final char c = (char) i;
427 buffer.append(c);
428 if (c == '>' && numRead >= 2 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("--")) //$NON-NLS-1$
429 {
430 break; // found "-->"
431 }
432 }
433 return;
434 } catch (final IOException e) {
435 return;
436 }
437 }
438
439 /**
440 * Parse an XML element.
441 *
442 * @param parentElement
443 * The parent element
444 * @param buffer
445 * The contents to parse
446 * @return The parsed content
447 */
448 public static StringBuffer parseElement(final Element parentElement, final StringBuffer buffer) {
449 final NodeList nodeList = parentElement.getChildNodes();
450 String separator = null;
451 for (int i = 0; i < nodeList.getLength(); i++) {
452 final Node node = nodeList.item(i);
453 short nodeType = node.getNodeType();
454 if (nodeType == Node.ELEMENT_NODE) {
455 if (separator == null) {
456 separator = " | "; //$NON-NLS-1$
457 } else {
458 buffer.append(separator);
459 }
460 final Element element = (Element) node;
461 if (!element.hasChildNodes()) {
462 buffer.append(element.getNodeName());
463 } else if (element.getChildNodes().getLength() == 1 && element.getFirstChild().getNodeType() == Node.TEXT_NODE) {
464 buffer.append(element.getNodeName());
465 buffer.append(':');
466 buffer.append(element.getFirstChild().getNodeValue().trim());
467 } else {
468 buffer.append(element.getNodeName());
469 buffer.append(" [ "); //$NON-NLS-1$
470 parseElement(element, buffer);
471 buffer.append(" ]"); //$NON-NLS-1$
472 }
473 } else if ((nodeType == Node.TEXT_NODE) && (!node.getNodeValue().trim().isEmpty())) {
474 buffer.append(node.getNodeValue().trim());
475 }
476 }
477 return buffer;
478 }
479
480 /**
481 * Get an input element if it is a valid record input. If not, we will look
482 * into its children for valid inputs.
483 *
484 * @param inputElement
485 * The main element to check for.
486 * @return The record element
487 */
488 public CustomXmlInputElement getRecordInputElement(final CustomXmlInputElement inputElement) {
489 if (inputElement.isLogEntry()) {
490 return inputElement;
491 } else if (inputElement.getChildElements() != null) {
492 for (final CustomXmlInputElement childInputElement : inputElement.getChildElements()) {
493 final CustomXmlInputElement recordInputElement = getRecordInputElement(childInputElement);
494 if (recordInputElement != null) {
495 return recordInputElement;
496 }
497 }
498 }
499 return null;
500 }
501
502 /**
503 * Extract a trace event from an XML element.
504 *
505 * @param element
506 * The element
507 * @param inputElement
508 * The input element
509 * @return The extracted event
510 */
511 public CustomXmlEvent extractEvent(final Element element, final CustomXmlInputElement inputElement) {
512 CustomXmlEventType eventType = new CustomXmlEventType(checkNotNull(fDefinition.definitionName), fRootField);
513 final CustomXmlEvent event = new CustomXmlEvent(fDefinition, this, TmfTimestamp.ZERO, eventType);
514 event.setContent(new CustomEventContent(event, new StringBuffer()));
515 parseElement(element, event, inputElement);
516 return event;
517 }
518
519 private void parseElement(final Element element, final CustomXmlEvent event, final CustomXmlInputElement inputElement) {
520 if (inputElement.getInputName() != null && !inputElement.getInputName().equals(CustomXmlTraceDefinition.TAG_IGNORE)) {
521 event.parseInput(parseElement(element, new StringBuffer()).toString(), inputElement.getInputName(), inputElement.getInputAction(), inputElement.getInputFormat());
522 }
523 if (inputElement.getAttributes() != null) {
524 for (final CustomXmlInputAttribute attribute : inputElement.getAttributes()) {
525 event.parseInput(element.getAttribute(attribute.getAttributeName()), attribute.getInputName(), attribute.getInputAction(), attribute.getInputFormat());
526 }
527 }
528 final NodeList childNodes = element.getChildNodes();
529 if (inputElement.getChildElements() != null) {
530 for (int i = 0; i < childNodes.getLength(); i++) {
531 final Node node = childNodes.item(i);
532 if (node instanceof Element) {
533 for (final CustomXmlInputElement child : inputElement.getChildElements()) {
534 if (node.getNodeName().equals(child.getElementName())) {
535 parseElement((Element) node, event, child);
536 break;
537 }
538 }
539 }
540 }
541 }
542 return;
543 }
544
545 /**
546 * Retrieve the trace definition.
547 *
548 * @return The trace definition
549 */
550 public CustomTraceDefinition getDefinition() {
551 return fDefinition;
552 }
553
554 /**
555 * {@inheritDoc}
556 * <p>
557 * The default implementation sets the confidence to 100 if any of the first
558 * 100 lines of the file contains a valid record input element, and 0
559 * otherwise.
560 */
561 @Override
562 public IStatus validate(IProject project, String path) {
563 File file = new File(path);
564 if (!file.exists() || !file.isFile() || !file.canRead()) {
565 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CustomTrace_FileNotFound + ": " + path); //$NON-NLS-1$
566 }
567 try {
568 if (!TmfTraceUtils.isText(file)) {
569 return new TraceValidationStatus(0, Activator.PLUGIN_ID);
570 }
571 } catch (IOException e) {
572 Activator.logError("Error validating file: " + path, e); //$NON-NLS-1$
573 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "IOException validating file: " + path, e); //$NON-NLS-1$
574 }
575 try (BufferedRandomAccessFile rafile = new BufferedRandomAccessFile(path, "r")) { //$NON-NLS-1$
576 int lineCount = 0;
577 long rawPos = 0;
578 String line = rafile.getNextLine();
579 while ((line != null) && (lineCount++ < MAX_LINES)) {
580 final int idx = indexOfElement(fRecordInputElement.getElementName(), line, 0);
581 if (idx != -1) {
582 rafile.seek(rawPos + idx + 1); // +1 is for the <
583 final StringBuffer elementBuffer = new StringBuffer("<"); //$NON-NLS-1$
584 readElement(elementBuffer, rafile);
585 final Element element = parseElementBuffer(elementBuffer);
586 if (element != null) {
587 rafile.close();
588 return new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
589 }
590 }
591 rawPos = rafile.getFilePointer();
592 line = rafile.getNextLine();
593 }
594 } catch (IOException e) {
595 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "IOException validating file: " + path, e); //$NON-NLS-1$
596 }
597 return new TraceValidationStatus(0, Activator.PLUGIN_ID);
598 }
599
600 private static int fCheckpointSize = -1;
601
602 @Override
603 public synchronized int getCheckpointSize() {
604 if (fCheckpointSize == -1) {
605 TmfCheckpoint c = new TmfCheckpoint(TmfTimestamp.ZERO, new TmfLongLocation(0L), 0);
606 ByteBuffer b = ByteBuffer.allocate(ITmfCheckpoint.MAX_SERIALIZE_SIZE);
607 b.clear();
608 c.serialize(b);
609 fCheckpointSize = b.position();
610 }
611
612 return fCheckpointSize;
613 }
614
615 @Override
616 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
617 return new TmfLongLocation(bufferIn);
618 }
619
620 @Override
621 protected ITmfTraceIndexer createIndexer(int interval) {
622 return new TmfBTreeTraceIndexer(this, interval);
623 }
624
625 @Override
626 public String getTraceTypeId() {
627 return fTraceTypeId;
628 }
629
630 /**
631 * Build the trace type id for a custom XML trace
632 *
633 * @param category
634 * the category
635 * @param definitionName
636 * the definition name
637 * @return the trace type id
638 */
639 public static @NonNull String buildTraceTypeId(String category, String definitionName) {
640 return CUSTOM_XML_TRACE_TYPE_PREFIX + category + SEPARATOR + definitionName;
641 }
642
643 /**
644 * Checks whether the given trace type ID is a custom XML trace type ID
645 *
646 * @param traceTypeId
647 * the trace type ID to check
648 * @return <code>true</code> if it's a custom text trace type ID else <code>false</code>
649 */
650 public static boolean isCustomTraceTypeId(@NonNull String traceTypeId) {
651 return traceTypeId.startsWith(CUSTOM_XML_TRACE_TYPE_PREFIX);
652 }
653
654 /**
655 * This methods builds a trace type ID from a given ID taking into
656 * consideration any format changes that were done for the IDs of custom
657 * XML traces. For example, such format change took place when moving to
658 * Trace Compass. Trace type IDs that are part of the plug-in extension for
659 * trace types won't be changed.
660 *
661 * This method is useful for IDs that were persisted in the workspace before
662 * the format changes (e.g. in the persistent properties of a trace
663 * resource).
664 *
665 * It ensures backwards compatibility of the workspace for custom XML
666 * traces.
667 *
668 * @param traceTypeId
669 * the legacy trace type ID
670 * @return the trace type id in Trace Compass format
671 */
672 public static @NonNull String buildCompatibilityTraceTypeId(@NonNull String traceTypeId) {
673 // Handle early Trace Compass custom XML trace type IDs
674 if (traceTypeId.startsWith(EARLY_TRACE_COMPASS_CUSTOM_XML_TRACE_TYPE_PREFIX)) {
675 return CUSTOM_XML_TRACE_TYPE_PREFIX + traceTypeId.substring(EARLY_TRACE_COMPASS_CUSTOM_XML_TRACE_TYPE_PREFIX.length());
676 }
677
678 // Handle Linux Tools custom XML trace type IDs (with and without category)
679 int index = traceTypeId.lastIndexOf(SEPARATOR);
680 if ((index != -1) && (traceTypeId.startsWith(LINUX_TOOLS_CUSTOM_XML_TRACE_TYPE_PREFIX))) {
681 String definitionName = index < traceTypeId.length() ? traceTypeId.substring(index + 1) : ""; //$NON-NLS-1$
682 if (traceTypeId.contains(CustomXmlTrace.class.getSimpleName() + SEPARATOR) && traceTypeId.indexOf(SEPARATOR) == index) {
683 return buildTraceTypeId(CustomXmlTraceDefinition.CUSTOM_XML_CATEGORY, definitionName);
684 }
685 return CUSTOM_XML_TRACE_TYPE_PREFIX + traceTypeId.substring(LINUX_TOOLS_CUSTOM_XML_TRACE_TYPE_PREFIX.length());
686 }
687 return traceTypeId;
688 }
689
690 @TmfSignalHandler
691 @Override
692 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
693 if (signal.getTrace() == this) {
694 try {
695 synchronized (this) {
696 // Reset the file handle in case it has reached the end of the
697 // file already. Otherwise, it will not be able to read new data
698 // pass the previous end.
699 initFile();
700 }
701 } catch (TmfTraceException e) {
702 Activator.logError(e.getLocalizedMessage(), e);
703 }
704 }
705 super.traceRangeUpdated(signal);
706 }
707 }
This page took 0.078857 seconds and 5 git commands to generate.