2010-10-26 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug309042
[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.event.TmfEvent;
26 import org.eclipse.linuxtools.tmf.event.TmfEventReference;
27 import org.eclipse.linuxtools.tmf.event.TmfEventSource;
28 import org.eclipse.linuxtools.tmf.event.TmfEventType;
29 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
30 import org.eclipse.linuxtools.tmf.trace.ITmfContext;
31 import org.eclipse.linuxtools.tmf.trace.ITmfLocation;
32 import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
33 import org.eclipse.linuxtools.tmf.trace.TmfContext;
34 import org.eclipse.linuxtools.tmf.trace.TmfLocation;
35 import org.eclipse.linuxtools.tmf.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 CustomXmlTraceDefinition fDefinition;
51 private InputElement fRecordInputElement;
52
53 public CustomXmlTrace(String name, CustomXmlTraceDefinition definition, String path, int cacheSize) throws FileNotFoundException {
54 super(name, CustomXmlEvent.class, path, cacheSize);
55 fDefinition = definition;
56 fRecordInputElement = getRecordInputElement(fDefinition.rootInputElement);
57 }
58
59 @Override
60 public TmfContext seekLocation(ITmfLocation<?> location) {
61 //System.out.println(Thread.currentThread().getName() + "::" + getName() + " seekLocation(" + ((location == null || location.getLocation() == null) ? "null" : location) + ")");
62 //new Throwable().printStackTrace();
63 CustomXmlTraceContext context = new CustomXmlTraceContext(new TmfLocation<Long>((Long)null), ITmfContext.INITIAL_RANK);
64 if (!new File(getPath()).isFile()) {
65 return context;
66 }
67 try {
68 context.raFile = new RandomAccessFile(getPath(), "r");
69 if (location != null && location.getLocation() instanceof Long) {
70 context.raFile.seek((Long)location.getLocation());
71 }
72
73 String line;
74 String recordElementStart = "<" + fRecordInputElement.elementName;
75 long rawPos = context.raFile.getFilePointer();
76
77 while ((line = context.raFile.readLine()) != null) {
78 int idx = line.indexOf(recordElementStart);
79 if (idx != -1) {
80 context.setLocation(new TmfLocation<Long>(rawPos + idx));
81 return context;
82 }
83 rawPos = context.raFile.getFilePointer();
84 }
85 return context;
86 } catch (FileNotFoundException e) {
87 e.printStackTrace();
88 return context;
89 } catch (IOException e) {
90 e.printStackTrace();
91 return context;
92 }
93
94 }
95
96 @Override
97 public ITmfTrace createTraceCopy() {
98 // TODO Auto-generated method stub
99 return null;
100 }
101
102 @Override
103 public ITmfLocation<?> getCurrentLocation() {
104 return new TmfLocation<Object>(null);
105 }
106
107 @Override
108 public synchronized TmfEvent getNextEvent(TmfContext context) {
109 ITmfContext savedContext = context.clone();
110 TmfEvent event = parseEvent(context);
111 if (event != null) {
112 updateIndex(savedContext, savedContext.getRank(), event.getTimestamp());
113 context.updateRank(1);
114 }
115 return event;
116 }
117
118 @Override
119 public TmfEvent parseEvent(TmfContext tmfContext) {
120 //System.out.println(Thread.currentThread().getName() + ":: " + getName() + " parseEvent(" + tmfContext.getRank() + " @ " + (tmfContext.getLocation().getLocation() == null ? "null" : tmfContext.getLocation()));
121 if (!(tmfContext instanceof CustomXmlTraceContext)) {
122 return null;
123 }
124
125 CustomXmlTraceContext context = (CustomXmlTraceContext) tmfContext;
126 if (!(context.getLocation().getLocation() instanceof Long)) {
127 return null;
128 }
129
130 synchronized (context.raFile) {
131 CustomXmlEvent event = null;
132 try {
133 if (context.raFile.getFilePointer() != (Long)context.getLocation().getLocation() + 1) {
134 context.raFile.seek((Long)context.getLocation().getLocation() + 1); // +1 is for the <
135 }
136 StringBuffer elementBuffer = new StringBuffer("<");
137 readElement(elementBuffer, context.raFile);
138 Element element = parseElementBuffer(elementBuffer);
139
140 event = extractEvent(element, fRecordInputElement);
141
142 String line;
143 String recordElementStart = "<" + fRecordInputElement.elementName;
144 long rawPos = context.raFile.getFilePointer();
145
146 while ((line = context.raFile.readLine()) != null) {
147 int idx = line.indexOf(recordElementStart);
148 if (idx != -1) {
149 context.setLocation(new TmfLocation<Long>(rawPos + idx));
150 return event;
151 }
152 rawPos = context.raFile.getFilePointer();
153 }
154 } catch (IOException e) {
155 e.printStackTrace();
156 }
157 context.setLocation(new TmfLocation<Long>((Long)null));
158 return event;
159 }
160 }
161
162 private Element parseElementBuffer(StringBuffer elementBuffer) {
163 try {
164 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
165 DocumentBuilder db = dbf.newDocumentBuilder();
166
167 // The following allows xml parsing without access to the dtd
168 EntityResolver resolver = new EntityResolver () {
169 @Override
170 public InputSource resolveEntity (String publicId, String systemId) {
171 String empty = "";
172 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
173 return new InputSource(bais);
174 }
175 };
176 db.setEntityResolver(resolver);
177
178 // The following catches xml parsing exceptions
179 db.setErrorHandler(new ErrorHandler(){
180 @Override
181 public void error(SAXParseException saxparseexception) throws SAXException {}
182 @Override
183 public void warning(SAXParseException saxparseexception) throws SAXException {}
184 @Override
185 public void fatalError(SAXParseException saxparseexception) throws SAXException {
186 throw saxparseexception;
187 }});
188
189 Document doc = db.parse(new ByteArrayInputStream(elementBuffer.toString().getBytes()));
190 return doc.getDocumentElement();
191 } catch (ParserConfigurationException e) {
192 e.printStackTrace();
193 } catch (SAXException e) {
194 e.printStackTrace();
195 } catch (IOException e) {
196 e.printStackTrace();
197 }
198 return null;
199 }
200
201 private void readElement(StringBuffer buffer, RandomAccessFile raFile) {
202 try {
203 int numRead = 0;
204 boolean startTagClosed = false;
205 int i;
206 while ((i = raFile.read()) != -1) {
207 numRead++;
208 char c = (char)i;
209 buffer.append(c);
210 if (c == '"') {
211 readQuote(buffer, raFile, '"');
212 } else if (c == '\'') {
213 readQuote(buffer, raFile, '\'');
214 } else if (c == '<') {
215 readElement(buffer, raFile);
216 } else if (c == '/' && numRead == 1) {
217 break; // found "</"
218 } else if (c == '-' && numRead == 3 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("!-")) {
219 readComment(buffer, raFile); // found "<!--"
220 } else if (i == '>') {
221 if (buffer.charAt(buffer.length() - 2) == '/') {
222 break; // found "/>"
223 } else if (startTagClosed) {
224 break; // found "<...>...</...>"
225 } else {
226 startTagClosed = true; // found "<...>"
227 }
228 }
229 }
230 return;
231 } catch (IOException e) {
232 return;
233 }
234 }
235
236 private void readQuote(StringBuffer buffer, RandomAccessFile raFile, char eq) {
237 try {
238 int i;
239 while ((i = raFile.read()) != -1) {
240 char c = (char)i;
241 buffer.append(c);
242 if (c == eq) {
243 break; // found matching end-quote
244 }
245 }
246 return;
247 } catch (IOException e) {
248 return;
249 }
250 }
251
252 private void readComment(StringBuffer buffer, RandomAccessFile raFile) {
253 try {
254 int numRead = 0;
255 int i;
256 while ((i = raFile.read()) != -1) {
257 numRead++;
258 char c = (char)i;
259 buffer.append(c);
260 if (c == '>' && numRead >= 2 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("--")) {
261 break; // found "-->"
262 }
263 }
264 return;
265 } catch (IOException e) {
266 return;
267 }
268 }
269
270 public static StringBuffer parseElement(Element parentElement, StringBuffer buffer) {
271 NodeList nodeList = parentElement.getChildNodes();
272 String separator = null;
273 for (int i = 0; i < nodeList.getLength(); i++) {
274 Node node = nodeList.item(i);
275 if (node.getNodeType() == Node.ELEMENT_NODE) {
276 if (separator == null) {
277 separator = " | ";
278 } else {
279 buffer.append(separator);
280 }
281 Element element = (Element) node;
282 if (element.hasChildNodes() == false) {
283 buffer.append(element.getNodeName());
284 } else if (element.getChildNodes().getLength() == 1 && element.getFirstChild().getNodeType() == Node.TEXT_NODE) {
285 buffer.append(element.getNodeName() + ":" + element.getFirstChild().getNodeValue().trim());
286 } else {
287 buffer.append(element.getNodeName());
288 buffer.append(" [ ");
289 parseElement(element, buffer);
290 buffer.append(" ]");
291 }
292 } else if (node.getNodeType() == Node.TEXT_NODE) {
293 if (node.getNodeValue().trim().length() != 0) {
294 buffer.append(node.getNodeValue().trim());
295 }
296 }
297 }
298 return buffer;
299 }
300
301 public InputElement getRecordInputElement(InputElement inputElement) {
302 if (inputElement.logEntry) {
303 return inputElement;
304 } else if (inputElement.childElements != null) {
305 for (InputElement childInputElement : inputElement.childElements) {
306 InputElement recordInputElement = getRecordInputElement(childInputElement);
307 if (recordInputElement != null) {
308 return recordInputElement;
309 }
310 }
311 }
312 return null;
313 }
314
315 public CustomXmlEvent extractEvent(Element element, InputElement inputElement) {
316 CustomXmlEvent event = new CustomXmlEvent(fDefinition, TmfTimestamp.Zero, new TmfEventSource(""), new TmfEventType(fDefinition.definitionName, new String[0]), new TmfEventReference(""));
317 parseElement(element, event, inputElement);
318 return event;
319 }
320
321 private void parseElement(Element element, CustomXmlEvent event, InputElement inputElement) {
322 if (inputElement.inputName != null && !inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_IGNORE)) {
323 event.parseInput(parseElement(element, new StringBuffer()).toString(), inputElement.inputName, inputElement.inputAction, inputElement.inputFormat);
324 }
325 if (inputElement.attributes != null) {
326 for (InputAttribute attribute : inputElement.attributes) {
327 event.parseInput(element.getAttribute(attribute.attributeName), attribute.inputName, attribute.inputAction, attribute.inputFormat);
328 }
329 }
330 NodeList childNodes = element.getChildNodes();
331 if (inputElement.childElements != null) {
332 for (int i = 0; i < childNodes.getLength(); i++) {
333 Node node = childNodes.item(i);
334 if (node instanceof Element) {
335 for (InputElement child : inputElement.childElements) {
336 if (node.getNodeName().equals(child.elementName)) {
337 parseElement((Element) node, event, child);
338 break;
339 }
340 }
341 }
342 }
343 }
344 return;
345 }
346
347 public CustomTraceDefinition getDefinition() {
348 return fDefinition;
349 }
350 }
This page took 0.04136 seconds and 5 git commands to generate.