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