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