tmf: Add unit tests for PeriodicMarkerEventSource
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / parsers / custom / CustomXmlTraceDefinition.java
CommitLineData
be222f56 1/*******************************************************************************
c9b31f60 2 * Copyright (c) 2010, 2015 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
70b7bc9c 11 * Matthew Khouzam - Add support for default xml parsers
be222f56
PT
12 *******************************************************************************/
13
2bdf0193 14package org.eclipse.tracecompass.tmf.core.parsers.custom;
be222f56 15
7a0b1e3c
PT
16import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
be222f56
PT
18import java.io.ByteArrayInputStream;
19import java.io.File;
1d8ab692 20import java.io.FileInputStream;
be222f56
PT
21import java.io.FileWriter;
22import java.io.IOException;
1d8ab692 23import java.io.InputStream;
be222f56
PT
24import java.io.StringWriter;
25import java.util.ArrayList;
70b7bc9c
MK
26import java.util.Arrays;
27import java.util.Comparator;
be222f56 28import java.util.List;
70b7bc9c
MK
29import java.util.Set;
30import java.util.TreeSet;
be222f56
PT
31
32import javax.xml.parsers.DocumentBuilder;
33import javax.xml.parsers.DocumentBuilderFactory;
34import javax.xml.parsers.ParserConfigurationException;
35import javax.xml.transform.OutputKeys;
36import javax.xml.transform.Transformer;
be222f56
PT
37import javax.xml.transform.TransformerException;
38import javax.xml.transform.TransformerFactory;
39import javax.xml.transform.TransformerFactoryConfigurationError;
40import javax.xml.transform.dom.DOMSource;
41import javax.xml.transform.stream.StreamResult;
42
70b7bc9c 43import org.eclipse.core.runtime.Platform;
2bdf0193
AM
44import org.eclipse.tracecompass.internal.tmf.core.Activator;
45import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
be222f56
PT
46import org.w3c.dom.Document;
47import org.w3c.dom.Element;
48import org.w3c.dom.Node;
49import org.w3c.dom.NodeList;
50import org.xml.sax.EntityResolver;
51import org.xml.sax.ErrorHandler;
52import org.xml.sax.InputSource;
53import org.xml.sax.SAXException;
54import org.xml.sax.SAXParseException;
55
a0a88f65
AM
56/**
57 * Trace definition for custom XML traces.
58 *
59 * @author Patrick Tassé
60 */
be222f56
PT
61public class CustomXmlTraceDefinition extends CustomTraceDefinition {
62
a0a88f65
AM
63 /** "ignore" tag */
64 public static final String TAG_IGNORE = Messages.CustomXmlTraceDefinition_ignoreTag;
65
c9b31f60
BH
66 /**
67 * Custom XML label used internally and therefore should not be externalized
68 */
69 public static final String CUSTOM_XML_CATEGORY = "Custom XML"; //$NON-NLS-1$
70
71
70b7bc9c
MK
72 /** Name of the default XML definitions file */
73 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME = "custom_xml_default_parsers.xml"; //$NON-NLS-1$
74
a0a88f65 75 /** Name of the XML definitions file */
be222f56 76 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME = "custom_xml_parsers.xml"; //$NON-NLS-1$
a0a88f65 77
70b7bc9c
MK
78 /** Path to the XML definitions file */
79 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME =
cb1cf0e8
MK
80 Platform.getInstallLocation().getURL().getPath() + "templates/org.eclipse.linuxtools.tmf.core/" + //$NON-NLS-1$
81 CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME;
70b7bc9c 82
a0a88f65 83 /** Path to the XML definitions file */
be222f56 84 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME =
70b7bc9c 85 Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();
be222f56 86
cb1cf0e8 87 /**
c9b31f60 88 * Legacy path to the XML definitions file (in the UI plug-in of linux tools) TODO Remove
cb1cf0e8
MK
89 * once we feel the transition phase is over.
90 */
c9b31f60 91 private static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI =
03573754
AM
92 Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
93 .append("org.eclipse.linuxtools.tmf.ui") //$NON-NLS-1$
94 .append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();
95
c9b31f60
BH
96 /**
97 * Legacy path to the XML definitions file (in the core plug-in of linux tools) TODO Remove
98 * once we feel the transition phase is over.
99 */
100 private static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE =
101 Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
102 .append("org.eclipse.linuxtools.tmf.core") //$NON-NLS-1$
103 .append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();
104
332527a4 105 // TODO: These strings should not be externalized
be222f56
PT
106 private static final String CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomXmlTraceDefinition_definitionRootElement;
107 private static final String DEFINITION_ELEMENT = Messages.CustomXmlTraceDefinition_definition;
332527a4 108 private static final String CATEGORY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_category;
be222f56
PT
109 private static final String NAME_ATTRIBUTE = Messages.CustomXmlTraceDefinition_name;
110 private static final String LOG_ENTRY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_logEntry;
111 private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = Messages.CustomXmlTraceDefinition_timestampOutputFormat;
112 private static final String INPUT_ELEMENT_ELEMENT = Messages.CustomXmlTraceDefinition_inputElement;
113 private static final String ATTRIBUTE_ELEMENT = Messages.CustomXmlTraceDefinition_attribute;
114 private static final String INPUT_DATA_ELEMENT = Messages.CustomXmlTraceDefinition_inputData;
115 private static final String ACTION_ATTRIBUTE = Messages.CustomXmlTraceDefinition_action;
116 private static final String FORMAT_ATTRIBUTE = Messages.CustomXmlTraceDefinition_format;
117 private static final String OUTPUT_COLUMN_ELEMENT = Messages.CustomXmlTraceDefinition_outputColumn;
118
a0a88f65 119 /** Top-level input element */
a7418109 120 public CustomXmlInputElement rootInputElement;
be222f56 121
a0a88f65
AM
122 /**
123 * Default constructor
124 */
be222f56 125 public CustomXmlTraceDefinition() {
c9b31f60 126 this(CUSTOM_XML_CATEGORY, "", null, new ArrayList<OutputColumn>(), ""); //$NON-NLS-1$ //$NON-NLS-2$
be222f56
PT
127 }
128
332527a4
PT
129 /**
130 * Full constructor
131 *
132 * @param category
133 * Category of the trace type
134 * @param traceType
135 * Name of the trace type
136 * @param rootElement
137 * The top-level XML element
138 * @param outputs
139 * The list of output columns
140 * @param timeStampOutputFormat
141 * The timestamp format to use
332527a4 142 */
a7418109 143 public CustomXmlTraceDefinition(String category, String traceType, CustomXmlInputElement rootElement,
332527a4
PT
144 List<OutputColumn> outputs, String timeStampOutputFormat) {
145 this.categoryName = category;
146 this.definitionName = traceType;
be222f56
PT
147 this.rootInputElement = rootElement;
148 this.outputs = outputs;
149 this.timeStampOutputFormat = timeStampOutputFormat;
150 }
151
a0a88f65 152 @Override
be222f56
PT
153 public void save() {
154 save(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
155 }
156
70b7bc9c 157 @Override
be222f56
PT
158 public void save(String path) {
159 try {
160 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
161 DocumentBuilder db = dbf.newDocumentBuilder();
162
163 // The following allows xml parsing without access to the dtd
cb1cf0e8 164 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
165
166 // The following catches xml parsing exceptions
cb1cf0e8 167 db.setErrorHandler(createErrorHandler());
be222f56
PT
168
169 Document doc = null;
170 File file = new File(path);
171 if (file.canRead()) {
172 doc = db.parse(file);
70b7bc9c 173 if (!doc.getDocumentElement().getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
174 return;
175 }
176 } else {
177 doc = db.newDocument();
178 Node node = doc.createElement(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT);
179 doc.appendChild(node);
180 }
181
182 Element root = doc.getDocumentElement();
183
332527a4
PT
184 Element oldDefinitionElement = findDefinitionElement(root, categoryName, definitionName);
185 if (oldDefinitionElement != null) {
186 root.removeChild(oldDefinitionElement);
be222f56
PT
187 }
188 Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
189 root.appendChild(definitionElement);
332527a4 190 definitionElement.setAttribute(CATEGORY_ATTRIBUTE, categoryName);
be222f56
PT
191 definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);
192
193 Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);
194 definitionElement.appendChild(formatElement);
195 formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));
196
197 if (rootInputElement != null) {
198 definitionElement.appendChild(createInputElementElement(rootInputElement, doc));
199 }
200
201 if (outputs != null) {
202 for (OutputColumn output : outputs) {
203 Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);
204 definitionElement.appendChild(outputColumnElement);
205 outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);
206 }
207 }
208
209 Transformer transformer = TransformerFactory.newInstance().newTransformer();
210 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
211
70b7bc9c 212 // initialize StreamResult with File object to save to file
be222f56
PT
213 StreamResult result = new StreamResult(new StringWriter());
214 DOMSource source = new DOMSource(doc);
215 transformer.transform(source, result);
216 String xmlString = result.getWriter().toString();
217
507b1336
AM
218 try (FileWriter writer = new FileWriter(file);) {
219 writer.write(xmlString);
220 }
52885aeb 221
4b3b667b 222 TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
52885aeb 223
cb1cf0e8 224 } catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException | IOException | SAXException e) {
47aafe74 225 Activator.logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56
PT
226 }
227 }
228
a7418109 229 private Element createInputElementElement(CustomXmlInputElement inputElement, Document doc) {
be222f56 230 Element inputElementElement = doc.createElement(INPUT_ELEMENT_ELEMENT);
a7418109 231 inputElementElement.setAttribute(NAME_ATTRIBUTE, inputElement.getElementName());
be222f56 232
a7418109
MK
233 if (inputElement.isLogEntry()) {
234 inputElementElement.setAttribute(LOG_ENTRY_ATTRIBUTE, Boolean.toString(inputElement.isLogEntry()));
be222f56
PT
235 }
236
a7418109 237 if (inputElement.getParentElement() != null) {
be222f56
PT
238 Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
239 inputElementElement.appendChild(inputDataElement);
a7418109
MK
240 inputDataElement.setAttribute(NAME_ATTRIBUTE, inputElement.getInputName());
241 inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputElement.getInputAction()));
242 if (inputElement.getInputFormat() != null) {
243 inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputElement.getInputFormat());
be222f56
PT
244 }
245 }
246
a7418109
MK
247 if (inputElement.getAttributes() != null) {
248 for (CustomXmlInputAttribute attribute : inputElement.getAttributes()) {
be222f56
PT
249 Element inputAttributeElement = doc.createElement(ATTRIBUTE_ELEMENT);
250 inputElementElement.appendChild(inputAttributeElement);
a7418109 251 inputAttributeElement.setAttribute(NAME_ATTRIBUTE, attribute.getAttributeName());
be222f56
PT
252 Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
253 inputAttributeElement.appendChild(inputDataElement);
a7418109
MK
254 inputDataElement.setAttribute(NAME_ATTRIBUTE, attribute.getInputName());
255 inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(attribute.getInputAction()));
256 if (attribute.getInputFormat() != null) {
257 inputDataElement.setAttribute(FORMAT_ATTRIBUTE, attribute.getInputFormat());
be222f56
PT
258 }
259 }
260 }
261
a7418109
MK
262 if (inputElement.getChildElements() != null) {
263 for (CustomXmlInputElement childInputElement : inputElement.getChildElements()) {
be222f56
PT
264 inputElementElement.appendChild(createInputElementElement(childInputElement, doc));
265 }
266 }
267
268 return inputElementElement;
269 }
270
a0a88f65 271 /**
54af96ab
PT
272 * Load all custom XML trace definitions, including the user-defined and
273 * default (built-in) parsers.
a0a88f65
AM
274 *
275 * @return The loaded trace definitions
276 */
be222f56 277 public static CustomXmlTraceDefinition[] loadAll() {
54af96ab
PT
278 return loadAll(true);
279 }
280
281 /**
282 * Load all custom XML trace definitions, including the user-defined and,
283 * optionally, the default (built-in) parsers.
284 *
285 * @param includeDefaults
286 * if true, the default (built-in) parsers are included
287 *
288 * @return The loaded trace definitions
54af96ab
PT
289 */
290 public static CustomXmlTraceDefinition[] loadAll(boolean includeDefaults) {
03573754 291 File defaultFile = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
c9b31f60
BH
292 File legacyFileUI = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI);
293 File legacyFileCore = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE);
03573754
AM
294
295 /*
296 * If there is no file at the expected location, check the legacy
c9b31f60 297 * locations instead.
03573754 298 */
c9b31f60
BH
299 if (!defaultFile.exists()) {
300 if (legacyFileCore.exists()) {
301 transferDefinitions(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE);
302 } else if (legacyFileUI.exists()) {
303 transferDefinitions(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI);
03573754
AM
304 }
305 }
306
70b7bc9c 307 Set<CustomXmlTraceDefinition> defs = new TreeSet<>(new Comparator<CustomXmlTraceDefinition>() {
70b7bc9c
MK
308 @Override
309 public int compare(CustomXmlTraceDefinition o1, CustomXmlTraceDefinition o2) {
c22ca172
PT
310 int result = o1.categoryName.compareTo(o2.categoryName);
311 if (result != 0) {
312 return result;
313 }
70b7bc9c
MK
314 return o1.definitionName.compareTo(o2.definitionName);
315 }
316 });
317 defs.addAll(Arrays.asList(loadAll(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME)));
54af96ab
PT
318 if (includeDefaults) {
319 defs.addAll(Arrays.asList(loadAll(CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME)));
320 }
70b7bc9c 321 return defs.toArray(new CustomXmlTraceDefinition[0]);
be222f56
PT
322 }
323
c9b31f60
BH
324 private static void transferDefinitions(String defFile) {
325 CustomXmlTraceDefinition[] oldDefs = loadAll(defFile);
326 for (CustomXmlTraceDefinition def : oldDefs) {
327 /* Save in the new location */
328 def.save();
329 }
330 }
331
332
a0a88f65
AM
333 /**
334 * Load all the XML trace definitions in the given definitions file.
335 *
336 * @param path
337 * Path to the definitions file to load
338 * @return The loaded trace definitions
339 */
be222f56 340 public static CustomXmlTraceDefinition[] loadAll(String path) {
1d8ab692
GB
341 File file = new File(path);
342 if (!file.canRead()) {
343 return new CustomXmlTraceDefinition[0];
344 }
345 try (FileInputStream fis = new FileInputStream(file);) {
346 return loadAll(fis);
347 } catch (IOException e) {
348 Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
349 }
350 return new CustomXmlTraceDefinition[0];
351 }
352
353 /**
354 * Load all the XML trace definitions from the given stream
355 *
356 * @param stream
357 * An input stream from which to read the definitions
358 * @return The loaded trace definitions
1d8ab692
GB
359 */
360 public static CustomXmlTraceDefinition[] loadAll(InputStream stream) {
be222f56
PT
361 try {
362 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
363 DocumentBuilder db = dbf.newDocumentBuilder();
364
365 // The following allows xml parsing without access to the dtd
cb1cf0e8 366 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
367
368 // The following catches xml parsing exceptions
cb1cf0e8 369 db.setErrorHandler(createErrorHandler());
be222f56 370
1d8ab692 371 Document doc = db.parse(stream);
be222f56 372 Element root = doc.getDocumentElement();
70b7bc9c 373 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
374 return new CustomXmlTraceDefinition[0];
375 }
376
507b1336 377 ArrayList<CustomXmlTraceDefinition> defList = new ArrayList<>();
be222f56
PT
378 NodeList nodeList = root.getChildNodes();
379 for (int i = 0; i < nodeList.getLength(); i++) {
380 Node node = nodeList.item(i);
381 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
382 CustomXmlTraceDefinition def = extractDefinition((Element) node);
383 if (def != null) {
384 defList.add(def);
385 }
386 }
387 }
388 return defList.toArray(new CustomXmlTraceDefinition[0]);
cb1cf0e8 389 } catch (ParserConfigurationException | SAXException | IOException e) {
1d8ab692 390 Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + stream, e); //$NON-NLS-1$
be222f56
PT
391 }
392 return new CustomXmlTraceDefinition[0];
393 }
394
332527a4
PT
395 /**
396 * Load the given trace definition.
397 *
398 * @param categoryName
399 * Category of the definition to load
400 * @param definitionName
401 * Name of the XML trace definition to load
402 * @return The loaded trace definition
332527a4
PT
403 */
404 public static CustomXmlTraceDefinition load(String categoryName, String definitionName) {
be222f56
PT
405 try {
406 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
407 DocumentBuilder db = dbf.newDocumentBuilder();
408
409 // The following allows xml parsing without access to the dtd
a0a88f65 410 EntityResolver resolver = new EntityResolver() {
be222f56 411 @Override
a0a88f65 412 public InputSource resolveEntity(String publicId, String systemId) {
be222f56
PT
413 String empty = ""; //$NON-NLS-1$
414 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
415 return new InputSource(bais);
416 }
417 };
418 db.setEntityResolver(resolver);
419
420 // The following catches xml parsing exceptions
a0a88f65 421 db.setErrorHandler(new ErrorHandler() {
be222f56 422 @Override
70b7bc9c
MK
423 public void error(SAXParseException saxparseexception) throws SAXException {
424 }
a0a88f65 425
be222f56 426 @Override
70b7bc9c
MK
427 public void warning(SAXParseException saxparseexception) throws SAXException {
428 }
a0a88f65 429
be222f56 430 @Override
a0a88f65 431 public void fatalError(SAXParseException saxparseexception) throws SAXException {
be222f56 432 throw saxparseexception;
a0a88f65
AM
433 }
434 });
be222f56 435
332527a4 436 CustomXmlTraceDefinition value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
70b7bc9c 437 if (value == null) {
332527a4 438 value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME);
be222f56 439 }
70b7bc9c 440 return value;
cb1cf0e8 441 } catch (ParserConfigurationException | SAXException | IOException e) {
47aafe74 442 Activator.logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
443 }
444 return null;
445 }
446
332527a4 447 private static CustomXmlTraceDefinition lookupXmlDefinition(String categoryName, String definitionName, DocumentBuilder db, String source) throws SAXException, IOException {
70b7bc9c
MK
448 File file = new File(source);
449 if (!file.exists()) {
450 return null;
451 }
452
453 Document doc = db.parse(file);
454
455 Element root = doc.getDocumentElement();
456 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
457 return null;
458 }
459
332527a4
PT
460 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
461 if (definitionElement != null) {
462 return extractDefinition(definitionElement);
463 }
464 return null;
465 }
466
467 private static Element findDefinitionElement(Element root, String categoryName, String definitionName) {
70b7bc9c
MK
468 NodeList nodeList = root.getChildNodes();
469 for (int i = 0; i < nodeList.getLength(); i++) {
470 Node node = nodeList.item(i);
332527a4
PT
471 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
472 Element element = (Element) node;
473 String categoryAttribute = element.getAttribute(CATEGORY_ATTRIBUTE);
474 if (categoryAttribute.isEmpty()) {
c9b31f60 475 categoryAttribute = CUSTOM_XML_CATEGORY;
332527a4
PT
476 }
477 String nameAttribute = element.getAttribute(NAME_ATTRIBUTE);
478 if (categoryName.equals(categoryAttribute) &&
479 definitionName.equals(nameAttribute)) {
480 return element;
481 }
70b7bc9c
MK
482 }
483 }
484 return null;
485 }
486
a0a88f65
AM
487 /**
488 * Extract a trace definition from an XML element.
489 *
490 * @param definitionElement
491 * Definition element
492 * @return The extracted trace definition
493 */
be222f56
PT
494 public static CustomXmlTraceDefinition extractDefinition(Element definitionElement) {
495 CustomXmlTraceDefinition def = new CustomXmlTraceDefinition();
496
332527a4
PT
497 def.categoryName = definitionElement.getAttribute(CATEGORY_ATTRIBUTE);
498 if (def.categoryName.isEmpty()) {
c9b31f60 499 def.categoryName = CUSTOM_XML_CATEGORY;
332527a4 500 }
be222f56 501 def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
332527a4 502 if (def.definitionName.isEmpty()) {
be222f56
PT
503 return null;
504 }
505
506 NodeList nodeList = definitionElement.getChildNodes();
507 for (int i = 0; i < nodeList.getLength(); i++) {
508 Node node = nodeList.item(i);
509 String nodeName = node.getNodeName();
510 if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {
511 Element formatElement = (Element) node;
512 def.timeStampOutputFormat = formatElement.getTextContent();
513 } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {
a7418109 514 CustomXmlInputElement inputElement = extractInputElement((Element) node);
be222f56
PT
515 if (inputElement != null) {
516 if (def.rootInputElement == null) {
517 def.rootInputElement = inputElement;
518 } else {
519 return null;
520 }
521 }
522 } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {
523 Element outputColumnElement = (Element) node;
524 OutputColumn outputColumn = new OutputColumn();
7a0b1e3c 525 outputColumn.name = checkNotNull(outputColumnElement.getAttribute(NAME_ATTRIBUTE));
be222f56
PT
526 def.outputs.add(outputColumn);
527 }
528 }
529 return def;
530 }
531
a7418109
MK
532 private static CustomXmlInputElement extractInputElement(Element inputElementElement) {
533 CustomXmlInputElement inputElement = new CustomXmlInputElement();
534 inputElement.setElementName(inputElementElement.getAttribute(NAME_ATTRIBUTE));
535 inputElement.setLogEntry((Boolean.toString(true).equals(inputElementElement.getAttribute(LOG_ENTRY_ATTRIBUTE))) ? true : false);
be222f56
PT
536 NodeList nodeList = inputElementElement.getChildNodes();
537 for (int i = 0; i < nodeList.getLength(); i++) {
538 Node node = nodeList.item(i);
539 String nodeName = node.getNodeName();
540 if (nodeName.equals(INPUT_DATA_ELEMENT)) {
541 Element inputDataElement = (Element) node;
a7418109
MK
542 inputElement.setInputName(inputDataElement.getAttribute(NAME_ATTRIBUTE));
543 inputElement.setInputAction(Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE)));
544 inputElement.setInputFormat(inputDataElement.getAttribute(FORMAT_ATTRIBUTE));
be222f56
PT
545 } else if (nodeName.equals(ATTRIBUTE_ELEMENT)) {
546 Element attributeElement = (Element) node;
a7418109
MK
547
548 String attributeName = attributeElement.getAttribute(NAME_ATTRIBUTE);
549 String inputName = null;
550 int inputAction = 0;
551 String inputFormat = null;
be222f56
PT
552 NodeList attributeNodeList = attributeElement.getChildNodes();
553 for (int j = 0; j < attributeNodeList.getLength(); j++) {
554 Node attributeNode = attributeNodeList.item(j);
555 String attributeNodeName = attributeNode.getNodeName();
556 if (attributeNodeName.equals(INPUT_DATA_ELEMENT)) {
557 Element inputDataElement = (Element) attributeNode;
a7418109
MK
558 inputName = inputDataElement.getAttribute(NAME_ATTRIBUTE);
559 inputAction = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));
560 inputFormat = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);
be222f56
PT
561 }
562 }
a7418109 563 inputElement.addAttribute(new CustomXmlInputAttribute(attributeName, inputName, inputAction, inputFormat));
be222f56
PT
564 } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {
565 Element childInputElementElement = (Element) node;
a7418109 566 CustomXmlInputElement childInputElement = extractInputElement(childInputElementElement);
be222f56
PT
567 if (childInputElement != null) {
568 inputElement.addChild(childInputElement);
569 }
570 }
571 }
572 return inputElement;
573 }
574
332527a4
PT
575 /**
576 * Delete a definition from the currently loaded ones.
577 *
578 * @param categoryName
579 * The category of the definition to delete
580 * @param definitionName
581 * The name of the definition to delete
332527a4
PT
582 */
583 public static void delete(String categoryName, String definitionName) {
be222f56
PT
584 try {
585 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
586 DocumentBuilder db = dbf.newDocumentBuilder();
587
588 // The following allows xml parsing without access to the dtd
a0a88f65 589 EntityResolver resolver = new EntityResolver() {
be222f56 590 @Override
a0a88f65 591 public InputSource resolveEntity(String publicId, String systemId) {
be222f56
PT
592 String empty = ""; //$NON-NLS-1$
593 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
594 return new InputSource(bais);
595 }
596 };
597 db.setEntityResolver(resolver);
598
599 // The following catches xml parsing exceptions
a0a88f65 600 db.setErrorHandler(new ErrorHandler() {
be222f56 601 @Override
70b7bc9c
MK
602 public void error(SAXParseException saxparseexception) throws SAXException {
603 }
a0a88f65 604
be222f56 605 @Override
70b7bc9c
MK
606 public void warning(SAXParseException saxparseexception) throws SAXException {
607 }
a0a88f65 608
be222f56 609 @Override
a0a88f65 610 public void fatalError(SAXParseException saxparseexception) throws SAXException {
be222f56 611 throw saxparseexception;
a0a88f65
AM
612 }
613 });
be222f56
PT
614
615 File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
616 Document doc = db.parse(file);
617
618 Element root = doc.getDocumentElement();
70b7bc9c 619 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
620 return;
621 }
622
332527a4
PT
623 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
624 if (definitionElement != null) {
625 root.removeChild(definitionElement);
be222f56
PT
626 }
627
628 Transformer transformer = TransformerFactory.newInstance().newTransformer();
629 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
630
70b7bc9c 631 // initialize StreamResult with File object to save to file
be222f56
PT
632 StreamResult result = new StreamResult(new StringWriter());
633 DOMSource source = new DOMSource(doc);
634 transformer.transform(source, result);
635 String xmlString = result.getWriter().toString();
636
507b1336
AM
637 try (FileWriter writer = new FileWriter(file);) {
638 writer.write(xmlString);
639 }
52885aeb 640
4b3b667b 641 TmfTraceType.removeCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
0621dbae 642 // Check if default definition needs to be reloaded
4b3b667b 643 TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
52885aeb 644
cb1cf0e8 645 } catch (ParserConfigurationException | SAXException | IOException | TransformerFactoryConfigurationError | TransformerException e) {
47aafe74 646 Activator.logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
647 }
648 }
649}
This page took 0.136324 seconds and 5 git commands to generate.