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