ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / parsers / custom / CustomTxtTraceDefinition.java
1 /*******************************************************************************
2 * Copyright (c) 2010, 2014 Ericsson
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
11 * Matthew Khouzam - Add support for default parsers
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.tmf.core.parsers.custom;
15
16 import java.io.File;
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;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.TreeSet;
27 import java.util.regex.Pattern;
28 import java.util.regex.PatternSyntaxException;
29
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;
41
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;
50
51 /**
52 * Trace definition for custom text traces.
53 *
54 * @author Patrick Tassé
55 * @since 3.0
56 */
57 public class CustomTxtTraceDefinition extends CustomTraceDefinition {
58
59 /** Input lines */
60 public List<InputLine> inputs;
61
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$
66
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();
74
75 /**
76 * Legacy path to the XML definitions file (in the UI plug-in) TODO Remove
77 * once we feel the transition phase is over.
78 */
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();
83
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;
98
99 /**
100 * Default constructor.
101 */
102 public CustomTxtTraceDefinition() {
103 this(TmfTraceType.CUSTOM_TXT_CATEGORY, "", new ArrayList<InputLine>(0), new ArrayList<OutputColumn>(0), ""); //$NON-NLS-1$ //$NON-NLS-2$
104 }
105
106 /**
107 * Full constructor.
108 *
109 * @param traceType
110 * Name of the trace type
111 * @param inputs
112 * List of inputs
113 * @param outputs
114 * List of output columns
115 * @param timeStampOutputFormat
116 * The timestamp format to use
117 * @deprecated Use {@link #CustomTxtTraceDefinition(String, String, List, List, String)}
118 */
119 @Deprecated
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;
126 }
127
128 /**
129 * Full constructor.
130 *
131 * @param category
132 * Category of the trace type
133 * @param traceType
134 * Name of the trace type
135 * @param inputs
136 * List of inputs
137 * @param outputs
138 * List of output columns
139 * @param timeStampOutputFormat
140 * The timestamp format to use
141 * @since 3.2
142 */
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;
150 }
151
152 /**
153 * Wrapper to store a line of the log file
154 */
155 public static class InputLine {
156
157 /** Data columns of this line */
158 public List<InputData> columns;
159
160 /** Cardinality of this line (see {@link Cardinality}) */
161 public Cardinality cardinality;
162
163 /** Parent line */
164 public InputLine parentInput;
165
166 /** Level of this line */
167 public int level;
168
169 /** Next input line in the file */
170 public InputLine nextInput;
171
172 /** Children of this line (if one "event" spans many lines) */
173 public List<InputLine> childrenInputs;
174
175 private String regex;
176 private Pattern pattern;
177
178 /**
179 * Default (empty) constructor.
180 */
181 public InputLine() {
182 }
183
184 /**
185 * Constructor.
186 *
187 * @param cardinality
188 * Cardinality of this line.
189 * @param regex
190 * Regex
191 * @param columns
192 * Columns to use
193 */
194 public InputLine(Cardinality cardinality, String regex, List<InputData> columns) {
195 this.cardinality = cardinality;
196 this.regex = regex;
197 this.columns = columns;
198 }
199
200 /**
201 * Set the regex of this input line
202 *
203 * @param regex
204 * Regex to set
205 */
206 public void setRegex(String regex) {
207 this.regex = regex;
208 this.pattern = null;
209 }
210
211 /**
212 * Get the current regex
213 *
214 * @return The current regex
215 */
216 public String getRegex() {
217 return regex;
218 }
219
220 /**
221 * Get the Pattern object of this line's regex
222 *
223 * @return The Pattern
224 * @throws PatternSyntaxException
225 * If the regex does not parse correctly
226 */
227 public Pattern getPattern() throws PatternSyntaxException {
228 if (pattern == null) {
229 pattern = Pattern.compile(regex);
230 }
231 return pattern;
232 }
233
234 /**
235 * Add a child line to this line.
236 *
237 * @param input
238 * The child input line
239 */
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;
246 }
247 childrenInputs.add(input);
248 input.parentInput = this;
249 input.level = this.level + 1;
250 }
251
252 /**
253 * Set the next input line.
254 *
255 * @param input
256 * The next input line
257 */
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;
263 nextInput = input;
264 input.nextInput = next;
265 }
266 input.parentInput = this.parentInput;
267 input.level = this.level;
268 }
269
270 /**
271 * Move this line up in its parent's children.
272 */
273 public void moveUp() {
274 if (parentInput != null) {
275 int index = parentInput.childrenInputs.indexOf(this);
276 if (index > 0) {
277 parentInput.childrenInputs.add(index - 1, parentInput.childrenInputs.remove(index));
278 parentInput.childrenInputs.get(index).nextInput = nextInput;
279 nextInput = parentInput.childrenInputs.get(index);
280 }
281 }
282 }
283
284 /**
285 * Move this line down in its parent's children.
286 */
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;
294 }
295 }
296 }
297
298 /**
299 * Add a data column to this line
300 *
301 * @param column
302 * The column to add
303 */
304 public void addColumn(InputData column) {
305 if (columns == null) {
306 columns = new ArrayList<>(1);
307 }
308 columns.add(column);
309 }
310
311 /**
312 * Get the next input lines.
313 *
314 * @param countMap
315 * The map of line "sets".
316 * @return The next list of lines.
317 */
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) {
324 return nextInputs;
325 }
326 next = next.nextInput;
327 }
328 if (parentInput != null && parentInput.level > 0) {
329 int parentCount = countMap.get(parentInput);
330 if (parentCount < parentInput.getMaxCount()) {
331 nextInputs.add(parentInput);
332 }
333 if (parentCount < parentInput.getMinCount()) {
334 return nextInputs;
335 }
336 nextInputs.addAll(parentInput.getNextInputs(countMap));
337 }
338 return nextInputs;
339 }
340
341 /**
342 * Get the minimum possible amount of entries.
343 *
344 * @return The minimum
345 */
346 public int getMinCount() {
347 return cardinality.min;
348 }
349
350 /**
351 * Get the maximum possible amount of entries.
352 *
353 * @return The maximum
354 */
355 public int getMaxCount() {
356 return cardinality.max;
357 }
358
359 @Override
360 public String toString() {
361 return regex + " " + cardinality; //$NON-NLS-1$
362 }
363 }
364
365 /**
366 * Data column for input lines.
367 */
368 public static class InputData {
369
370 /** Name of this column */
371 public String name;
372
373 /** Action id */
374 public int action;
375
376 /** Format */
377 public String format;
378
379 /**
380 * Default (empty) constructor
381 */
382 public InputData() {
383 }
384
385 /**
386 * Full constructor
387 *
388 * @param name
389 * Name
390 * @param action
391 * Action
392 * @param format
393 * Format
394 */
395 public InputData(String name, int action, String format) {
396 this.name = name;
397 this.action = action;
398 this.format = format;
399 }
400
401 /**
402 * Constructor with default format
403 *
404 * @param name
405 * Name
406 * @param action
407 * Action
408 */
409 public InputData(String name, int action) {
410 this.name = name;
411 this.action = action;
412 }
413 }
414
415 /**
416 * Input line cardinality
417 */
418 public static class Cardinality {
419
420 /** Representation of infinity */
421 public final static int INF = Integer.MAX_VALUE;
422
423 /** Preset for [1, 1] */
424 public final static Cardinality ONE = new Cardinality(1, 1);
425
426 /** Preset for [1, inf] */
427 public final static Cardinality ONE_OR_MORE = new Cardinality(1, INF);
428
429 /** Preset for [0, 1] */
430 public final static Cardinality ZERO_OR_ONE = new Cardinality(0, 1);
431
432 /** Preset for [0, inf] */
433 public final static Cardinality ZERO_OR_MORE = new Cardinality(0, INF);
434
435 private final int min;
436 private final int max;
437
438 /**
439 * Constructor.
440 *
441 * @param min
442 * Minimum
443 * @param max
444 * Maximum
445 */
446 public Cardinality(int min, int max) {
447 this.min = min;
448 this.max = max;
449 }
450
451 @Override
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$
454 }
455
456 @Override
457 public int hashCode() {
458 final int prime = 31;
459 int result = 1;
460 result = prime * result + max;
461 result = prime * result + min;
462 return result;
463 }
464
465 @Override
466 public boolean equals(Object obj) {
467 if (this == obj) {
468 return true;
469 }
470 if (obj == null) {
471 return false;
472 }
473 if (!(obj instanceof Cardinality)) {
474 return false;
475 }
476 Cardinality other = (Cardinality) obj;
477 return (this.min == other.min && this.max == other.max);
478 }
479 }
480
481 @Override
482 public void save() {
483 save(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
484 }
485
486 @Override
487 public void save(String path) {
488 try {
489 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
490 DocumentBuilder db = dbf.newDocumentBuilder();
491
492 // The following allows xml parsing without access to the dtd
493 db.setEntityResolver(createEmptyEntityResolver());
494
495 // The following catches xml parsing exceptions
496 db.setErrorHandler(createErrorHandler());
497
498 Document doc = null;
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)) {
503 return;
504 }
505 } else {
506 doc = db.newDocument();
507 Node node = doc.createElement(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT);
508 doc.appendChild(node);
509 }
510
511 Element root = doc.getDocumentElement();
512
513 Element oldDefinitionElement = findDefinitionElement(root, categoryName, definitionName);
514 if (oldDefinitionElement != null) {
515 root.removeChild(oldDefinitionElement);
516 }
517 Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
518 root.appendChild(definitionElement);
519 definitionElement.setAttribute(CATEGORY_ATTRIBUTE, categoryName);
520 definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);
521
522 Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);
523 definitionElement.appendChild(formatElement);
524 formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));
525
526 if (inputs != null) {
527 for (InputLine inputLine : inputs) {
528 definitionElement.appendChild(createInputLineElement(inputLine, doc));
529 }
530 }
531
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);
537 }
538 }
539
540 Transformer transformer = TransformerFactory.newInstance().newTransformer();
541 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
542
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();
548
549 try (FileWriter writer = new FileWriter(file);) {
550 writer.write(xmlString);
551 }
552
553 TmfTraceType.addCustomTraceType(CustomTxtTrace.class, categoryName, definitionName);
554
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$
567 }
568 }
569
570 private Element createInputLineElement(InputLine inputLine, Document doc) {
571 Element inputLineElement = doc.createElement(INPUT_LINE_ELEMENT);
572
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));
577
578 Element regexElement = doc.createElement(REGEX_ELEMENT);
579 inputLineElement.appendChild(regexElement);
580 regexElement.appendChild(doc.createTextNode(inputLine.regex));
581
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);
590 }
591 }
592 }
593
594 if (inputLine.childrenInputs != null) {
595 for (InputLine childInputLine : inputLine.childrenInputs) {
596 inputLineElement.appendChild(createInputLineElement(childInputLine, doc));
597 }
598 }
599
600 return inputLineElement;
601 }
602
603 /**
604 * Load all custom text trace definitions, including the user-defined and
605 * default (built-in) parsers.
606 *
607 * @return The loaded trace definitions
608 */
609 public static CustomTxtTraceDefinition[] loadAll() {
610 return loadAll(true);
611 }
612
613 /**
614 * Load all custom text trace definitions, including the user-defined and,
615 * optionally, the default (built-in) parsers.
616 *
617 * @param includeDefaults
618 * if true, the default (built-in) parsers are included
619 *
620 * @return The loaded trace definitions
621 * @since 3.2
622 */
623 public static CustomTxtTraceDefinition[] loadAll(boolean includeDefaults) {
624 File defaultFile = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
625 File legacyFile = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY);
626
627 /*
628 * If there is no file at the expected location, check the legacy
629 * location instead.
630 */
631 if (!defaultFile.exists() && legacyFile.exists()) {
632 CustomTxtTraceDefinition[] oldDefs = loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY);
633 for (CustomTxtTraceDefinition def : oldDefs) {
634 /* Save in the new location */
635 def.save();
636 }
637 }
638
639 Set<CustomTxtTraceDefinition> defs = new TreeSet<>(new Comparator<CustomTxtTraceDefinition>() {
640 @Override
641 public int compare(CustomTxtTraceDefinition o1, CustomTxtTraceDefinition o2) {
642 int result = o1.categoryName.compareTo(o2.categoryName);
643 if (result != 0) {
644 return result;
645 }
646 return o1.definitionName.compareTo(o2.definitionName);
647 }
648 });
649 defs.addAll(Arrays.asList(loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME)));
650 if (includeDefaults) {
651 defs.addAll(Arrays.asList(loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME)));
652 }
653 return defs.toArray(new CustomTxtTraceDefinition[0]);
654
655 }
656
657 /**
658 * Load a specific text trace definition file.
659 *
660 * @param path
661 * The path to the file to load
662 * @return The loaded trace definitions
663 */
664 public static CustomTxtTraceDefinition[] loadAll(String path) {
665 try {
666 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
667 DocumentBuilder db = dbf.newDocumentBuilder();
668
669 // The following allows xml parsing without access to the dtd
670 db.setEntityResolver(createEmptyEntityResolver());
671
672 // The following catches xml parsing exceptions
673 db.setErrorHandler(createErrorHandler());
674
675 File file = new File(path);
676 if (!file.canRead()) {
677 return new CustomTxtTraceDefinition[0];
678 }
679 Document doc = db.parse(file);
680
681 Element root = doc.getDocumentElement();
682 if (!root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
683 return new CustomTxtTraceDefinition[0];
684 }
685
686 ArrayList<CustomTxtTraceDefinition> defList = new ArrayList<>();
687 NodeList nodeList = root.getChildNodes();
688 for (int i = 0; i < nodeList.getLength(); i++) {
689 Node node = nodeList.item(i);
690 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
691 CustomTxtTraceDefinition def = extractDefinition((Element) node);
692 if (def != null) {
693 defList.add(def);
694 }
695 }
696 }
697 return defList.toArray(new CustomTxtTraceDefinition[0]);
698 } catch (ParserConfigurationException e) {
699 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
700 } catch (SAXException e) {
701 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
702 } catch (IOException e) {
703 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
704 }
705 return new CustomTxtTraceDefinition[0];
706 }
707
708 /**
709 * Load a single definition.
710 *
711 * @param definitionName
712 * Name of the definition to load
713 * @return The loaded trace definition
714 * @deprecated Use {@link #load(String, String)}
715 */
716 @Deprecated
717 public static CustomTxtTraceDefinition load(String definitionName) {
718 return load(TmfTraceType.CUSTOM_TXT_CATEGORY, definitionName);
719 }
720
721 /**
722 * Load a single definition.
723 *
724 * @param categoryName
725 * Category of the definition to load
726 * @param definitionName
727 * Name of the definition to load
728 * @return The loaded trace definition
729 * @since 3.2
730 */
731 public static CustomTxtTraceDefinition load(String categoryName, String definitionName) {
732 try {
733 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
734 DocumentBuilder db = dbf.newDocumentBuilder();
735
736 // The following allows xml parsing without access to the dtd
737 db.setEntityResolver(createEmptyEntityResolver());
738
739 // The following catches xml parsing exceptions
740 db.setErrorHandler(createErrorHandler());
741
742 CustomTxtTraceDefinition value = lookupDefinition(categoryName, definitionName, db, CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
743 if (value == null) {
744 return lookupDefinition(categoryName, definitionName, db, CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME);
745 }
746 return value;
747 } catch (ParserConfigurationException | SAXException | IOException e) {
748 Activator.logError("Error loading CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
749 }
750 return null;
751 }
752
753 private static CustomTxtTraceDefinition lookupDefinition(String categoryName, String definitionName, DocumentBuilder db, String source) throws SAXException, IOException {
754 File file = new File(source);
755 if (!file.exists()) {
756 return null;
757 }
758 Document doc = db.parse(file);
759
760 Element root = doc.getDocumentElement();
761 if (!root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
762 return null;
763 }
764
765 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
766 if (definitionElement != null) {
767 return extractDefinition(definitionElement);
768 }
769 return null;
770 }
771
772 private static Element findDefinitionElement(Element root, String categoryName, String definitionName) {
773 NodeList nodeList = root.getChildNodes();
774 for (int i = 0; i < nodeList.getLength(); i++) {
775 Node node = nodeList.item(i);
776 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
777 Element element = (Element) node;
778 String categoryAttribute = element.getAttribute(CATEGORY_ATTRIBUTE);
779 if (categoryAttribute.isEmpty()) {
780 categoryAttribute = TmfTraceType.CUSTOM_TXT_CATEGORY;
781 }
782 String nameAttribute = element.getAttribute(NAME_ATTRIBUTE);
783 if (categoryName.equals(categoryAttribute) &&
784 definitionName.equals(nameAttribute)) {
785 return element;
786 }
787 }
788 }
789 return null;
790 }
791
792 /**
793 * Get the definition from a definition element.
794 *
795 * @param definitionElement
796 * The Element to extract from
797 * @return The loaded trace definition
798 */
799 public static CustomTxtTraceDefinition extractDefinition(Element definitionElement) {
800 CustomTxtTraceDefinition def = new CustomTxtTraceDefinition();
801
802 def.categoryName = definitionElement.getAttribute(CATEGORY_ATTRIBUTE);
803 if (def.categoryName.isEmpty()) {
804 def.categoryName = TmfTraceType.CUSTOM_TXT_CATEGORY;
805 }
806 def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
807 if (def.definitionName.isEmpty()) {
808 return null;
809 }
810
811 NodeList nodeList = definitionElement.getChildNodes();
812 for (int i = 0; i < nodeList.getLength(); i++) {
813 Node node = nodeList.item(i);
814 String nodeName = node.getNodeName();
815 if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {
816 Element formatElement = (Element) node;
817 def.timeStampOutputFormat = formatElement.getTextContent();
818 } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {
819 InputLine inputLine = extractInputLine((Element) node);
820 if (inputLine != null) {
821 def.inputs.add(inputLine);
822 }
823 } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {
824 Element outputColumnElement = (Element) node;
825 OutputColumn outputColumn = new OutputColumn();
826 outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE);
827 def.outputs.add(outputColumn);
828 }
829 }
830 return def;
831 }
832
833 private static InputLine extractInputLine(Element inputLineElement) {
834 InputLine inputLine = new InputLine();
835 NodeList nodeList = inputLineElement.getChildNodes();
836 for (int i = 0; i < nodeList.getLength(); i++) {
837 Node node = nodeList.item(i);
838 String nodeName = node.getNodeName();
839 if (nodeName.equals(CARDINALITY_ELEMENT)) {
840 Element cardinalityElement = (Element) node;
841 try {
842 int min = Integer.parseInt(cardinalityElement.getAttribute(MIN_ATTRIBUTE));
843 int max = Integer.parseInt(cardinalityElement.getAttribute(MAX_ATTRIBUTE));
844 inputLine.cardinality = new Cardinality(min, max);
845 } catch (NumberFormatException e) {
846 return null;
847 }
848 } else if (nodeName.equals(REGEX_ELEMENT)) {
849 Element regexElement = (Element) node;
850 inputLine.regex = regexElement.getTextContent();
851 } else if (nodeName.equals(INPUT_DATA_ELEMENT)) {
852 Element inputDataElement = (Element) node;
853 InputData inputData = new InputData();
854 inputData.name = inputDataElement.getAttribute(NAME_ATTRIBUTE);
855 inputData.action = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));
856 inputData.format = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);
857 inputLine.addColumn(inputData);
858 } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {
859 Element childInputLineElement = (Element) node;
860 InputLine childInputLine = extractInputLine(childInputLineElement);
861 if (childInputLine != null) {
862 inputLine.addChild(childInputLine);
863 }
864 }
865 }
866 return inputLine;
867 }
868
869 /**
870 * Delete a definition from the currently loaded ones.
871 *
872 * @param definitionName
873 * The name of the definition to delete
874 * @deprecated Use {@link #delete(String, String)}
875 */
876 @Deprecated
877 public static void delete(String definitionName) {
878 delete(TmfTraceType.CUSTOM_TXT_CATEGORY, definitionName);
879 }
880
881 /**
882 * Delete a definition from the currently loaded ones.
883 *
884 * @param categoryName
885 * The category of the definition to delete
886 * @param definitionName
887 * The name of the definition to delete
888 * @since 3.2
889 */
890 public static void delete(String categoryName, String definitionName) {
891 try {
892 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
893 DocumentBuilder db = dbf.newDocumentBuilder();
894
895 // The following allows xml parsing without access to the dtd
896 db.setEntityResolver(createEmptyEntityResolver());
897
898 // The following catches xml parsing exceptions
899 db.setErrorHandler(createErrorHandler());
900
901 File file = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
902 Document doc = db.parse(file);
903
904 Element root = doc.getDocumentElement();
905 if (!root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
906 return;
907 }
908
909 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
910 if (definitionElement != null) {
911 root.removeChild(definitionElement);
912 }
913
914 Transformer transformer = TransformerFactory.newInstance().newTransformer();
915 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
916
917 // initialize StreamResult with File object to save to file
918 StreamResult result = new StreamResult(new StringWriter());
919 DOMSource source = new DOMSource(doc);
920 transformer.transform(source, result);
921 String xmlString = result.getWriter().toString();
922
923 try (FileWriter writer = new FileWriter(file);) {
924 writer.write(xmlString);
925 }
926
927 TmfTraceType.removeCustomTraceType(CustomTxtTrace.class, categoryName, definitionName);
928 // Check if default definition needs to be reloaded
929 TmfTraceType.addCustomTraceType(CustomTxtTrace.class, categoryName, definitionName);
930
931 } catch (ParserConfigurationException | SAXException | IOException | TransformerFactoryConfigurationError | TransformerException e) {
932 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
933 }
934 }
935 }
This page took 0.054594 seconds and 5 git commands to generate.