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