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
be222f56 1/*******************************************************************************
70b7bc9c 2 * Copyright (c) 2010, 2014 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
47aafe74 14package org.eclipse.linuxtools.tmf.core.parsers.custom;
be222f56
PT
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;
70b7bc9c
MK
22import java.util.Arrays;
23import java.util.Comparator;
be222f56 24import java.util.List;
70b7bc9c
MK
25import java.util.Set;
26import java.util.TreeSet;
be222f56
PT
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;
be222f56
PT
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
70b7bc9c 39import org.eclipse.core.runtime.Platform;
47aafe74
AM
40import org.eclipse.linuxtools.internal.tmf.core.Activator;
41import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
be222f56
PT
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
a0a88f65
AM
52/**
53 * Trace definition for custom XML traces.
54 *
55 * @author Patrick Tassé
47aafe74 56 * @since 3.0
a0a88f65 57 */
be222f56
PT
58public class CustomXmlTraceDefinition extends CustomTraceDefinition {
59
a0a88f65
AM
60 /** "ignore" tag */
61 public static final String TAG_IGNORE = Messages.CustomXmlTraceDefinition_ignoreTag;
62
70b7bc9c
MK
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
a0a88f65 66 /** Name of the XML definitions file */
be222f56 67 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME = "custom_xml_parsers.xml"; //$NON-NLS-1$
a0a88f65 68
70b7bc9c
MK
69 /** Path to the XML definitions file */
70 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME =
cb1cf0e8
MK
71 Platform.getInstallLocation().getURL().getPath() + "templates/org.eclipse.linuxtools.tmf.core/" + //$NON-NLS-1$
72 CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME;
70b7bc9c 73
a0a88f65 74 /** Path to the XML definitions file */
be222f56 75 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME =
70b7bc9c 76 Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();
be222f56 77
cb1cf0e8
MK
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 */
03573754
AM
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
332527a4 87 // TODO: These strings should not be externalized
be222f56
PT
88 private static final String CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomXmlTraceDefinition_definitionRootElement;
89 private static final String DEFINITION_ELEMENT = Messages.CustomXmlTraceDefinition_definition;
332527a4 90 private static final String CATEGORY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_category;
be222f56
PT
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
a0a88f65 101 /** Top-level input element */
be222f56
PT
102 public InputElement rootInputElement;
103
a0a88f65
AM
104 /**
105 * Default constructor
106 */
be222f56 107 public CustomXmlTraceDefinition() {
332527a4 108 this(TmfTraceType.CUSTOM_XML_CATEGORY, "", null, new ArrayList<OutputColumn>(), ""); //$NON-NLS-1$ //$NON-NLS-2$
be222f56
PT
109 }
110
a0a88f65
AM
111 /**
112 * Full constructor
113 *
332527a4
PT
114 * @param traceType
115 * Name of the trace type
a0a88f65
AM
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
332527a4 122 * @deprecated Use {@link #CustomXmlTraceDefinition(String, String, InputElement, List, String)}
a0a88f65 123 */
332527a4
PT
124 @Deprecated
125 public CustomXmlTraceDefinition(String traceType, InputElement rootElement,
a0a88f65 126 List<OutputColumn> outputs, String timeStampOutputFormat) {
332527a4
PT
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;
be222f56
PT
152 this.rootInputElement = rootElement;
153 this.outputs = outputs;
154 this.timeStampOutputFormat = timeStampOutputFormat;
155 }
156
a0a88f65
AM
157 /**
158 * Wrapper for input XML elements
159 */
be222f56 160 public static class InputElement {
a0a88f65
AM
161
162 /** Name of the element */
be222f56 163 public String elementName;
a0a88f65
AM
164
165 /** Indicates if this is a log entry */
be222f56 166 public boolean logEntry;
a0a88f65
AM
167
168 /** Name of the input element */
be222f56 169 public String inputName;
a0a88f65
AM
170
171 /** Input action */
be222f56 172 public int inputAction;
a0a88f65
AM
173
174 /** Input format */
be222f56 175 public String inputFormat;
a0a88f65
AM
176
177 /** XML attributes of this element */
be222f56 178 public List<InputAttribute> attributes;
a0a88f65
AM
179
180 /** Parent element */
be222f56 181 public InputElement parentElement;
a0a88f65
AM
182
183 /** Following element in the file */
be222f56 184 public InputElement nextElement;
a0a88f65
AM
185
186 /** Child elements */
be222f56
PT
187 public List<InputElement> childElements;
188
a0a88f65
AM
189 /**
190 * Default (empty) constructor
191 */
70b7bc9c
MK
192 public InputElement() {
193 }
be222f56 194
a0a88f65
AM
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) {
be222f56
PT
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
a0a88f65
AM
222 /**
223 * Add a XML attribute to the element
224 *
225 * @param attribute
226 * The attribute to add
227 */
be222f56
PT
228 public void addAttribute(InputAttribute attribute) {
229 if (attributes == null) {
507b1336 230 attributes = new ArrayList<>(1);
be222f56
PT
231 }
232 attributes.add(attribute);
233 }
234
a0a88f65
AM
235 /**
236 * Add a child element to this one.
237 *
238 * @param input
239 * The input element to add as child
240 */
be222f56
PT
241 public void addChild(InputElement input) {
242 if (childElements == null) {
507b1336 243 childElements = new ArrayList<>(1);
be222f56
PT
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
a0a88f65
AM
252 /**
253 * Set the following input element.
254 *
255 * @param input
256 * The input element to add as next element
257 */
be222f56
PT
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
a0a88f65
AM
269 /**
270 * Move this element up in its parent's list of children.
271 */
be222f56
PT
272 public void moveUp() {
273 if (parentElement != null) {
274 int index = parentElement.childElements.indexOf(this);
275 if (index > 0) {
70b7bc9c 276 parentElement.childElements.add(index - 1, parentElement.childElements.remove(index));
be222f56
PT
277 parentElement.childElements.get(index).nextElement = nextElement;
278 nextElement = parentElement.childElements.get(index);
279 }
280 }
281 }
282
a0a88f65
AM
283 /**
284 * Move this element down in its parent's list of children.
285 */
be222f56
PT
286 public void moveDown() {
287 if (parentElement != null) {
288 int index = parentElement.childElements.indexOf(this);
289 if (index < parentElement.childElements.size() - 1) {
70b7bc9c 290 parentElement.childElements.add(index + 1, parentElement.childElements.remove(index));
be222f56
PT
291 nextElement = parentElement.childElements.get(index).nextElement;
292 parentElement.childElements.get(index).nextElement = this;
293 }
294 }
295 }
296
297 }
298
a0a88f65
AM
299 /**
300 * Wrapper for XML element attributes
301 */
be222f56 302 public static class InputAttribute {
a0a88f65
AM
303
304 /** Name of the XML attribute */
be222f56 305 public String attributeName;
a0a88f65
AM
306
307 /** Input name */
be222f56 308 public String inputName;
a0a88f65
AM
309
310 /** Input action */
be222f56 311 public int inputAction;
a0a88f65
AM
312
313 /** Input format */
be222f56
PT
314 public String inputFormat;
315
a0a88f65
AM
316 /**
317 * Default (empty) constructor
318 */
70b7bc9c
MK
319 public InputAttribute() {
320 }
be222f56 321
a0a88f65
AM
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) {
be222f56
PT
336 this.attributeName = attributeName;
337 this.inputName = inputName;
338 this.inputAction = inputAction;
339 this.inputFormat = inputFormat;
340 }
341 }
342
a0a88f65 343 @Override
be222f56
PT
344 public void save() {
345 save(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
346 }
347
70b7bc9c 348 @Override
be222f56
PT
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
cb1cf0e8 355 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
356
357 // The following catches xml parsing exceptions
cb1cf0e8 358 db.setErrorHandler(createErrorHandler());
be222f56
PT
359
360 Document doc = null;
361 File file = new File(path);
362 if (file.canRead()) {
363 doc = db.parse(file);
70b7bc9c 364 if (!doc.getDocumentElement().getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
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
332527a4
PT
375 Element oldDefinitionElement = findDefinitionElement(root, categoryName, definitionName);
376 if (oldDefinitionElement != null) {
377 root.removeChild(oldDefinitionElement);
be222f56
PT
378 }
379 Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
380 root.appendChild(definitionElement);
332527a4 381 definitionElement.setAttribute(CATEGORY_ATTRIBUTE, categoryName);
be222f56
PT
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
70b7bc9c 403 // initialize StreamResult with File object to save to file
be222f56
PT
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
507b1336
AM
409 try (FileWriter writer = new FileWriter(file);) {
410 writer.write(xmlString);
411 }
52885aeb 412
4b3b667b 413 TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
52885aeb 414
cb1cf0e8 415 } catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException | IOException | SAXException e) {
47aafe74 416 Activator.logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56
PT
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
a0a88f65
AM
462 /**
463 * Load all the XML trace definitions in the default definitions file.
464 *
465 * @return The loaded trace definitions
466 */
be222f56 467 public static CustomXmlTraceDefinition[] loadAll() {
03573754
AM
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
70b7bc9c 483 Set<CustomXmlTraceDefinition> defs = new TreeSet<>(new Comparator<CustomXmlTraceDefinition>() {
70b7bc9c
MK
484 @Override
485 public int compare(CustomXmlTraceDefinition o1, CustomXmlTraceDefinition o2) {
c22ca172
PT
486 int result = o1.categoryName.compareTo(o2.categoryName);
487 if (result != 0) {
488 return result;
489 }
70b7bc9c
MK
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]);
be222f56
PT
496 }
497
a0a88f65
AM
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 */
be222f56
PT
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
cb1cf0e8 511 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
512
513 // The following catches xml parsing exceptions
cb1cf0e8 514 db.setErrorHandler(createErrorHandler());
be222f56
PT
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();
70b7bc9c 523 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
524 return new CustomXmlTraceDefinition[0];
525 }
526
507b1336 527 ArrayList<CustomXmlTraceDefinition> defList = new ArrayList<>();
be222f56
PT
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]);
cb1cf0e8 539 } catch (ParserConfigurationException | SAXException | IOException e) {
47aafe74 540 Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56
PT
541 }
542 return new CustomXmlTraceDefinition[0];
543 }
544
a0a88f65
AM
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
332527a4 551 * @deprecated Use {@link #load(String, String)}
a0a88f65 552 */
332527a4 553 @Deprecated
be222f56 554 public static CustomXmlTraceDefinition load(String definitionName) {
332527a4
PT
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) {
be222f56
PT
569 try {
570 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
571 DocumentBuilder db = dbf.newDocumentBuilder();
572
573 // The following allows xml parsing without access to the dtd
a0a88f65 574 EntityResolver resolver = new EntityResolver() {
be222f56 575 @Override
a0a88f65 576 public InputSource resolveEntity(String publicId, String systemId) {
be222f56
PT
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
a0a88f65 585 db.setErrorHandler(new ErrorHandler() {
be222f56 586 @Override
70b7bc9c
MK
587 public void error(SAXParseException saxparseexception) throws SAXException {
588 }
a0a88f65 589
be222f56 590 @Override
70b7bc9c
MK
591 public void warning(SAXParseException saxparseexception) throws SAXException {
592 }
a0a88f65 593
be222f56 594 @Override
a0a88f65 595 public void fatalError(SAXParseException saxparseexception) throws SAXException {
be222f56 596 throw saxparseexception;
a0a88f65
AM
597 }
598 });
be222f56 599
332527a4 600 CustomXmlTraceDefinition value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
70b7bc9c 601 if (value == null) {
332527a4 602 value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME);
be222f56 603 }
70b7bc9c 604 return value;
cb1cf0e8 605 } catch (ParserConfigurationException | SAXException | IOException e) {
47aafe74 606 Activator.logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
607 }
608 return null;
609 }
610
332527a4 611 private static CustomXmlTraceDefinition lookupXmlDefinition(String categoryName, String definitionName, DocumentBuilder db, String source) throws SAXException, IOException {
70b7bc9c
MK
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
332527a4
PT
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) {
70b7bc9c
MK
632 NodeList nodeList = root.getChildNodes();
633 for (int i = 0; i < nodeList.getLength(); i++) {
634 Node node = nodeList.item(i);
332527a4
PT
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 }
70b7bc9c
MK
646 }
647 }
648 return null;
649 }
650
a0a88f65
AM
651 /**
652 * Extract a trace definition from an XML element.
653 *
654 * @param definitionElement
655 * Definition element
656 * @return The extracted trace definition
657 */
be222f56
PT
658 public static CustomXmlTraceDefinition extractDefinition(Element definitionElement) {
659 CustomXmlTraceDefinition def = new CustomXmlTraceDefinition();
660
332527a4
PT
661 def.categoryName = definitionElement.getAttribute(CATEGORY_ATTRIBUTE);
662 if (def.categoryName.isEmpty()) {
663 def.categoryName = TmfTraceType.CUSTOM_XML_CATEGORY;
664 }
be222f56 665 def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
332527a4 666 if (def.definitionName.isEmpty()) {
be222f56
PT
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
a0a88f65 736 /**
332527a4 737 * Delete a definition from the currently loaded ones.
a0a88f65
AM
738 *
739 * @param definitionName
332527a4
PT
740 * The name of the definition to delete
741 * @deprecated Use {@link #delete(String, String)}
a0a88f65 742 */
332527a4 743 @Deprecated
be222f56 744 public static void delete(String definitionName) {
332527a4
PT
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) {
be222f56
PT
758 try {
759 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
760 DocumentBuilder db = dbf.newDocumentBuilder();
761
762 // The following allows xml parsing without access to the dtd
a0a88f65 763 EntityResolver resolver = new EntityResolver() {
be222f56 764 @Override
a0a88f65 765 public InputSource resolveEntity(String publicId, String systemId) {
be222f56
PT
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
a0a88f65 774 db.setErrorHandler(new ErrorHandler() {
be222f56 775 @Override
70b7bc9c
MK
776 public void error(SAXParseException saxparseexception) throws SAXException {
777 }
a0a88f65 778
be222f56 779 @Override
70b7bc9c
MK
780 public void warning(SAXParseException saxparseexception) throws SAXException {
781 }
a0a88f65 782
be222f56 783 @Override
a0a88f65 784 public void fatalError(SAXParseException saxparseexception) throws SAXException {
be222f56 785 throw saxparseexception;
a0a88f65
AM
786 }
787 });
be222f56
PT
788
789 File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
790 Document doc = db.parse(file);
791
792 Element root = doc.getDocumentElement();
70b7bc9c 793 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
794 return;
795 }
796
332527a4
PT
797 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
798 if (definitionElement != null) {
799 root.removeChild(definitionElement);
be222f56
PT
800 }
801
802 Transformer transformer = TransformerFactory.newInstance().newTransformer();
803 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
804
70b7bc9c 805 // initialize StreamResult with File object to save to file
be222f56
PT
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
507b1336
AM
811 try (FileWriter writer = new FileWriter(file);) {
812 writer.write(xmlString);
813 }
52885aeb 814
4b3b667b 815 TmfTraceType.removeCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
0621dbae 816 // Check if default definition needs to be reloaded
4b3b667b 817 TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
52885aeb 818
cb1cf0e8 819 } catch (ParserConfigurationException | SAXException | IOException | TransformerFactoryConfigurationError | TransformerException e) {
47aafe74 820 Activator.logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
821 }
822 }
823}
This page took 0.097059 seconds and 5 git commands to generate.