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