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