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