Remove the generic location (replace by Comparable)
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / internal / tmf / ui / parsers / custom / CustomXmlTrace.java
CommitLineData
c3c5c786
FC
1/*******************************************************************************\r
2 * Copyright (c) 2010 Ericsson\r
6256d8ad 3 *\r
c3c5c786
FC
4 * All rights reserved. This program and the accompanying materials are\r
5 * made available under the terms of the Eclipse Public License v1.0 which\r
6 * accompanies this distribution, and is available at\r
7 * http://www.eclipse.org/legal/epl-v10.html\r
6256d8ad 8 *\r
c3c5c786
FC
9 * Contributors:\r
10 * Patrick Tasse - Initial API and implementation\r
11 *******************************************************************************/\r
12\r
d34665f9 13package org.eclipse.linuxtools.internal.tmf.ui.parsers.custom;\r
c3c5c786
FC
14\r
15import java.io.ByteArrayInputStream;\r
c3c5c786
FC
16import java.io.IOException;\r
17import java.io.RandomAccessFile;\r
18\r
19import javax.xml.parsers.DocumentBuilder;\r
20import javax.xml.parsers.DocumentBuilderFactory;\r
21import javax.xml.parsers.ParserConfigurationException;\r
22\r
2352aed9 23import org.eclipse.core.resources.IProject;\r
25e48683 24import org.eclipse.core.resources.IResource;\r
8fd82db5 25import org.eclipse.linuxtools.internal.tmf.ui.Activator;\r
d34665f9
FC
26import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTraceDefinition.InputAttribute;\r
27import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTraceDefinition.InputElement;\r
6256d8ad 28import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;\r
6c13869b 29import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;\r
b4f71e4a 30import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;\r
6c13869b
FC
31import org.eclipse.linuxtools.tmf.core.io.BufferedRandomAccessFile;\r
32import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;\r
7e6347b0 33import org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser;\r
6c13869b 34import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;\r
6c13869b 35import org.eclipse.linuxtools.tmf.core.trace.TmfContext;\r
cb8c854e 36import org.eclipse.linuxtools.tmf.core.trace.TmfLongLocation;\r
6c13869b 37import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;\r
c3c5c786
FC
38import org.w3c.dom.Document;\r
39import org.w3c.dom.Element;\r
40import org.w3c.dom.Node;\r
41import org.w3c.dom.NodeList;\r
42import org.xml.sax.EntityResolver;\r
43import org.xml.sax.ErrorHandler;\r
44import org.xml.sax.InputSource;\r
45import org.xml.sax.SAXException;\r
46import org.xml.sax.SAXParseException;\r
47\r
6256d8ad 48public class CustomXmlTrace extends TmfTrace implements ITmfEventParser {\r
c3c5c786 49\r
cb8c854e 50 private static final TmfLongLocation NULL_LOCATION = new TmfLongLocation((Long) null);\r
3118edf1 51 private static final int DEFAULT_CACHE_SIZE = 100;\r
1b70b6dc 52\r
25e48683
FC
53 private final CustomXmlTraceDefinition fDefinition;\r
54 private final CustomXmlEventType fEventType;\r
55 private final InputElement fRecordInputElement;\r
2a4fba11 56 private BufferedRandomAccessFile fFile;\r
25e48683
FC
57\r
58 public CustomXmlTrace(final CustomXmlTraceDefinition definition) {\r
4bf17f4a 59 fDefinition = definition;\r
60 fEventType = new CustomXmlEventType(fDefinition);\r
61 fRecordInputElement = getRecordInputElement(fDefinition.rootInputElement);\r
c843ebb5 62 setCacheSize(DEFAULT_CACHE_SIZE);\r
4bf17f4a 63 }\r
64\r
b4f71e4a 65 public CustomXmlTrace(final IResource resource, final CustomXmlTraceDefinition definition, final String path, final int pageSize) throws TmfTraceException {\r
c843ebb5
PT
66 this(definition);\r
67 setCacheSize((pageSize > 0) ? pageSize : DEFAULT_CACHE_SIZE);\r
68 initTrace(resource, path, CustomXmlEvent.class);\r
c3c5c786
FC
69 }\r
70\r
1b70b6dc 71 @Override\r
6256d8ad 72 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType) throws TmfTraceException {\r
25e48683 73 super.initTrace(resource, path, eventType);\r
2a4fba11
PT
74 try {\r
75 fFile = new BufferedRandomAccessFile(getPath(), "r"); //$NON-NLS-1$\r
76 } catch (IOException e) {\r
77 throw new TmfTraceException(e.getMessage(), e);\r
78 }\r
64e16ee9 79 indexTrace(false);\r
1b70b6dc
PT
80 }\r
81\r
c3c5c786 82 @Override\r
2a4fba11
PT
83 public synchronized void dispose() {\r
84 super.dispose();\r
85 if (fFile != null) {\r
86 try {\r
87 fFile.close();\r
88 } catch (IOException e) {\r
89 } finally {\r
90 fFile = null;\r
91 }\r
92 }\r
93 }\r
94\r
95 @Override\r
1e1bef82 96 public synchronized TmfContext seekEvent(final ITmfLocation location) {\r
2352aed9 97 final CustomXmlTraceContext context = new CustomXmlTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);\r
2a4fba11 98 if (NULL_LOCATION.equals(location) || fFile == null) {\r
c3c5c786 99 return context;\r
2a4fba11 100 }\r
c3c5c786 101 try {\r
2a4fba11
PT
102 if (location == null) {\r
103 fFile.seek(0);\r
6bab4511
AM
104 } else if (location.getLocationData() instanceof Long) {\r
105 fFile.seek((Long) location.getLocationData());\r
09e86496 106 }\r
c3c5c786 107 String line;\r
25e48683 108 final String recordElementStart = "<" + fRecordInputElement.elementName; //$NON-NLS-1$\r
2a4fba11 109 long rawPos = fFile.getFilePointer();\r
25e48683 110\r
2a4fba11 111 while ((line = fFile.getNextLine()) != null) {\r
25e48683 112 final int idx = line.indexOf(recordElementStart);\r
c3c5c786 113 if (idx != -1) {\r
cb8c854e 114 context.setLocation(new TmfLongLocation(rawPos + idx));\r
c3c5c786
FC
115 return context;\r
116 }\r
2a4fba11 117 rawPos = fFile.getFilePointer();\r
c3c5c786
FC
118 }\r
119 return context;\r
25e48683 120 } catch (final IOException e) {\r
8fd82db5 121 Activator.getDefault().logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$\r
c3c5c786
FC
122 return context;\r
123 }\r
25e48683 124\r
c3c5c786
FC
125 }\r
126\r
c76c54bb 127 @Override\r
2a4fba11
PT
128 public synchronized TmfContext seekEvent(final double ratio) {\r
129 if (fFile == null) {\r
130 return new CustomTxtTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);\r
131 }\r
c76c54bb 132 try {\r
2a4fba11 133 long pos = (long) (ratio * fFile.length());\r
a79913eb 134 while (pos > 0) {\r
2a4fba11
PT
135 fFile.seek(pos - 1);\r
136 if (fFile.read() == '\n') {\r
09e86496
FC
137 break;\r
138 }\r
a79913eb
FC
139 pos--;\r
140 }\r
1e1bef82 141 final ITmfLocation location = new TmfLongLocation(pos);\r
7e6347b0 142 final TmfContext context = seekEvent(location);\r
c76c54bb
FC
143 context.setRank(ITmfContext.UNKNOWN_RANK);\r
144 return context;\r
25e48683 145 } catch (final IOException e) {\r
8fd82db5 146 Activator.getDefault().logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$\r
2352aed9 147 return new CustomXmlTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);\r
c76c54bb
FC
148 }\r
149 }\r
150\r
151 @Override\r
1e1bef82 152 public synchronized double getLocationRatio(final ITmfLocation location) {\r
2a4fba11
PT
153 if (fFile == null) {\r
154 return 0;\r
155 }\r
c76c54bb 156 try {\r
6bab4511
AM
157 if (location.getLocationData() instanceof Long) {\r
158 return (double) ((Long) location.getLocationData()) / fFile.length();\r
c76c54bb 159 }\r
25e48683 160 } catch (final IOException e) {\r
8fd82db5 161 Activator.getDefault().logError("Error getting location ration. File: " + getPath(), e); //$NON-NLS-1$\r
c76c54bb
FC
162 }\r
163 return 0;\r
164 }\r
25e48683 165\r
c3c5c786 166 @Override\r
1e1bef82 167 public ITmfLocation getCurrentLocation() {\r
a79913eb
FC
168 // TODO Auto-generated method stub\r
169 return null;\r
c3c5c786
FC
170 }\r
171\r
2a4fba11
PT
172 @Override\r
173 public synchronized CustomXmlEvent parseEvent(final ITmfContext tmfContext) {\r
174 ITmfContext context = seekEvent(tmfContext.getLocation());\r
175 return parse(context);\r
176 }\r
177\r
c3c5c786 178 @Override\r
c32744d6 179 public synchronized CustomXmlEvent getNext(final ITmfContext context) {\r
25e48683 180 final ITmfContext savedContext = context.clone();\r
2a4fba11 181 final CustomXmlEvent event = parse(context);\r
c3c5c786 182 if (event != null) {\r
d337369a 183 updateAttributes(savedContext, event.getTimestamp());\r
cbdacf03 184 context.increaseRank();\r
c3c5c786
FC
185 }\r
186 return event;\r
187 }\r
188\r
2a4fba11
PT
189 private synchronized CustomXmlEvent parse(final ITmfContext tmfContext) {\r
190 if (fFile == null) {\r
191 return null;\r
192 }\r
193 if (!(tmfContext instanceof CustomXmlTraceContext)) {\r
c3c5c786 194 return null;\r
2a4fba11 195 }\r
25e48683
FC
196\r
197 final CustomXmlTraceContext context = (CustomXmlTraceContext) tmfContext;\r
6bab4511 198 if (!(context.getLocation().getLocationData() instanceof Long) || NULL_LOCATION.equals(context.getLocation())) {\r
c3c5c786 199 return null;\r
2a4fba11 200 }\r
c3c5c786 201\r
2a4fba11
PT
202 CustomXmlEvent event = null;\r
203 try {\r
6bab4511 204 if (fFile.getFilePointer() != (Long)context.getLocation().getLocationData() + 1)\r
2a4fba11 205 {\r
6bab4511 206 fFile.seek((Long)context.getLocation().getLocationData() + 1); // +1 is for the <\r
2a4fba11
PT
207 }\r
208 final StringBuffer elementBuffer = new StringBuffer("<"); //$NON-NLS-1$\r
209 readElement(elementBuffer, fFile);\r
210 final Element element = parseElementBuffer(elementBuffer);\r
211\r
212 event = extractEvent(element, fRecordInputElement);\r
213 ((StringBuffer) event.getContent().getValue()).append(elementBuffer);\r
214\r
215 String line;\r
216 final String recordElementStart = "<" + fRecordInputElement.elementName; //$NON-NLS-1$\r
217 long rawPos = fFile.getFilePointer();\r
218\r
219 while ((line = fFile.getNextLine()) != null) {\r
220 final int idx = line.indexOf(recordElementStart);\r
221 if (idx != -1) {\r
cb8c854e 222 context.setLocation(new TmfLongLocation(rawPos + idx));\r
2a4fba11 223 return event;\r
c3c5c786 224 }\r
2a4fba11 225 rawPos = fFile.getFilePointer();\r
c3c5c786 226 }\r
2a4fba11
PT
227 } catch (final IOException e) {\r
228 Activator.getDefault().logError("Error parsing event. File: " + getPath(), e); //$NON-NLS-1$\r
abbdd66a 229\r
c3c5c786 230 }\r
2a4fba11
PT
231 context.setLocation(NULL_LOCATION);\r
232 return event;\r
c3c5c786
FC
233 }\r
234\r
25e48683 235 private Element parseElementBuffer(final StringBuffer elementBuffer) {\r
c3c5c786 236 try {\r
25e48683
FC
237 final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
238 final DocumentBuilder db = dbf.newDocumentBuilder();\r
c3c5c786
FC
239\r
240 // The following allows xml parsing without access to the dtd\r
25e48683 241 final EntityResolver resolver = new EntityResolver () {\r
d4011df2 242 @Override\r
25e48683
FC
243 public InputSource resolveEntity (final String publicId, final String systemId) {\r
244 final String empty = ""; //$NON-NLS-1$\r
245 final ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
c3c5c786
FC
246 return new InputSource(bais);\r
247 }\r
248 };\r
249 db.setEntityResolver(resolver);\r
250\r
251 // The following catches xml parsing exceptions\r
252 db.setErrorHandler(new ErrorHandler(){\r
d4011df2 253 @Override\r
25e48683 254 public void error(final SAXParseException saxparseexception) throws SAXException {}\r
d4011df2 255 @Override\r
25e48683 256 public void warning(final SAXParseException saxparseexception) throws SAXException {}\r
d4011df2 257 @Override\r
25e48683 258 public void fatalError(final SAXParseException saxparseexception) throws SAXException {\r
c3c5c786
FC
259 throw saxparseexception;\r
260 }});\r
25e48683
FC
261\r
262 final Document doc = db.parse(new ByteArrayInputStream(elementBuffer.toString().getBytes()));\r
c3c5c786 263 return doc.getDocumentElement();\r
25e48683 264 } catch (final ParserConfigurationException e) {\r
8fd82db5 265 Activator.getDefault().logError("Error parsing element buffer. File:" + getPath(), e); //$NON-NLS-1$\r
25e48683 266 } catch (final SAXException e) {\r
8fd82db5 267 Activator.getDefault().logError("Error parsing element buffer. File:" + getPath(), e); //$NON-NLS-1$\r
25e48683 268 } catch (final IOException e) {\r
8fd82db5 269 Activator.getDefault().logError("Error parsing element buffer. File: " + getPath(), e); //$NON-NLS-1$\r
c3c5c786
FC
270 }\r
271 return null;\r
272 }\r
273\r
25e48683 274 private void readElement(final StringBuffer buffer, final RandomAccessFile raFile) {\r
c3c5c786
FC
275 try {\r
276 int numRead = 0;\r
277 boolean startTagClosed = false;\r
278 int i;\r
279 while ((i = raFile.read()) != -1) {\r
280 numRead++;\r
25e48683 281 final char c = (char)i;\r
c3c5c786 282 buffer.append(c);\r
09e86496 283 if (c == '"') {\r
c3c5c786 284 readQuote(buffer, raFile, '"');\r
09e86496 285 } else if (c == '\'') {\r
c3c5c786 286 readQuote(buffer, raFile, '\'');\r
09e86496 287 } else if (c == '<') {\r
c3c5c786 288 readElement(buffer, raFile);\r
09e86496 289 } else if (c == '/' && numRead == 1) {\r
c3c5c786 290 break; // found "</"\r
2352aed9 291 } else if (c == '-' && numRead == 3 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("!-")) { //$NON-NLS-1$\r
c3c5c786 292 readComment(buffer, raFile); // found "<!--"\r
2a4fba11 293 } else if (i == '>') {\r
09e86496 294 if (buffer.charAt(buffer.length() - 2) == '/') {\r
c3c5c786 295 break; // found "/>"\r
09e86496 296 } else if (startTagClosed) {\r
c3c5c786 297 break; // found "<...>...</...>"\r
09e86496
FC
298 }\r
299 else {\r
c3c5c786 300 startTagClosed = true; // found "<...>"\r
09e86496 301 }\r
2a4fba11 302 }\r
c3c5c786
FC
303 }\r
304 return;\r
25e48683 305 } catch (final IOException e) {\r
c3c5c786
FC
306 return;\r
307 }\r
308 }\r
309\r
abbdd66a
AM
310 private static void readQuote(final StringBuffer buffer,\r
311 final RandomAccessFile raFile, final char eq) {\r
c3c5c786
FC
312 try {\r
313 int i;\r
314 while ((i = raFile.read()) != -1) {\r
25e48683 315 final char c = (char)i;\r
c3c5c786 316 buffer.append(c);\r
25e48683 317 if (c == eq)\r
09e86496 318 {\r
c3c5c786 319 break; // found matching end-quote\r
09e86496 320 }\r
c3c5c786
FC
321 }\r
322 return;\r
25e48683 323 } catch (final IOException e) {\r
c3c5c786
FC
324 return;\r
325 }\r
326 }\r
327\r
abbdd66a
AM
328 private static void readComment(final StringBuffer buffer,\r
329 final RandomAccessFile raFile) {\r
c3c5c786
FC
330 try {\r
331 int numRead = 0;\r
332 int i;\r
333 while ((i = raFile.read()) != -1) {\r
334 numRead++;\r
25e48683 335 final char c = (char)i;\r
c3c5c786 336 buffer.append(c);\r
2352aed9 337 if (c == '>' && numRead >= 2 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("--")) //$NON-NLS-1$\r
09e86496 338 {\r
c3c5c786 339 break; // found "-->"\r
09e86496 340 }\r
c3c5c786
FC
341 }\r
342 return;\r
25e48683 343 } catch (final IOException e) {\r
c3c5c786
FC
344 return;\r
345 }\r
346 }\r
347\r
25e48683
FC
348 public static StringBuffer parseElement(final Element parentElement, final StringBuffer buffer) {\r
349 final NodeList nodeList = parentElement.getChildNodes();\r
c3c5c786
FC
350 String separator = null;\r
351 for (int i = 0; i < nodeList.getLength(); i++) {\r
25e48683 352 final Node node = nodeList.item(i);\r
c3c5c786 353 if (node.getNodeType() == Node.ELEMENT_NODE) {\r
09e86496 354 if (separator == null) {\r
3b38ea61 355 separator = " | "; //$NON-NLS-1$\r
09e86496 356 } else {\r
c3c5c786 357 buffer.append(separator);\r
09e86496 358 }\r
25e48683 359 final Element element = (Element) node;\r
9fa32496 360 if (!element.hasChildNodes()) {\r
c3c5c786 361 buffer.append(element.getNodeName());\r
09e86496 362 } else if (element.getChildNodes().getLength() == 1 && element.getFirstChild().getNodeType() == Node.TEXT_NODE) {\r
3b38ea61 363 buffer.append(element.getNodeName() + ":" + element.getFirstChild().getNodeValue().trim()); //$NON-NLS-1$\r
09e86496 364 } else {\r
c3c5c786 365 buffer.append(element.getNodeName());\r
3b38ea61 366 buffer.append(" [ "); //$NON-NLS-1$\r
c3c5c786 367 parseElement(element, buffer);\r
3b38ea61 368 buffer.append(" ]"); //$NON-NLS-1$\r
c3c5c786 369 }\r
2a4fba11 370 } else if (node.getNodeType() == Node.TEXT_NODE) {\r
09e86496 371 if (node.getNodeValue().trim().length() != 0) {\r
c3c5c786 372 buffer.append(node.getNodeValue().trim());\r
09e86496 373 }\r
2a4fba11 374 }\r
c3c5c786
FC
375 }\r
376 return buffer;\r
377 }\r
378\r
25e48683 379 public InputElement getRecordInputElement(final InputElement inputElement) {\r
2a4fba11 380 if (inputElement.logEntry) {\r
c3c5c786 381 return inputElement;\r
2a4fba11 382 } else if (inputElement.childElements != null) {\r
25e48683
FC
383 for (final InputElement childInputElement : inputElement.childElements) {\r
384 final InputElement recordInputElement = getRecordInputElement(childInputElement);\r
2a4fba11 385 if (recordInputElement != null) {\r
c3c5c786 386 return recordInputElement;\r
2a4fba11 387 }\r
c3c5c786 388 }\r
09e86496 389 }\r
c3c5c786
FC
390 return null;\r
391 }\r
25e48683
FC
392\r
393 public CustomXmlEvent extractEvent(final Element element, final InputElement inputElement) {\r
394 final CustomXmlEvent event = new CustomXmlEvent(fDefinition, this, TmfTimestamp.ZERO, "", fEventType,""); //$NON-NLS-1$ //$NON-NLS-2$\r
2a4fba11 395 event.setContent(new CustomEventContent(event, new StringBuffer()));\r
c3c5c786
FC
396 parseElement(element, event, inputElement);\r
397 return event;\r
398 }\r
25e48683
FC
399\r
400 private void parseElement(final Element element, final CustomXmlEvent event, final InputElement inputElement) {\r
09e86496 401 if (inputElement.inputName != null && !inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_IGNORE)) {\r
c3c5c786 402 event.parseInput(parseElement(element, new StringBuffer()).toString(), inputElement.inputName, inputElement.inputAction, inputElement.inputFormat);\r
09e86496
FC
403 }\r
404 if (inputElement.attributes != null) {\r
405 for (final InputAttribute attribute : inputElement.attributes) {\r
c3c5c786 406 event.parseInput(element.getAttribute(attribute.attributeName), attribute.inputName, attribute.inputAction, attribute.inputFormat);\r
09e86496
FC
407 }\r
408 }\r
25e48683 409 final NodeList childNodes = element.getChildNodes();\r
09e86496 410 if (inputElement.childElements != null) {\r
c3c5c786 411 for (int i = 0; i < childNodes.getLength(); i++) {\r
25e48683 412 final Node node = childNodes.item(i);\r
09e86496 413 if (node instanceof Element) {\r
2a4fba11 414 for (final InputElement child : inputElement.childElements) {\r
c3c5c786
FC
415 if (node.getNodeName().equals(child.elementName)) {\r
416 parseElement((Element) node, event, child);\r
417 break;\r
418 }\r
2a4fba11 419 }\r
09e86496 420 }\r
c3c5c786 421 }\r
09e86496 422 }\r
c3c5c786
FC
423 return;\r
424 }\r
425\r
426 public CustomTraceDefinition getDefinition() {\r
427 return fDefinition;\r
428 }\r
2352aed9
FC
429\r
430 /* (non-Javadoc)\r
431 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(org.eclipse.core.resources.IProject, java.lang.String)\r
432 */\r
433 @Override\r
434 public boolean validate(IProject project, String path) {\r
435 return fileExists(path);\r
436 }\r
c3c5c786 437}\r
This page took 0.091718 seconds and 5 git commands to generate.