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