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