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