1 /*******************************************************************************
2 * Copyright (c) 2010, 2014 Ericsson
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
10 * Patrick Tasse - Initial API and implementation
11 * Matthew Khouzam - Add support for default parsers
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.core
.parsers
.custom
;
17 import java
.io
.FileWriter
;
18 import java
.io
.IOException
;
19 import java
.io
.StringWriter
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Arrays
;
22 import java
.util
.Comparator
;
23 import java
.util
.List
;
26 import java
.util
.TreeSet
;
27 import java
.util
.regex
.Pattern
;
28 import java
.util
.regex
.PatternSyntaxException
;
30 import javax
.xml
.parsers
.DocumentBuilder
;
31 import javax
.xml
.parsers
.DocumentBuilderFactory
;
32 import javax
.xml
.parsers
.ParserConfigurationException
;
33 import javax
.xml
.transform
.OutputKeys
;
34 import javax
.xml
.transform
.Transformer
;
35 import javax
.xml
.transform
.TransformerConfigurationException
;
36 import javax
.xml
.transform
.TransformerException
;
37 import javax
.xml
.transform
.TransformerFactory
;
38 import javax
.xml
.transform
.TransformerFactoryConfigurationError
;
39 import javax
.xml
.transform
.dom
.DOMSource
;
40 import javax
.xml
.transform
.stream
.StreamResult
;
42 import org
.eclipse
.core
.runtime
.Platform
;
43 import org
.eclipse
.linuxtools
.internal
.tmf
.core
.Activator
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.project
.model
.TmfTraceType
;
45 import org
.w3c
.dom
.Document
;
46 import org
.w3c
.dom
.Element
;
47 import org
.w3c
.dom
.Node
;
48 import org
.w3c
.dom
.NodeList
;
49 import org
.xml
.sax
.SAXException
;
52 * Trace definition for custom text traces.
54 * @author Patrick Tassé
57 public class CustomTxtTraceDefinition
extends CustomTraceDefinition
{
60 public List
<InputLine
> inputs
;
62 /** File name of the default definition file */
63 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_FILE_NAME
= "custom_txt_default_parsers.xml"; //$NON-NLS-1$
64 /** File name of the definition file */
65 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME
= "custom_txt_parsers.xml"; //$NON-NLS-1$
67 /** Path of the definition file */
68 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME
=
69 Platform
.getInstallLocation().getURL().getPath() + "templates/org.eclipse.linuxtools.tmf.core/" + //$NON-NLS-1$
70 CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_FILE_NAME
;
71 /** Path of the definition file */
72 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME
=
73 Activator
.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME
).toString();
76 * Legacy path to the XML definitions file (in the UI plug-in) TODO Remove
77 * once we feel the transition phase is over.
79 private static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY
=
80 Activator
.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
81 .append("org.eclipse.linuxtools.tmf.ui") //$NON-NLS-1$
82 .append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME
).toString();
84 private static final String CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT
= Messages
.CustomTxtTraceDefinition_definitionRootElement
;
85 private static final String DEFINITION_ELEMENT
= Messages
.CustomTxtTraceDefinition_definition
;
86 private static final String CATEGORY_ATTRIBUTE
= Messages
.CustomTxtTraceDefinition_category
;
87 private static final String NAME_ATTRIBUTE
= Messages
.CustomTxtTraceDefinition_name
;
88 private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT
= Messages
.CustomTxtTraceDefinition_timestampOutputFormat
;
89 private static final String INPUT_LINE_ELEMENT
= Messages
.CustomTxtTraceDefinition_inputLine
;
90 private static final String CARDINALITY_ELEMENT
= Messages
.CustomTxtTraceDefinition_cardinality
;
91 private static final String MIN_ATTRIBUTE
= Messages
.CustomTxtTraceDefinition_min
;
92 private static final String MAX_ATTRIBUTE
= Messages
.CustomTxtTraceDefinition_max
;
93 private static final String REGEX_ELEMENT
= Messages
.CustomTxtTraceDefinition_regEx
;
94 private static final String INPUT_DATA_ELEMENT
= Messages
.CustomTxtTraceDefinition_inputData
;
95 private static final String ACTION_ATTRIBUTE
= Messages
.CustomTxtTraceDefinition_action
;
96 private static final String FORMAT_ATTRIBUTE
= Messages
.CustomTxtTraceDefinition_format
;
97 private static final String OUTPUT_COLUMN_ELEMENT
= Messages
.CustomTxtTraceDefinition_outputColumn
;
100 * Default constructor.
102 public CustomTxtTraceDefinition() {
103 this(TmfTraceType
.CUSTOM_TXT_CATEGORY
, "", new ArrayList
<InputLine
>(0), new ArrayList
<OutputColumn
>(0), ""); //$NON-NLS-1$ //$NON-NLS-2$
110 * Name of the trace type
114 * List of output columns
115 * @param timeStampOutputFormat
116 * The timestamp format to use
117 * @deprecated Use {@link #CustomTxtTraceDefinition(String, String, List, List, String)}
120 public CustomTxtTraceDefinition(String traceType
, List
<InputLine
> inputs
,
121 List
<OutputColumn
> outputs
, String timeStampOutputFormat
) {
122 this.definitionName
= traceType
;
123 this.inputs
= inputs
;
124 this.outputs
= outputs
;
125 this.timeStampOutputFormat
= timeStampOutputFormat
;
132 * Category of the trace type
134 * Name of the trace type
138 * List of output columns
139 * @param timeStampOutputFormat
140 * The timestamp format to use
143 public CustomTxtTraceDefinition(String category
, String traceType
, List
<InputLine
> inputs
,
144 List
<OutputColumn
> outputs
, String timeStampOutputFormat
) {
145 this.categoryName
= category
;
146 this.definitionName
= traceType
;
147 this.inputs
= inputs
;
148 this.outputs
= outputs
;
149 this.timeStampOutputFormat
= timeStampOutputFormat
;
153 * Wrapper to store a line of the log file
155 public static class InputLine
{
157 /** Data columns of this line */
158 public List
<InputData
> columns
;
160 /** Cardinality of this line (see {@link Cardinality}) */
161 public Cardinality cardinality
;
164 public InputLine parentInput
;
166 /** Level of this line */
169 /** Next input line in the file */
170 public InputLine nextInput
;
172 /** Children of this line (if one "event" spans many lines) */
173 public List
<InputLine
> childrenInputs
;
175 private String regex
;
176 private Pattern pattern
;
179 * Default (empty) constructor.
188 * Cardinality of this line.
194 public InputLine(Cardinality cardinality
, String regex
, List
<InputData
> columns
) {
195 this.cardinality
= cardinality
;
197 this.columns
= columns
;
201 * Set the regex of this input line
206 public void setRegex(String regex
) {
212 * Get the current regex
214 * @return The current regex
216 public String
getRegex() {
221 * Get the Pattern object of this line's regex
223 * @return The Pattern
224 * @throws PatternSyntaxException
225 * If the regex does not parse correctly
227 public Pattern
getPattern() throws PatternSyntaxException
{
228 if (pattern
== null) {
229 pattern
= Pattern
.compile(regex
);
235 * Add a child line to this line.
238 * The child input line
240 public void addChild(InputLine input
) {
241 if (childrenInputs
== null) {
242 childrenInputs
= new ArrayList
<>(1);
243 } else if (childrenInputs
.size() > 0) {
244 InputLine last
= childrenInputs
.get(childrenInputs
.size() - 1);
245 last
.nextInput
= input
;
247 childrenInputs
.add(input
);
248 input
.parentInput
= this;
249 input
.level
= this.level
+ 1;
253 * Set the next input line.
256 * The next input line
258 public void addNext(InputLine input
) {
259 if (parentInput
!= null) {
260 int index
= parentInput
.childrenInputs
.indexOf(this);
261 parentInput
.childrenInputs
.add(index
+ 1, input
);
262 InputLine next
= nextInput
;
264 input
.nextInput
= next
;
266 input
.parentInput
= this.parentInput
;
267 input
.level
= this.level
;
271 * Move this line up in its parent's children.
273 public void moveUp() {
274 if (parentInput
!= null) {
275 int index
= parentInput
.childrenInputs
.indexOf(this);
277 parentInput
.childrenInputs
.add(index
- 1, parentInput
.childrenInputs
.remove(index
));
278 parentInput
.childrenInputs
.get(index
).nextInput
= nextInput
;
279 nextInput
= parentInput
.childrenInputs
.get(index
);
285 * Move this line down in its parent's children.
287 public void moveDown() {
288 if (parentInput
!= null) {
289 int index
= parentInput
.childrenInputs
.indexOf(this);
290 if (index
< parentInput
.childrenInputs
.size() - 1) {
291 parentInput
.childrenInputs
.add(index
+ 1, parentInput
.childrenInputs
.remove(index
));
292 nextInput
= parentInput
.childrenInputs
.get(index
).nextInput
;
293 parentInput
.childrenInputs
.get(index
).nextInput
= this;
299 * Add a data column to this line
304 public void addColumn(InputData column
) {
305 if (columns
== null) {
306 columns
= new ArrayList
<>(1);
312 * Get the next input lines.
315 * The map of line "sets".
316 * @return The next list of lines.
318 public List
<InputLine
> getNextInputs(Map
<InputLine
, Integer
> countMap
) {
319 List
<InputLine
> nextInputs
= new ArrayList
<>();
320 InputLine next
= nextInput
;
321 while (next
!= null) {
322 nextInputs
.add(next
);
323 if (next
.cardinality
.min
> 0) {
326 next
= next
.nextInput
;
328 if (parentInput
!= null && parentInput
.level
> 0) {
329 int parentCount
= countMap
.get(parentInput
);
330 if (parentCount
< parentInput
.getMaxCount()) {
331 nextInputs
.add(parentInput
);
333 if (parentCount
< parentInput
.getMinCount()) {
336 nextInputs
.addAll(parentInput
.getNextInputs(countMap
));
342 * Get the minimum possible amount of entries.
344 * @return The minimum
346 public int getMinCount() {
347 return cardinality
.min
;
351 * Get the maximum possible amount of entries.
353 * @return The maximum
355 public int getMaxCount() {
356 return cardinality
.max
;
360 public String
toString() {
361 return regex
+ " " + cardinality
; //$NON-NLS-1$
366 * Data column for input lines.
368 public static class InputData
{
370 /** Name of this column */
377 public String format
;
380 * Default (empty) constructor
395 public InputData(String name
, int action
, String format
) {
397 this.action
= action
;
398 this.format
= format
;
402 * Constructor with default format
409 public InputData(String name
, int action
) {
411 this.action
= action
;
416 * Input line cardinality
418 public static class Cardinality
{
420 /** Representation of infinity */
421 public final static int INF
= Integer
.MAX_VALUE
;
423 /** Preset for [1, 1] */
424 public final static Cardinality ONE
= new Cardinality(1, 1);
426 /** Preset for [1, inf] */
427 public final static Cardinality ONE_OR_MORE
= new Cardinality(1, INF
);
429 /** Preset for [0, 1] */
430 public final static Cardinality ZERO_OR_ONE
= new Cardinality(0, 1);
432 /** Preset for [0, inf] */
433 public final static Cardinality ZERO_OR_MORE
= new Cardinality(0, INF
);
435 private final int min
;
436 private final int max
;
446 public Cardinality(int min
, int max
) {
452 public String
toString() {
453 return "(" + (min
>= 0 ? min
: "?") + ',' + (max
== INF ?
"\u221E" : (max
>= 0 ? max
: "?")) + ')'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
457 public int hashCode() {
458 final int prime
= 31;
460 result
= prime
* result
+ max
;
461 result
= prime
* result
+ min
;
466 public boolean equals(Object obj
) {
473 if (!(obj
instanceof Cardinality
)) {
476 Cardinality other
= (Cardinality
) obj
;
477 return (this.min
== other
.min
&& this.max
== other
.max
);
483 save(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME
);
487 public void save(String path
) {
489 DocumentBuilderFactory dbf
= DocumentBuilderFactory
.newInstance();
490 DocumentBuilder db
= dbf
.newDocumentBuilder();
492 // The following allows xml parsing without access to the dtd
493 db
.setEntityResolver(createEmptyEntityResolver());
495 // The following catches xml parsing exceptions
496 db
.setErrorHandler(createErrorHandler());
499 File file
= new File(path
);
500 if (file
.canRead()) {
501 doc
= db
.parse(file
);
502 if (!doc
.getDocumentElement().getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT
)) {
506 doc
= db
.newDocument();
507 Node node
= doc
.createElement(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT
);
508 doc
.appendChild(node
);
511 Element root
= doc
.getDocumentElement();
513 Element oldDefinitionElement
= findDefinitionElement(root
, categoryName
, definitionName
);
514 if (oldDefinitionElement
!= null) {
515 root
.removeChild(oldDefinitionElement
);
517 Element definitionElement
= doc
.createElement(DEFINITION_ELEMENT
);
518 root
.appendChild(definitionElement
);
519 definitionElement
.setAttribute(CATEGORY_ATTRIBUTE
, categoryName
);
520 definitionElement
.setAttribute(NAME_ATTRIBUTE
, definitionName
);
522 Element formatElement
= doc
.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT
);
523 definitionElement
.appendChild(formatElement
);
524 formatElement
.appendChild(doc
.createTextNode(timeStampOutputFormat
));
526 if (inputs
!= null) {
527 for (InputLine inputLine
: inputs
) {
528 definitionElement
.appendChild(createInputLineElement(inputLine
, doc
));
532 if (outputs
!= null) {
533 for (OutputColumn output
: outputs
) {
534 Element outputColumnElement
= doc
.createElement(OUTPUT_COLUMN_ELEMENT
);
535 definitionElement
.appendChild(outputColumnElement
);
536 outputColumnElement
.setAttribute(NAME_ATTRIBUTE
, output
.name
);
540 Transformer transformer
= TransformerFactory
.newInstance().newTransformer();
541 transformer
.setOutputProperty(OutputKeys
.INDENT
, "yes"); //$NON-NLS-1$
543 // initialize StreamResult with File object to save to file
544 StreamResult result
= new StreamResult(new StringWriter());
545 DOMSource source
= new DOMSource(doc
);
546 transformer
.transform(source
, result
);
547 String xmlString
= result
.getWriter().toString();
549 try (FileWriter writer
= new FileWriter(file
);) {
550 writer
.write(xmlString
);
553 TmfTraceType
.addCustomTraceType(CustomTxtTrace
.class, categoryName
, definitionName
);
555 } catch (ParserConfigurationException e
) {
556 Activator
.logError("Error saving CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
557 } catch (TransformerConfigurationException e
) {
558 Activator
.logError("Error saving CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
559 } catch (TransformerFactoryConfigurationError e
) {
560 Activator
.logError("Error saving CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
561 } catch (TransformerException e
) {
562 Activator
.logError("Error saving CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
563 } catch (IOException e
) {
564 Activator
.logError("Error saving CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
565 } catch (SAXException e
) {
566 Activator
.logError("Error saving CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
570 private Element
createInputLineElement(InputLine inputLine
, Document doc
) {
571 Element inputLineElement
= doc
.createElement(INPUT_LINE_ELEMENT
);
573 Element cardinalityElement
= doc
.createElement(CARDINALITY_ELEMENT
);
574 inputLineElement
.appendChild(cardinalityElement
);
575 cardinalityElement
.setAttribute(MIN_ATTRIBUTE
, Integer
.toString(inputLine
.cardinality
.min
));
576 cardinalityElement
.setAttribute(MAX_ATTRIBUTE
, Integer
.toString(inputLine
.cardinality
.max
));
578 Element regexElement
= doc
.createElement(REGEX_ELEMENT
);
579 inputLineElement
.appendChild(regexElement
);
580 regexElement
.appendChild(doc
.createTextNode(inputLine
.regex
));
582 if (inputLine
.columns
!= null) {
583 for (InputData inputData
: inputLine
.columns
) {
584 Element inputDataElement
= doc
.createElement(INPUT_DATA_ELEMENT
);
585 inputLineElement
.appendChild(inputDataElement
);
586 inputDataElement
.setAttribute(NAME_ATTRIBUTE
, inputData
.name
);
587 inputDataElement
.setAttribute(ACTION_ATTRIBUTE
, Integer
.toString(inputData
.action
));
588 if (inputData
.format
!= null) {
589 inputDataElement
.setAttribute(FORMAT_ATTRIBUTE
, inputData
.format
);
594 if (inputLine
.childrenInputs
!= null) {
595 for (InputLine childInputLine
: inputLine
.childrenInputs
) {
596 inputLineElement
.appendChild(createInputLineElement(childInputLine
, doc
));
600 return inputLineElement
;
604 * Load the default text trace definitions file.
606 * @return The loaded trace definitions
608 public static CustomTxtTraceDefinition
[] loadAll() {
609 File defaultFile
= new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME
);
610 File legacyFile
= new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY
);
613 * If there is no file at the expected location, check the legacy
616 if (!defaultFile
.exists() && legacyFile
.exists()) {
617 CustomTxtTraceDefinition
[] oldDefs
= loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY
);
618 for (CustomTxtTraceDefinition def
: oldDefs
) {
619 /* Save in the new location */
624 Set
<CustomTxtTraceDefinition
> defs
= new TreeSet
<>(new Comparator
<CustomTxtTraceDefinition
>() {
626 public int compare(CustomTxtTraceDefinition o1
, CustomTxtTraceDefinition o2
) {
627 int result
= o1
.categoryName
.compareTo(o2
.categoryName
);
631 return o1
.definitionName
.compareTo(o2
.definitionName
);
634 defs
.addAll(Arrays
.asList(loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME
)));
635 defs
.addAll(Arrays
.asList(loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME
)));
636 return defs
.toArray(new CustomTxtTraceDefinition
[0]);
641 * Load a specific text trace definition file.
644 * The path to the file to load
645 * @return The loaded trace definitions
647 public static CustomTxtTraceDefinition
[] loadAll(String path
) {
649 DocumentBuilderFactory dbf
= DocumentBuilderFactory
.newInstance();
650 DocumentBuilder db
= dbf
.newDocumentBuilder();
652 // The following allows xml parsing without access to the dtd
653 db
.setEntityResolver(createEmptyEntityResolver());
655 // The following catches xml parsing exceptions
656 db
.setErrorHandler(createErrorHandler());
658 File file
= new File(path
);
659 if (!file
.canRead()) {
660 return new CustomTxtTraceDefinition
[0];
662 Document doc
= db
.parse(file
);
664 Element root
= doc
.getDocumentElement();
665 if (!root
.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT
)) {
666 return new CustomTxtTraceDefinition
[0];
669 ArrayList
<CustomTxtTraceDefinition
> defList
= new ArrayList
<>();
670 NodeList nodeList
= root
.getChildNodes();
671 for (int i
= 0; i
< nodeList
.getLength(); i
++) {
672 Node node
= nodeList
.item(i
);
673 if (node
instanceof Element
&& node
.getNodeName().equals(DEFINITION_ELEMENT
)) {
674 CustomTxtTraceDefinition def
= extractDefinition((Element
) node
);
680 return defList
.toArray(new CustomTxtTraceDefinition
[0]);
681 } catch (ParserConfigurationException e
) {
682 Activator
.logError("Error loading all in CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
683 } catch (SAXException e
) {
684 Activator
.logError("Error loading all in CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
685 } catch (IOException e
) {
686 Activator
.logError("Error loading all in CustomTxtTraceDefinition: path=" + path
, e
); //$NON-NLS-1$
688 return new CustomTxtTraceDefinition
[0];
692 * Load a single definition.
694 * @param definitionName
695 * Name of the definition to load
696 * @return The loaded trace definition
697 * @deprecated Use {@link #load(String, String)}
700 public static CustomTxtTraceDefinition
load(String definitionName
) {
701 return load(TmfTraceType
.CUSTOM_TXT_CATEGORY
, definitionName
);
705 * Load a single definition.
707 * @param categoryName
708 * Category of the definition to load
709 * @param definitionName
710 * Name of the definition to load
711 * @return The loaded trace definition
714 public static CustomTxtTraceDefinition
load(String categoryName
, String definitionName
) {
716 DocumentBuilderFactory dbf
= DocumentBuilderFactory
.newInstance();
717 DocumentBuilder db
= dbf
.newDocumentBuilder();
719 // The following allows xml parsing without access to the dtd
720 db
.setEntityResolver(createEmptyEntityResolver());
722 // The following catches xml parsing exceptions
723 db
.setErrorHandler(createErrorHandler());
725 CustomTxtTraceDefinition value
= lookupDefinition(categoryName
, definitionName
, db
, CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME
);
727 return lookupDefinition(categoryName
, definitionName
, db
, CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME
);
730 } catch (ParserConfigurationException
| SAXException
| IOException e
) {
731 Activator
.logError("Error loading CustomTxtTraceDefinition: definitionName=" + definitionName
, e
); //$NON-NLS-1$
736 private static CustomTxtTraceDefinition
lookupDefinition(String categoryName
, String definitionName
, DocumentBuilder db
, String source
) throws SAXException
, IOException
{
737 File file
= new File(source
);
738 if (!file
.exists()) {
741 Document doc
= db
.parse(file
);
743 Element root
= doc
.getDocumentElement();
744 if (!root
.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT
)) {
748 Element definitionElement
= findDefinitionElement(root
, categoryName
, definitionName
);
749 if (definitionElement
!= null) {
750 return extractDefinition(definitionElement
);
755 private static Element
findDefinitionElement(Element root
, String categoryName
, String definitionName
) {
756 NodeList nodeList
= root
.getChildNodes();
757 for (int i
= 0; i
< nodeList
.getLength(); i
++) {
758 Node node
= nodeList
.item(i
);
759 if (node
instanceof Element
&& node
.getNodeName().equals(DEFINITION_ELEMENT
)) {
760 Element element
= (Element
) node
;
761 String categoryAttribute
= element
.getAttribute(CATEGORY_ATTRIBUTE
);
762 if (categoryAttribute
.isEmpty()) {
763 categoryAttribute
= TmfTraceType
.CUSTOM_TXT_CATEGORY
;
765 String nameAttribute
= element
.getAttribute(NAME_ATTRIBUTE
);
766 if (categoryName
.equals(categoryAttribute
) &&
767 definitionName
.equals(nameAttribute
)) {
776 * Get the definition from a definition element.
778 * @param definitionElement
779 * The Element to extract from
780 * @return The loaded trace definition
782 public static CustomTxtTraceDefinition
extractDefinition(Element definitionElement
) {
783 CustomTxtTraceDefinition def
= new CustomTxtTraceDefinition();
785 def
.categoryName
= definitionElement
.getAttribute(CATEGORY_ATTRIBUTE
);
786 if (def
.categoryName
.isEmpty()) {
787 def
.categoryName
= TmfTraceType
.CUSTOM_TXT_CATEGORY
;
789 def
.definitionName
= definitionElement
.getAttribute(NAME_ATTRIBUTE
);
790 if (def
.definitionName
.isEmpty()) {
794 NodeList nodeList
= definitionElement
.getChildNodes();
795 for (int i
= 0; i
< nodeList
.getLength(); i
++) {
796 Node node
= nodeList
.item(i
);
797 String nodeName
= node
.getNodeName();
798 if (nodeName
.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT
)) {
799 Element formatElement
= (Element
) node
;
800 def
.timeStampOutputFormat
= formatElement
.getTextContent();
801 } else if (nodeName
.equals(INPUT_LINE_ELEMENT
)) {
802 InputLine inputLine
= extractInputLine((Element
) node
);
803 if (inputLine
!= null) {
804 def
.inputs
.add(inputLine
);
806 } else if (nodeName
.equals(OUTPUT_COLUMN_ELEMENT
)) {
807 Element outputColumnElement
= (Element
) node
;
808 OutputColumn outputColumn
= new OutputColumn();
809 outputColumn
.name
= outputColumnElement
.getAttribute(NAME_ATTRIBUTE
);
810 def
.outputs
.add(outputColumn
);
816 private static InputLine
extractInputLine(Element inputLineElement
) {
817 InputLine inputLine
= new InputLine();
818 NodeList nodeList
= inputLineElement
.getChildNodes();
819 for (int i
= 0; i
< nodeList
.getLength(); i
++) {
820 Node node
= nodeList
.item(i
);
821 String nodeName
= node
.getNodeName();
822 if (nodeName
.equals(CARDINALITY_ELEMENT
)) {
823 Element cardinalityElement
= (Element
) node
;
825 int min
= Integer
.parseInt(cardinalityElement
.getAttribute(MIN_ATTRIBUTE
));
826 int max
= Integer
.parseInt(cardinalityElement
.getAttribute(MAX_ATTRIBUTE
));
827 inputLine
.cardinality
= new Cardinality(min
, max
);
828 } catch (NumberFormatException e
) {
831 } else if (nodeName
.equals(REGEX_ELEMENT
)) {
832 Element regexElement
= (Element
) node
;
833 inputLine
.regex
= regexElement
.getTextContent();
834 } else if (nodeName
.equals(INPUT_DATA_ELEMENT
)) {
835 Element inputDataElement
= (Element
) node
;
836 InputData inputData
= new InputData();
837 inputData
.name
= inputDataElement
.getAttribute(NAME_ATTRIBUTE
);
838 inputData
.action
= Integer
.parseInt(inputDataElement
.getAttribute(ACTION_ATTRIBUTE
));
839 inputData
.format
= inputDataElement
.getAttribute(FORMAT_ATTRIBUTE
);
840 inputLine
.addColumn(inputData
);
841 } else if (nodeName
.equals(INPUT_LINE_ELEMENT
)) {
842 Element childInputLineElement
= (Element
) node
;
843 InputLine childInputLine
= extractInputLine(childInputLineElement
);
844 if (childInputLine
!= null) {
845 inputLine
.addChild(childInputLine
);
853 * Delete a definition from the currently loaded ones.
855 * @param definitionName
856 * The name of the definition to delete
857 * @deprecated Use {@link #delete(String, String)}
860 public static void delete(String definitionName
) {
861 delete(TmfTraceType
.CUSTOM_TXT_CATEGORY
, definitionName
);
865 * Delete a definition from the currently loaded ones.
867 * @param categoryName
868 * The category of the definition to delete
869 * @param definitionName
870 * The name of the definition to delete
873 public static void delete(String categoryName
, String definitionName
) {
875 DocumentBuilderFactory dbf
= DocumentBuilderFactory
.newInstance();
876 DocumentBuilder db
= dbf
.newDocumentBuilder();
878 // The following allows xml parsing without access to the dtd
879 db
.setEntityResolver(createEmptyEntityResolver());
881 // The following catches xml parsing exceptions
882 db
.setErrorHandler(createErrorHandler());
884 File file
= new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME
);
885 Document doc
= db
.parse(file
);
887 Element root
= doc
.getDocumentElement();
888 if (!root
.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT
)) {
892 Element definitionElement
= findDefinitionElement(root
, categoryName
, definitionName
);
893 if (definitionElement
!= null) {
894 root
.removeChild(definitionElement
);
897 Transformer transformer
= TransformerFactory
.newInstance().newTransformer();
898 transformer
.setOutputProperty(OutputKeys
.INDENT
, "yes"); //$NON-NLS-1$
900 // initialize StreamResult with File object to save to file
901 StreamResult result
= new StreamResult(new StringWriter());
902 DOMSource source
= new DOMSource(doc
);
903 transformer
.transform(source
, result
);
904 String xmlString
= result
.getWriter().toString();
906 try (FileWriter writer
= new FileWriter(file
);) {
907 writer
.write(xmlString
);
910 TmfTraceType
.removeCustomTraceType(CustomTxtTrace
.class, categoryName
, definitionName
);
911 // Check if default definition needs to be reloaded
912 TmfTraceType
.addCustomTraceType(CustomTxtTrace
.class, categoryName
, definitionName
);
914 } catch (ParserConfigurationException
| SAXException
| IOException
| TransformerFactoryConfigurationError
| TransformerException e
) {
915 Activator
.logError("Error deleting CustomTxtTraceDefinition: definitionName=" + definitionName
, e
); //$NON-NLS-1$