Commit | Line | Data |
---|---|---|
be222f56 | 1 | /******************************************************************************* |
c8422608 | 2 | * Copyright (c) 2010, 2013 Ericsson |
be222f56 PT |
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.FileWriter; | |
18 | import java.io.IOException; | |
19 | import java.io.StringWriter; | |
20 | import java.util.ArrayList; | |
21 | import java.util.List; | |
22 | ||
23 | import javax.xml.parsers.DocumentBuilder; | |
24 | import javax.xml.parsers.DocumentBuilderFactory; | |
25 | import javax.xml.parsers.ParserConfigurationException; | |
26 | import javax.xml.transform.OutputKeys; | |
27 | import javax.xml.transform.Transformer; | |
28 | import javax.xml.transform.TransformerConfigurationException; | |
29 | import javax.xml.transform.TransformerException; | |
30 | import javax.xml.transform.TransformerFactory; | |
31 | import javax.xml.transform.TransformerFactoryConfigurationError; | |
32 | import javax.xml.transform.dom.DOMSource; | |
33 | import javax.xml.transform.stream.StreamResult; | |
34 | ||
35 | import org.eclipse.linuxtools.internal.tmf.ui.Activator; | |
36 | import org.eclipse.linuxtools.internal.tmf.ui.Messages; | |
52885aeb | 37 | import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceType; |
be222f56 PT |
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 | ||
a0a88f65 AM |
48 | /** |
49 | * Trace definition for custom XML traces. | |
50 | * | |
51 | * @author Patrick Tassé | |
52 | */ | |
be222f56 PT |
53 | public class CustomXmlTraceDefinition extends CustomTraceDefinition { |
54 | ||
a0a88f65 AM |
55 | /** "ignore" tag */ |
56 | public static final String TAG_IGNORE = Messages.CustomXmlTraceDefinition_ignoreTag; | |
57 | ||
58 | /** Name of the XML definitions file */ | |
be222f56 | 59 | protected static final String CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME = "custom_xml_parsers.xml"; //$NON-NLS-1$ |
a0a88f65 AM |
60 | |
61 | /** Path to the XML definitions file */ | |
be222f56 PT |
62 | protected static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME = |
63 | Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString(); | |
64 | ||
be222f56 PT |
65 | private static final String CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomXmlTraceDefinition_definitionRootElement; |
66 | private static final String DEFINITION_ELEMENT = Messages.CustomXmlTraceDefinition_definition; | |
67 | private static final String NAME_ATTRIBUTE = Messages.CustomXmlTraceDefinition_name; | |
68 | private static final String LOG_ENTRY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_logEntry; | |
69 | private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = Messages.CustomXmlTraceDefinition_timestampOutputFormat; | |
70 | private static final String INPUT_ELEMENT_ELEMENT = Messages.CustomXmlTraceDefinition_inputElement; | |
71 | private static final String ATTRIBUTE_ELEMENT = Messages.CustomXmlTraceDefinition_attribute; | |
72 | private static final String INPUT_DATA_ELEMENT = Messages.CustomXmlTraceDefinition_inputData; | |
73 | private static final String ACTION_ATTRIBUTE = Messages.CustomXmlTraceDefinition_action; | |
74 | private static final String FORMAT_ATTRIBUTE = Messages.CustomXmlTraceDefinition_format; | |
75 | private static final String OUTPUT_COLUMN_ELEMENT = Messages.CustomXmlTraceDefinition_outputColumn; | |
76 | ||
a0a88f65 | 77 | /** Top-level input element */ |
be222f56 PT |
78 | public InputElement rootInputElement; |
79 | ||
a0a88f65 AM |
80 | /** |
81 | * Default constructor | |
82 | */ | |
be222f56 PT |
83 | public CustomXmlTraceDefinition() { |
84 | this("", null, new ArrayList<OutputColumn>(), ""); //$NON-NLS-1$ //$NON-NLS-2$ | |
85 | } | |
86 | ||
a0a88f65 AM |
87 | /** |
88 | * Full constructor | |
89 | * | |
90 | * @param logtype | |
91 | * Type of trace type | |
92 | * @param rootElement | |
93 | * The top-level XML element | |
94 | * @param outputs | |
95 | * The list of output columns | |
96 | * @param timeStampOutputFormat | |
97 | * The timestamp format to use | |
98 | */ | |
99 | public CustomXmlTraceDefinition(String logtype, InputElement rootElement, | |
100 | List<OutputColumn> outputs, String timeStampOutputFormat) { | |
be222f56 PT |
101 | this.definitionName = logtype; |
102 | this.rootInputElement = rootElement; | |
103 | this.outputs = outputs; | |
104 | this.timeStampOutputFormat = timeStampOutputFormat; | |
105 | } | |
106 | ||
a0a88f65 AM |
107 | /** |
108 | * Wrapper for input XML elements | |
109 | */ | |
be222f56 | 110 | public static class InputElement { |
a0a88f65 AM |
111 | |
112 | /** Name of the element */ | |
be222f56 | 113 | public String elementName; |
a0a88f65 AM |
114 | |
115 | /** Indicates if this is a log entry */ | |
be222f56 | 116 | public boolean logEntry; |
a0a88f65 AM |
117 | |
118 | /** Name of the input element */ | |
be222f56 | 119 | public String inputName; |
a0a88f65 AM |
120 | |
121 | /** Input action */ | |
be222f56 | 122 | public int inputAction; |
a0a88f65 AM |
123 | |
124 | /** Input format */ | |
be222f56 | 125 | public String inputFormat; |
a0a88f65 AM |
126 | |
127 | /** XML attributes of this element */ | |
be222f56 | 128 | public List<InputAttribute> attributes; |
a0a88f65 AM |
129 | |
130 | /** Parent element */ | |
be222f56 | 131 | public InputElement parentElement; |
a0a88f65 AM |
132 | |
133 | /** Following element in the file */ | |
be222f56 | 134 | public InputElement nextElement; |
a0a88f65 AM |
135 | |
136 | /** Child elements */ | |
be222f56 PT |
137 | public List<InputElement> childElements; |
138 | ||
a0a88f65 AM |
139 | /** |
140 | * Default (empty) constructor | |
141 | */ | |
be222f56 PT |
142 | public InputElement() {} |
143 | ||
a0a88f65 AM |
144 | /** |
145 | * Constructor | |
146 | * | |
147 | * @param elementName | |
148 | * Element name | |
149 | * @param logEntry | |
150 | * If this element is a log entry | |
151 | * @param inputName | |
152 | * Name of the the input | |
153 | * @param inputAction | |
154 | * Input action | |
155 | * @param inputFormat | |
156 | * Input format | |
157 | * @param attributes | |
158 | * XML attributes of this element | |
159 | */ | |
160 | public InputElement(String elementName, boolean logEntry, | |
161 | String inputName, int inputAction, String inputFormat, | |
162 | List<InputAttribute> attributes) { | |
be222f56 PT |
163 | this.elementName = elementName; |
164 | this.logEntry = logEntry; | |
165 | this.inputName = inputName; | |
166 | this.inputAction = inputAction; | |
167 | this.inputFormat = inputFormat; | |
168 | this.attributes = attributes; | |
169 | } | |
170 | ||
a0a88f65 AM |
171 | /** |
172 | * Add a XML attribute to the element | |
173 | * | |
174 | * @param attribute | |
175 | * The attribute to add | |
176 | */ | |
be222f56 PT |
177 | public void addAttribute(InputAttribute attribute) { |
178 | if (attributes == null) { | |
507b1336 | 179 | attributes = new ArrayList<>(1); |
be222f56 PT |
180 | } |
181 | attributes.add(attribute); | |
182 | } | |
183 | ||
a0a88f65 AM |
184 | /** |
185 | * Add a child element to this one. | |
186 | * | |
187 | * @param input | |
188 | * The input element to add as child | |
189 | */ | |
be222f56 PT |
190 | public void addChild(InputElement input) { |
191 | if (childElements == null) { | |
507b1336 | 192 | childElements = new ArrayList<>(1); |
be222f56 PT |
193 | } else if (childElements.size() > 0) { |
194 | InputElement last = childElements.get(childElements.size() - 1); | |
195 | last.nextElement = input; | |
196 | } | |
197 | childElements.add(input); | |
198 | input.parentElement = this; | |
199 | } | |
200 | ||
a0a88f65 AM |
201 | /** |
202 | * Set the following input element. | |
203 | * | |
204 | * @param input | |
205 | * The input element to add as next element | |
206 | */ | |
be222f56 PT |
207 | public void addNext(InputElement input) { |
208 | if (parentElement != null) { | |
209 | int index = parentElement.childElements.indexOf(this); | |
210 | parentElement.childElements.add(index + 1, input); | |
211 | InputElement next = nextElement; | |
212 | nextElement = input; | |
213 | input.nextElement = next; | |
214 | } | |
215 | input.parentElement = this.parentElement; | |
216 | } | |
217 | ||
a0a88f65 AM |
218 | /** |
219 | * Move this element up in its parent's list of children. | |
220 | */ | |
be222f56 PT |
221 | public void moveUp() { |
222 | if (parentElement != null) { | |
223 | int index = parentElement.childElements.indexOf(this); | |
224 | if (index > 0) { | |
225 | parentElement.childElements.add(index - 1 , parentElement.childElements.remove(index)); | |
226 | parentElement.childElements.get(index).nextElement = nextElement; | |
227 | nextElement = parentElement.childElements.get(index); | |
228 | } | |
229 | } | |
230 | } | |
231 | ||
a0a88f65 AM |
232 | /** |
233 | * Move this element down in its parent's list of children. | |
234 | */ | |
be222f56 PT |
235 | public void moveDown() { |
236 | if (parentElement != null) { | |
237 | int index = parentElement.childElements.indexOf(this); | |
238 | if (index < parentElement.childElements.size() - 1) { | |
239 | parentElement.childElements.add(index + 1 , parentElement.childElements.remove(index)); | |
240 | nextElement = parentElement.childElements.get(index).nextElement; | |
241 | parentElement.childElements.get(index).nextElement = this; | |
242 | } | |
243 | } | |
244 | } | |
245 | ||
246 | } | |
247 | ||
a0a88f65 AM |
248 | /** |
249 | * Wrapper for XML element attributes | |
250 | */ | |
be222f56 | 251 | public static class InputAttribute { |
a0a88f65 AM |
252 | |
253 | /** Name of the XML attribute */ | |
be222f56 | 254 | public String attributeName; |
a0a88f65 AM |
255 | |
256 | /** Input name */ | |
be222f56 | 257 | public String inputName; |
a0a88f65 AM |
258 | |
259 | /** Input action */ | |
be222f56 | 260 | public int inputAction; |
a0a88f65 AM |
261 | |
262 | /** Input format */ | |
be222f56 PT |
263 | public String inputFormat; |
264 | ||
a0a88f65 AM |
265 | /** |
266 | * Default (empty) constructor | |
267 | */ | |
be222f56 PT |
268 | public InputAttribute() {} |
269 | ||
a0a88f65 AM |
270 | /** |
271 | * Constructor | |
272 | * | |
273 | * @param attributeName | |
274 | * Name of the XML attribute | |
275 | * @param inputName | |
276 | * Input name | |
277 | * @param inputAction | |
278 | * Input action | |
279 | * @param inputFormat | |
280 | * Input format | |
281 | */ | |
282 | public InputAttribute(String attributeName, String inputName, | |
283 | int inputAction, String inputFormat) { | |
be222f56 PT |
284 | this.attributeName = attributeName; |
285 | this.inputName = inputName; | |
286 | this.inputAction = inputAction; | |
287 | this.inputFormat = inputFormat; | |
288 | } | |
289 | } | |
290 | ||
a0a88f65 | 291 | @Override |
be222f56 PT |
292 | public void save() { |
293 | save(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME); | |
294 | } | |
295 | ||
296 | @Override | |
297 | public void save(String path) { | |
298 | try { | |
299 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
300 | DocumentBuilder db = dbf.newDocumentBuilder(); | |
301 | ||
302 | // The following allows xml parsing without access to the dtd | |
a0a88f65 | 303 | EntityResolver resolver = new EntityResolver() { |
be222f56 | 304 | @Override |
a0a88f65 | 305 | public InputSource resolveEntity(String publicId, String systemId) { |
be222f56 PT |
306 | String empty = ""; //$NON-NLS-1$ |
307 | ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes()); | |
308 | return new InputSource(bais); | |
309 | } | |
310 | }; | |
311 | db.setEntityResolver(resolver); | |
312 | ||
313 | // The following catches xml parsing exceptions | |
a0a88f65 | 314 | db.setErrorHandler(new ErrorHandler() { |
be222f56 | 315 | @Override |
a0a88f65 AM |
316 | public void error(SAXParseException saxparseexception) throws SAXException {} |
317 | ||
be222f56 | 318 | @Override |
a0a88f65 AM |
319 | public void warning(SAXParseException saxparseexception) throws SAXException {} |
320 | ||
be222f56 | 321 | @Override |
a0a88f65 | 322 | public void fatalError(SAXParseException saxparseexception) throws SAXException { |
be222f56 | 323 | throw saxparseexception; |
a0a88f65 AM |
324 | } |
325 | }); | |
be222f56 PT |
326 | |
327 | Document doc = null; | |
328 | File file = new File(path); | |
329 | if (file.canRead()) { | |
330 | doc = db.parse(file); | |
331 | if (! doc.getDocumentElement().getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) { | |
332 | return; | |
333 | } | |
334 | } else { | |
335 | doc = db.newDocument(); | |
336 | Node node = doc.createElement(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT); | |
337 | doc.appendChild(node); | |
338 | } | |
339 | ||
340 | Element root = doc.getDocumentElement(); | |
341 | ||
342 | NodeList nodeList = root.getChildNodes(); | |
343 | for (int i = 0; i < nodeList.getLength(); i++) { | |
344 | Node node = nodeList.item(i); | |
345 | if (node instanceof Element && | |
346 | node.getNodeName().equals(DEFINITION_ELEMENT) && | |
347 | definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) { | |
348 | root.removeChild(node); | |
349 | } | |
350 | } | |
351 | Element definitionElement = doc.createElement(DEFINITION_ELEMENT); | |
352 | root.appendChild(definitionElement); | |
353 | definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName); | |
354 | ||
355 | Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT); | |
356 | definitionElement.appendChild(formatElement); | |
357 | formatElement.appendChild(doc.createTextNode(timeStampOutputFormat)); | |
358 | ||
359 | if (rootInputElement != null) { | |
360 | definitionElement.appendChild(createInputElementElement(rootInputElement, doc)); | |
361 | } | |
362 | ||
363 | if (outputs != null) { | |
364 | for (OutputColumn output : outputs) { | |
365 | Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT); | |
366 | definitionElement.appendChild(outputColumnElement); | |
367 | outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name); | |
368 | } | |
369 | } | |
370 | ||
371 | Transformer transformer = TransformerFactory.newInstance().newTransformer(); | |
372 | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ | |
373 | ||
374 | //initialize StreamResult with File object to save to file | |
375 | StreamResult result = new StreamResult(new StringWriter()); | |
376 | DOMSource source = new DOMSource(doc); | |
377 | transformer.transform(source, result); | |
378 | String xmlString = result.getWriter().toString(); | |
379 | ||
507b1336 AM |
380 | try (FileWriter writer = new FileWriter(file);) { |
381 | writer.write(xmlString); | |
382 | } | |
52885aeb PT |
383 | |
384 | TmfTraceType.getInstance().addCustomTraceType(TmfTraceType.CUSTOM_XML_CATEGORY, definitionName); | |
385 | ||
be222f56 PT |
386 | } catch (ParserConfigurationException e) { |
387 | Activator.getDefault().logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
388 | } catch (TransformerConfigurationException e) { | |
389 | Activator.getDefault().logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
390 | } catch (TransformerFactoryConfigurationError e) { | |
391 | Activator.getDefault().logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
392 | } catch (TransformerException e) { | |
393 | Activator.getDefault().logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
394 | } catch (IOException e) { | |
395 | Activator.getDefault().logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
396 | } catch (SAXException e) { | |
397 | Activator.getDefault().logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
398 | } | |
399 | } | |
400 | ||
401 | private Element createInputElementElement(InputElement inputElement, Document doc) { | |
402 | Element inputElementElement = doc.createElement(INPUT_ELEMENT_ELEMENT); | |
403 | inputElementElement.setAttribute(NAME_ATTRIBUTE, inputElement.elementName); | |
404 | ||
405 | if (inputElement.logEntry) { | |
406 | inputElementElement.setAttribute(LOG_ENTRY_ATTRIBUTE, Boolean.toString(inputElement.logEntry)); | |
407 | } | |
408 | ||
409 | if (inputElement.parentElement != null) { | |
410 | Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT); | |
411 | inputElementElement.appendChild(inputDataElement); | |
412 | inputDataElement.setAttribute(NAME_ATTRIBUTE, inputElement.inputName); | |
413 | inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputElement.inputAction)); | |
414 | if (inputElement.inputFormat != null) { | |
415 | inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputElement.inputFormat); | |
416 | } | |
417 | } | |
418 | ||
419 | if (inputElement.attributes != null) { | |
420 | for (InputAttribute attribute : inputElement.attributes) { | |
421 | Element inputAttributeElement = doc.createElement(ATTRIBUTE_ELEMENT); | |
422 | inputElementElement.appendChild(inputAttributeElement); | |
423 | inputAttributeElement.setAttribute(NAME_ATTRIBUTE, attribute.attributeName); | |
424 | Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT); | |
425 | inputAttributeElement.appendChild(inputDataElement); | |
426 | inputDataElement.setAttribute(NAME_ATTRIBUTE, attribute.inputName); | |
427 | inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(attribute.inputAction)); | |
428 | if (attribute.inputFormat != null) { | |
429 | inputDataElement.setAttribute(FORMAT_ATTRIBUTE, attribute.inputFormat); | |
430 | } | |
431 | } | |
432 | } | |
433 | ||
434 | if (inputElement.childElements != null) { | |
435 | for (InputElement childInputElement : inputElement.childElements) { | |
436 | inputElementElement.appendChild(createInputElementElement(childInputElement, doc)); | |
437 | } | |
438 | } | |
439 | ||
440 | return inputElementElement; | |
441 | } | |
442 | ||
a0a88f65 AM |
443 | /** |
444 | * Load all the XML trace definitions in the default definitions file. | |
445 | * | |
446 | * @return The loaded trace definitions | |
447 | */ | |
be222f56 PT |
448 | public static CustomXmlTraceDefinition[] loadAll() { |
449 | return loadAll(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME); | |
450 | } | |
451 | ||
a0a88f65 AM |
452 | /** |
453 | * Load all the XML trace definitions in the given definitions file. | |
454 | * | |
455 | * @param path | |
456 | * Path to the definitions file to load | |
457 | * @return The loaded trace definitions | |
458 | */ | |
be222f56 PT |
459 | public static CustomXmlTraceDefinition[] loadAll(String path) { |
460 | try { | |
461 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
462 | DocumentBuilder db = dbf.newDocumentBuilder(); | |
463 | ||
464 | // The following allows xml parsing without access to the dtd | |
a0a88f65 | 465 | EntityResolver resolver = new EntityResolver() { |
be222f56 | 466 | @Override |
a0a88f65 | 467 | public InputSource resolveEntity(String publicId, String systemId) { |
be222f56 PT |
468 | String empty = ""; //$NON-NLS-1$ |
469 | ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes()); | |
470 | return new InputSource(bais); | |
471 | } | |
472 | }; | |
473 | db.setEntityResolver(resolver); | |
474 | ||
475 | // The following catches xml parsing exceptions | |
a0a88f65 | 476 | db.setErrorHandler(new ErrorHandler() { |
be222f56 | 477 | @Override |
a0a88f65 AM |
478 | public void error(SAXParseException saxparseexception) throws SAXException {} |
479 | ||
be222f56 | 480 | @Override |
a0a88f65 AM |
481 | public void warning(SAXParseException saxparseexception) throws SAXException {} |
482 | ||
be222f56 | 483 | @Override |
a0a88f65 | 484 | public void fatalError(SAXParseException saxparseexception) throws SAXException { |
be222f56 | 485 | throw saxparseexception; |
a0a88f65 AM |
486 | } |
487 | }); | |
be222f56 PT |
488 | |
489 | File file = new File(path); | |
490 | if (!file.canRead()) { | |
491 | return new CustomXmlTraceDefinition[0]; | |
492 | } | |
493 | Document doc = db.parse(file); | |
494 | ||
495 | Element root = doc.getDocumentElement(); | |
496 | if (! root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) { | |
497 | return new CustomXmlTraceDefinition[0]; | |
498 | } | |
499 | ||
507b1336 | 500 | ArrayList<CustomXmlTraceDefinition> defList = new ArrayList<>(); |
be222f56 PT |
501 | NodeList nodeList = root.getChildNodes(); |
502 | for (int i = 0; i < nodeList.getLength(); i++) { | |
503 | Node node = nodeList.item(i); | |
504 | if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) { | |
505 | CustomXmlTraceDefinition def = extractDefinition((Element) node); | |
506 | if (def != null) { | |
507 | defList.add(def); | |
508 | } | |
509 | } | |
510 | } | |
511 | return defList.toArray(new CustomXmlTraceDefinition[0]); | |
512 | } catch (ParserConfigurationException e) { | |
513 | Activator.getDefault().logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
514 | } catch (SAXException e) { | |
515 | Activator.getDefault().logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
516 | } catch (IOException e) { | |
517 | Activator.getDefault().logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$ | |
518 | } | |
519 | return new CustomXmlTraceDefinition[0]; | |
520 | } | |
521 | ||
a0a88f65 AM |
522 | /** |
523 | * Load the given trace definition. | |
524 | * | |
525 | * @param definitionName | |
526 | * Name of the XML trace definition to load | |
527 | * @return The loaded trace definition | |
528 | */ | |
be222f56 PT |
529 | public static CustomXmlTraceDefinition load(String definitionName) { |
530 | try { | |
531 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
532 | DocumentBuilder db = dbf.newDocumentBuilder(); | |
533 | ||
534 | // The following allows xml parsing without access to the dtd | |
a0a88f65 | 535 | EntityResolver resolver = new EntityResolver() { |
be222f56 | 536 | @Override |
a0a88f65 | 537 | public InputSource resolveEntity(String publicId, String systemId) { |
be222f56 PT |
538 | String empty = ""; //$NON-NLS-1$ |
539 | ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes()); | |
540 | return new InputSource(bais); | |
541 | } | |
542 | }; | |
543 | db.setEntityResolver(resolver); | |
544 | ||
545 | // The following catches xml parsing exceptions | |
a0a88f65 | 546 | db.setErrorHandler(new ErrorHandler() { |
be222f56 | 547 | @Override |
a0a88f65 AM |
548 | public void error(SAXParseException saxparseexception) throws SAXException {} |
549 | ||
be222f56 | 550 | @Override |
a0a88f65 AM |
551 | public void warning(SAXParseException saxparseexception) throws SAXException {} |
552 | ||
be222f56 | 553 | @Override |
a0a88f65 | 554 | public void fatalError(SAXParseException saxparseexception) throws SAXException { |
be222f56 | 555 | throw saxparseexception; |
a0a88f65 AM |
556 | } |
557 | }); | |
be222f56 PT |
558 | |
559 | File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME); | |
560 | Document doc = db.parse(file); | |
561 | ||
562 | Element root = doc.getDocumentElement(); | |
563 | if (! root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) { | |
564 | return null; | |
565 | } | |
566 | ||
567 | NodeList nodeList = root.getChildNodes(); | |
568 | for (int i = 0; i < nodeList.getLength(); i++) { | |
569 | Node node = nodeList.item(i); | |
570 | if (node instanceof Element && | |
571 | node.getNodeName().equals(DEFINITION_ELEMENT) && | |
572 | definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) { | |
573 | return extractDefinition((Element) node); | |
574 | } | |
575 | } | |
576 | } catch (ParserConfigurationException e) { | |
577 | Activator.getDefault().logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
578 | } catch (SAXException e) { | |
579 | Activator.getDefault().logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
580 | } catch (IOException e) { | |
581 | Activator.getDefault().logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
582 | } | |
583 | return null; | |
584 | } | |
585 | ||
a0a88f65 AM |
586 | /** |
587 | * Extract a trace definition from an XML element. | |
588 | * | |
589 | * @param definitionElement | |
590 | * Definition element | |
591 | * @return The extracted trace definition | |
592 | */ | |
be222f56 PT |
593 | public static CustomXmlTraceDefinition extractDefinition(Element definitionElement) { |
594 | CustomXmlTraceDefinition def = new CustomXmlTraceDefinition(); | |
595 | ||
596 | def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE); | |
597 | if (def.definitionName == null) { | |
598 | return null; | |
599 | } | |
600 | ||
601 | NodeList nodeList = definitionElement.getChildNodes(); | |
602 | for (int i = 0; i < nodeList.getLength(); i++) { | |
603 | Node node = nodeList.item(i); | |
604 | String nodeName = node.getNodeName(); | |
605 | if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) { | |
606 | Element formatElement = (Element) node; | |
607 | def.timeStampOutputFormat = formatElement.getTextContent(); | |
608 | } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) { | |
609 | InputElement inputElement = extractInputElement((Element) node); | |
610 | if (inputElement != null) { | |
611 | if (def.rootInputElement == null) { | |
612 | def.rootInputElement = inputElement; | |
613 | } else { | |
614 | return null; | |
615 | } | |
616 | } | |
617 | } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) { | |
618 | Element outputColumnElement = (Element) node; | |
619 | OutputColumn outputColumn = new OutputColumn(); | |
620 | outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE); | |
621 | def.outputs.add(outputColumn); | |
622 | } | |
623 | } | |
624 | return def; | |
625 | } | |
626 | ||
627 | private static InputElement extractInputElement(Element inputElementElement) { | |
628 | InputElement inputElement = new InputElement(); | |
629 | inputElement.elementName = inputElementElement.getAttribute(NAME_ATTRIBUTE); | |
630 | inputElement.logEntry = (Boolean.toString(true).equals(inputElementElement.getAttribute(LOG_ENTRY_ATTRIBUTE))) ? true : false; | |
631 | NodeList nodeList = inputElementElement.getChildNodes(); | |
632 | for (int i = 0; i < nodeList.getLength(); i++) { | |
633 | Node node = nodeList.item(i); | |
634 | String nodeName = node.getNodeName(); | |
635 | if (nodeName.equals(INPUT_DATA_ELEMENT)) { | |
636 | Element inputDataElement = (Element) node; | |
637 | inputElement.inputName = inputDataElement.getAttribute(NAME_ATTRIBUTE); | |
638 | inputElement.inputAction = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE)); | |
639 | inputElement.inputFormat = inputDataElement.getAttribute(FORMAT_ATTRIBUTE); | |
640 | } else if (nodeName.equals(ATTRIBUTE_ELEMENT)) { | |
641 | Element attributeElement = (Element) node; | |
642 | InputAttribute attribute = new InputAttribute(); | |
643 | attribute.attributeName = attributeElement.getAttribute(NAME_ATTRIBUTE); | |
644 | NodeList attributeNodeList = attributeElement.getChildNodes(); | |
645 | for (int j = 0; j < attributeNodeList.getLength(); j++) { | |
646 | Node attributeNode = attributeNodeList.item(j); | |
647 | String attributeNodeName = attributeNode.getNodeName(); | |
648 | if (attributeNodeName.equals(INPUT_DATA_ELEMENT)) { | |
649 | Element inputDataElement = (Element) attributeNode; | |
650 | attribute.inputName = inputDataElement.getAttribute(NAME_ATTRIBUTE); | |
651 | attribute.inputAction = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE)); | |
652 | attribute.inputFormat = inputDataElement.getAttribute(FORMAT_ATTRIBUTE); | |
653 | } | |
654 | } | |
655 | inputElement.addAttribute(attribute); | |
656 | } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) { | |
657 | Element childInputElementElement = (Element) node; | |
658 | InputElement childInputElement = extractInputElement(childInputElementElement); | |
659 | if (childInputElement != null) { | |
660 | inputElement.addChild(childInputElement); | |
661 | } | |
662 | } | |
663 | } | |
664 | return inputElement; | |
665 | } | |
666 | ||
a0a88f65 AM |
667 | /** |
668 | * Delete the given trace definition from the list of currently loaded ones. | |
669 | * | |
670 | * @param definitionName | |
671 | * Name of the trace definition to delete | |
672 | */ | |
be222f56 PT |
673 | public static void delete(String definitionName) { |
674 | try { | |
675 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
676 | DocumentBuilder db = dbf.newDocumentBuilder(); | |
677 | ||
678 | // The following allows xml parsing without access to the dtd | |
a0a88f65 | 679 | EntityResolver resolver = new EntityResolver() { |
be222f56 | 680 | @Override |
a0a88f65 | 681 | public InputSource resolveEntity(String publicId, String systemId) { |
be222f56 PT |
682 | String empty = ""; //$NON-NLS-1$ |
683 | ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes()); | |
684 | return new InputSource(bais); | |
685 | } | |
686 | }; | |
687 | db.setEntityResolver(resolver); | |
688 | ||
689 | // The following catches xml parsing exceptions | |
a0a88f65 | 690 | db.setErrorHandler(new ErrorHandler() { |
be222f56 | 691 | @Override |
a0a88f65 AM |
692 | public void error(SAXParseException saxparseexception) throws SAXException {} |
693 | ||
be222f56 | 694 | @Override |
a0a88f65 AM |
695 | public void warning(SAXParseException saxparseexception) throws SAXException {} |
696 | ||
be222f56 | 697 | @Override |
a0a88f65 | 698 | public void fatalError(SAXParseException saxparseexception) throws SAXException { |
be222f56 | 699 | throw saxparseexception; |
a0a88f65 AM |
700 | } |
701 | }); | |
be222f56 PT |
702 | |
703 | File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME); | |
704 | Document doc = db.parse(file); | |
705 | ||
706 | Element root = doc.getDocumentElement(); | |
707 | if (! root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) { | |
708 | return; | |
709 | } | |
710 | ||
711 | NodeList nodeList = root.getChildNodes(); | |
712 | for (int i = 0; i < nodeList.getLength(); i++) { | |
713 | Node node = nodeList.item(i); | |
714 | if (node instanceof Element && | |
715 | node.getNodeName().equals(DEFINITION_ELEMENT) && | |
716 | definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) { | |
717 | root.removeChild(node); | |
718 | } | |
719 | } | |
720 | ||
721 | Transformer transformer = TransformerFactory.newInstance().newTransformer(); | |
722 | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ | |
723 | ||
724 | //initialize StreamResult with File object to save to file | |
725 | StreamResult result = new StreamResult(new StringWriter()); | |
726 | DOMSource source = new DOMSource(doc); | |
727 | transformer.transform(source, result); | |
728 | String xmlString = result.getWriter().toString(); | |
729 | ||
507b1336 AM |
730 | try (FileWriter writer = new FileWriter(file);) { |
731 | writer.write(xmlString); | |
732 | } | |
52885aeb PT |
733 | |
734 | TmfTraceType.getInstance().removeCustomTraceType(TmfTraceType.CUSTOM_XML_CATEGORY, definitionName); | |
735 | ||
be222f56 PT |
736 | } catch (ParserConfigurationException e) { |
737 | Activator.getDefault().logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
738 | } catch (SAXException e) { | |
739 | Activator.getDefault().logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
740 | } catch (IOException e) { | |
741 | Activator.getDefault().logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
742 | } catch (TransformerConfigurationException e) { | |
743 | Activator.getDefault().logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
744 | } catch (TransformerFactoryConfigurationError e) { | |
745 | Activator.getDefault().logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
746 | } catch (TransformerException e) { | |
747 | Activator.getDefault().logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$ | |
748 | } | |
749 | } | |
750 | } |