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