tmf: Transition custom parsers to the new location
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / parsers / custom / CustomTxtTraceDefinition.java
1 /*******************************************************************************
2 * Copyright (c) 2010, 2013 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 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.core.parsers.custom;
14
15 import java.io.ByteArrayInputStream;
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.List;
22 import java.util.Map;
23 import java.util.regex.Pattern;
24 import java.util.regex.PatternSyntaxException;
25
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.parsers.ParserConfigurationException;
29 import javax.xml.transform.OutputKeys;
30 import javax.xml.transform.Transformer;
31 import javax.xml.transform.TransformerConfigurationException;
32 import javax.xml.transform.TransformerException;
33 import javax.xml.transform.TransformerFactory;
34 import javax.xml.transform.TransformerFactoryConfigurationError;
35 import javax.xml.transform.dom.DOMSource;
36 import javax.xml.transform.stream.StreamResult;
37
38 import org.eclipse.linuxtools.internal.tmf.core.Activator;
39 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.Node;
43 import org.w3c.dom.NodeList;
44 import org.xml.sax.EntityResolver;
45 import org.xml.sax.ErrorHandler;
46 import org.xml.sax.InputSource;
47 import org.xml.sax.SAXException;
48 import org.xml.sax.SAXParseException;
49
50 /**
51 * Trace definition for custom text traces.
52 *
53 * @author Patrick Tassé
54 * @since 3.0
55 */
56 public class CustomTxtTraceDefinition extends CustomTraceDefinition {
57
58 /** Input lines */
59 public List<InputLine> inputs;
60
61 /** File name of the definition file */
62 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME = "custom_txt_parsers.xml"; //$NON-NLS-1$
63
64 /** Path of the definition file */
65 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME =
66 Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME).toString();
67
68 /** Legacy path to the XML definitions file (in the UI plug-in)
69 * TODO Remove once we feel the transition phase is over. */
70 private static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY =
71 Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
72 .append("org.eclipse.linuxtools.tmf.ui") //$NON-NLS-1$
73 .append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME).toString();
74
75 private static final String CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomTxtTraceDefinition_definitionRootElement;
76 private static final String DEFINITION_ELEMENT = Messages.CustomTxtTraceDefinition_definition;
77 private static final String NAME_ATTRIBUTE = Messages.CustomTxtTraceDefinition_name;
78 private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = Messages.CustomTxtTraceDefinition_timestampOutputFormat;
79 private static final String INPUT_LINE_ELEMENT = Messages.CustomTxtTraceDefinition_inputLine;
80 private static final String CARDINALITY_ELEMENT = Messages.CustomTxtTraceDefinition_cardinality;
81 private static final String MIN_ATTRIBUTE = Messages.CustomTxtTraceDefinition_min;
82 private static final String MAX_ATTRIBUTE = Messages.CustomTxtTraceDefinition_max;
83 private static final String REGEX_ELEMENT = Messages.CustomTxtTraceDefinition_regEx;
84 private static final String INPUT_DATA_ELEMENT = Messages.CustomTxtTraceDefinition_inputData;
85 private static final String ACTION_ATTRIBUTE = Messages.CustomTxtTraceDefinition_action;
86 private static final String FORMAT_ATTRIBUTE = Messages.CustomTxtTraceDefinition_format;
87 private static final String OUTPUT_COLUMN_ELEMENT = Messages.CustomTxtTraceDefinition_outputColumn;
88
89 /**
90 * Default constructor.
91 */
92 public CustomTxtTraceDefinition() {
93 this("", new ArrayList<InputLine>(0), new ArrayList<OutputColumn>(0), ""); //$NON-NLS-1$ //$NON-NLS-2$
94 }
95
96 /**
97 * Full constructor.
98 *
99 * @param logtype
100 * Name of the trace type
101 * @param inputs
102 * List of inputs
103 * @param outputs
104 * List of output columns
105 * @param timeStampOutputFormat
106 * The timestamp format to use
107 */
108 public CustomTxtTraceDefinition(String logtype, List<InputLine> inputs,
109 List<OutputColumn> outputs, String timeStampOutputFormat) {
110 this.definitionName = logtype;
111 this.inputs = inputs;
112 this.outputs = outputs;
113 this.timeStampOutputFormat = timeStampOutputFormat;
114 }
115
116 /**
117 * Wrapper to store a line of the log file
118 */
119 public static class InputLine {
120
121 /** Data columns of this line */
122 public List<InputData> columns;
123
124 /** Cardinality of this line (see {@link Cardinality}) */
125 public Cardinality cardinality;
126
127 /** Parent line */
128 public InputLine parentInput;
129
130 /** Level of this line */
131 public int level;
132
133 /** Next input line in the file */
134 public InputLine nextInput;
135
136 /** Children of this line (if one "event" spans many lines) */
137 public List<InputLine> childrenInputs;
138
139 private String regex;
140 private Pattern pattern;
141
142 /**
143 * Default (empty) constructor.
144 */
145 public InputLine() {}
146
147 /**
148 * Constructor.
149 *
150 * @param cardinality Cardinality of this line.
151 * @param regex Regex
152 * @param columns Columns to use
153 */
154 public InputLine(Cardinality cardinality, String regex, List<InputData> columns) {
155 this.cardinality = cardinality;
156 this.regex = regex;
157 this.columns = columns;
158 }
159
160 /**
161 * Set the regex of this input line
162 *
163 * @param regex
164 * Regex to set
165 */
166 public void setRegex(String regex) {
167 this.regex = regex;
168 this.pattern = null;
169 }
170
171 /**
172 * Get the current regex
173 *
174 * @return The current regex
175 */
176 public String getRegex() {
177 return regex;
178 }
179
180 /**
181 * Get the Pattern object of this line's regex
182 *
183 * @return The Pattern
184 * @throws PatternSyntaxException
185 * If the regex does not parse correctly
186 */
187 public Pattern getPattern() throws PatternSyntaxException {
188 if (pattern == null) {
189 pattern = Pattern.compile(regex);
190 }
191 return pattern;
192 }
193
194 /**
195 * Add a child line to this line.
196 *
197 * @param input
198 * The child input line
199 */
200 public void addChild(InputLine input) {
201 if (childrenInputs == null) {
202 childrenInputs = new ArrayList<>(1);
203 } else if (childrenInputs.size() > 0) {
204 InputLine last = childrenInputs.get(childrenInputs.size() - 1);
205 last.nextInput = input;
206 }
207 childrenInputs.add(input);
208 input.parentInput = this;
209 input.level = this.level + 1;
210 }
211
212 /**
213 * Set the next input line.
214 *
215 * @param input
216 * The next input line
217 */
218 public void addNext(InputLine input) {
219 if (parentInput != null) {
220 int index = parentInput.childrenInputs.indexOf(this);
221 parentInput.childrenInputs.add(index + 1, input);
222 InputLine next = nextInput;
223 nextInput = input;
224 input.nextInput = next;
225 }
226 input.parentInput = this.parentInput;
227 input.level = this.level;
228 }
229
230 /**
231 * Move this line up in its parent's children.
232 */
233 public void moveUp() {
234 if (parentInput != null) {
235 int index = parentInput.childrenInputs.indexOf(this);
236 if (index > 0) {
237 parentInput.childrenInputs.add(index - 1 , parentInput.childrenInputs.remove(index));
238 parentInput.childrenInputs.get(index).nextInput = nextInput;
239 nextInput = parentInput.childrenInputs.get(index);
240 }
241 }
242 }
243
244 /**
245 * Move this line down in its parent's children.
246 */
247 public void moveDown() {
248 if (parentInput != null) {
249 int index = parentInput.childrenInputs.indexOf(this);
250 if (index < parentInput.childrenInputs.size() - 1) {
251 parentInput.childrenInputs.add(index + 1 , parentInput.childrenInputs.remove(index));
252 nextInput = parentInput.childrenInputs.get(index).nextInput;
253 parentInput.childrenInputs.get(index).nextInput = this;
254 }
255 }
256 }
257
258 /**
259 * Add a data column to this line
260 *
261 * @param column
262 * The column to add
263 */
264 public void addColumn(InputData column) {
265 if (columns == null) {
266 columns = new ArrayList<>(1);
267 }
268 columns.add(column);
269 }
270
271 /**
272 * Get the next input lines.
273 *
274 * @param countMap
275 * The map of line "sets".
276 * @return The next list of lines.
277 */
278 public List<InputLine> getNextInputs(Map<InputLine, Integer> countMap) {
279 List<InputLine> nextInputs = new ArrayList<>();
280 InputLine next = nextInput;
281 while (next != null) {
282 nextInputs.add(next);
283 if (next.cardinality.min > 0) {
284 return nextInputs;
285 }
286 next = next.nextInput;
287 }
288 if (parentInput != null && parentInput.level > 0) {
289 int parentCount = countMap.get(parentInput);
290 if (parentCount < parentInput.getMaxCount()) {
291 nextInputs.add(parentInput);
292 }
293 if (parentCount < parentInput.getMinCount()) {
294 return nextInputs;
295 }
296 nextInputs.addAll(parentInput.getNextInputs(countMap));
297 }
298 return nextInputs;
299 }
300
301 /**
302 * Get the minimum possible amount of entries.
303 *
304 * @return The minimum
305 */
306 public int getMinCount() {
307 return cardinality.min;
308 }
309
310 /**
311 * Get the maximum possible amount of entries.
312 *
313 * @return The maximum
314 */
315 public int getMaxCount() {
316 return cardinality.max;
317 }
318
319 @Override
320 public String toString() {
321 return regex + " " + cardinality; //$NON-NLS-1$
322 }
323 }
324
325 /**
326 * Data column for input lines.
327 */
328 public static class InputData {
329
330 /** Name of this column */
331 public String name;
332
333 /** Action id */
334 public int action;
335
336 /** Format */
337 public String format;
338
339 /**
340 * Default (empty) constructor
341 */
342 public InputData() {}
343
344 /**
345 * Full constructor
346 *
347 * @param name Name
348 * @param action Action
349 * @param format Format
350 */
351 public InputData(String name, int action, String format) {
352 this.name = name;
353 this.action = action;
354 this.format = format;
355 }
356
357 /**
358 * Constructor with default format
359 *
360 * @param name Name
361 * @param action Action
362 */
363 public InputData(String name, int action) {
364 this.name = name;
365 this.action = action;
366 }
367 }
368
369 /**
370 * Input line cardinality
371 */
372 public static class Cardinality {
373
374 /** Representation of infinity */
375 public final static int INF = Integer.MAX_VALUE;
376
377 /** Preset for [1, 1] */
378 public final static Cardinality ONE = new Cardinality(1, 1);
379
380 /** Preset for [1, inf] */
381 public final static Cardinality ONE_OR_MORE = new Cardinality(1, INF);
382
383 /** Preset for [0, 1] */
384 public final static Cardinality ZERO_OR_ONE = new Cardinality(0, 1);
385
386 /** Preset for [0, inf] */
387 public final static Cardinality ZERO_OR_MORE = new Cardinality(0, INF);
388
389 private final int min;
390 private final int max;
391
392 /**
393 * Constructor.
394 *
395 * @param min
396 * Minimum
397 * @param max
398 * Maximum
399 */
400 public Cardinality(int min, int max) {
401 this.min = min;
402 this.max = max;
403 }
404
405 @Override
406 public String toString() {
407 return "(" + (min >= 0 ? min : "?") + "," + (max == INF ? "\u221E" : (max >= 0 ? max : "?")) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
408 }
409
410 @Override
411 public int hashCode() {
412 final int prime = 31;
413 int result = 1;
414 result = prime * result + max;
415 result = prime * result + min;
416 return result;
417 }
418
419 @Override
420 public boolean equals(Object obj) {
421 if (this == obj) {
422 return true;
423 }
424 if (obj == null) {
425 return false;
426 }
427 if (!(obj instanceof Cardinality)) {
428 return false;
429 }
430 Cardinality other = (Cardinality) obj;
431 return (this.min == other.min && this.max == other.max);
432 }
433 }
434
435 @Override
436 public void save() {
437 save(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
438 }
439
440 @Override
441 public void save(String path) {
442 try {
443 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
444 DocumentBuilder db = dbf.newDocumentBuilder();
445
446 // The following allows xml parsing without access to the dtd
447 EntityResolver resolver = new EntityResolver() {
448 @Override
449 public InputSource resolveEntity(String publicId, String systemId) {
450 String empty = ""; //$NON-NLS-1$
451 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
452 return new InputSource(bais);
453 }
454 };
455 db.setEntityResolver(resolver);
456
457 // The following catches xml parsing exceptions
458 db.setErrorHandler(new ErrorHandler() {
459 @Override
460 public void error(SAXParseException saxparseexception) throws SAXException {}
461
462 @Override
463 public void warning(SAXParseException saxparseexception) throws SAXException {}
464
465 @Override
466 public void fatalError(SAXParseException saxparseexception) throws SAXException {
467 throw saxparseexception;
468 }
469 });
470
471 Document doc = null;
472 File file = new File(path);
473 if (file.canRead()) {
474 doc = db.parse(file);
475 if (! doc.getDocumentElement().getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
476 return;
477 }
478 } else {
479 doc = db.newDocument();
480 Node node = doc.createElement(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT);
481 doc.appendChild(node);
482 }
483
484 Element root = doc.getDocumentElement();
485
486 NodeList nodeList = root.getChildNodes();
487 for (int i = 0; i < nodeList.getLength(); i++) {
488 Node node = nodeList.item(i);
489 if (node instanceof Element &&
490 node.getNodeName().equals(DEFINITION_ELEMENT) &&
491 definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {
492 root.removeChild(node);
493 }
494 }
495 Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
496 root.appendChild(definitionElement);
497 definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);
498
499 Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);
500 definitionElement.appendChild(formatElement);
501 formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));
502
503 if (inputs != null) {
504 for (InputLine inputLine : inputs) {
505 definitionElement.appendChild(createInputLineElement(inputLine, doc));
506 }
507 }
508
509 if (outputs != null) {
510 for (OutputColumn output : outputs) {
511 Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);
512 definitionElement.appendChild(outputColumnElement);
513 outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);
514 }
515 }
516
517 Transformer transformer = TransformerFactory.newInstance().newTransformer();
518 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
519
520 //initialize StreamResult with File object to save to file
521 StreamResult result = new StreamResult(new StringWriter());
522 DOMSource source = new DOMSource(doc);
523 transformer.transform(source, result);
524 String xmlString = result.getWriter().toString();
525
526 try (FileWriter writer = new FileWriter(file);) {
527 writer.write(xmlString);
528 }
529
530 TmfTraceType.getInstance().addCustomTraceType(TmfTraceType.CUSTOM_TXT_CATEGORY, definitionName);
531
532 } catch (ParserConfigurationException e) {
533 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
534 } catch (TransformerConfigurationException e) {
535 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
536 } catch (TransformerFactoryConfigurationError e) {
537 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
538 } catch (TransformerException e) {
539 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
540 } catch (IOException e) {
541 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
542 } catch (SAXException e) {
543 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
544 }
545 }
546
547 private Element createInputLineElement(InputLine inputLine, Document doc) {
548 Element inputLineElement = doc.createElement(INPUT_LINE_ELEMENT);
549
550 Element cardinalityElement = doc.createElement(CARDINALITY_ELEMENT);
551 inputLineElement.appendChild(cardinalityElement);
552 cardinalityElement.setAttribute(MIN_ATTRIBUTE, Integer.toString(inputLine.cardinality.min));
553 cardinalityElement.setAttribute(MAX_ATTRIBUTE, Integer.toString(inputLine.cardinality.max));
554
555 Element regexElement = doc.createElement(REGEX_ELEMENT);
556 inputLineElement.appendChild(regexElement);
557 regexElement.appendChild(doc.createTextNode(inputLine.regex));
558
559 if (inputLine.columns != null) {
560 for (InputData inputData : inputLine.columns) {
561 Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
562 inputLineElement.appendChild(inputDataElement);
563 inputDataElement.setAttribute(NAME_ATTRIBUTE, inputData.name);
564 inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputData.action));
565 if (inputData.format != null) {
566 inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputData.format);
567 }
568 }
569 }
570
571 if (inputLine.childrenInputs != null) {
572 for (InputLine childInputLine : inputLine.childrenInputs) {
573 inputLineElement.appendChild(createInputLineElement(childInputLine, doc));
574 }
575 }
576
577 return inputLineElement;
578 }
579
580 /**
581 * Load the default text trace definitions file.
582 *
583 * @return The loaded trace definitions
584 */
585 public static CustomTxtTraceDefinition[] loadAll() {
586 File defaultFile = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
587 File legacyFile = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY);
588
589 /*
590 * If there is no file at the expected location, check the legacy
591 * location instead.
592 */
593 if (!defaultFile.exists() && legacyFile.exists()) {
594 CustomTxtTraceDefinition[] oldDefs = loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY);
595 for (CustomTxtTraceDefinition def : oldDefs) {
596 /* Save in the new location */
597 def.save();
598 }
599 }
600
601 return loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
602 }
603
604 /**
605 * Load a specific text trace definition file.
606 *
607 * @param path
608 * The path to the file to load
609 * @return The loaded trace definitions
610 */
611 public static CustomTxtTraceDefinition[] loadAll(String path) {
612 try {
613 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
614 DocumentBuilder db = dbf.newDocumentBuilder();
615
616 // The following allows xml parsing without access to the dtd
617 EntityResolver resolver = new EntityResolver() {
618 @Override
619 public InputSource resolveEntity(String publicId, String systemId) {
620 String empty = ""; //$NON-NLS-1$
621 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
622 return new InputSource(bais);
623 }
624 };
625 db.setEntityResolver(resolver);
626
627 // The following catches xml parsing exceptions
628 db.setErrorHandler(new ErrorHandler() {
629 @Override
630 public void error(SAXParseException saxparseexception) throws SAXException {}
631
632 @Override
633 public void warning(SAXParseException saxparseexception) throws SAXException {}
634
635 @Override
636 public void fatalError(SAXParseException saxparseexception) throws SAXException {
637 throw saxparseexception;
638 }
639 });
640
641 File file = new File(path);
642 if (!file.canRead()) {
643 return new CustomTxtTraceDefinition[0];
644 }
645 Document doc = db.parse(file);
646
647 Element root = doc.getDocumentElement();
648 if (! root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
649 return new CustomTxtTraceDefinition[0];
650 }
651
652 ArrayList<CustomTxtTraceDefinition> defList = new ArrayList<>();
653 NodeList nodeList = root.getChildNodes();
654 for (int i = 0; i < nodeList.getLength(); i++) {
655 Node node = nodeList.item(i);
656 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
657 CustomTxtTraceDefinition def = extractDefinition((Element) node);
658 if (def != null) {
659 defList.add(def);
660 }
661 }
662 }
663 return defList.toArray(new CustomTxtTraceDefinition[0]);
664 } catch (ParserConfigurationException e) {
665 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
666 } catch (SAXException e) {
667 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
668 } catch (IOException e) {
669 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
670 }
671 return new CustomTxtTraceDefinition[0];
672 }
673
674 /**
675 * Load a single definition.
676 *
677 * @param definitionName
678 * Name of the definition to load
679 * @return The loaded trace definition
680 */
681 public static CustomTxtTraceDefinition load(String definitionName) {
682 try {
683 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
684 DocumentBuilder db = dbf.newDocumentBuilder();
685
686 // The following allows xml parsing without access to the dtd
687 EntityResolver resolver = new EntityResolver() {
688 @Override
689 public InputSource resolveEntity(String publicId, String systemId) {
690 String empty = ""; //$NON-NLS-1$
691 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
692 return new InputSource(bais);
693 }
694 };
695 db.setEntityResolver(resolver);
696
697 // The following catches xml parsing exceptions
698 db.setErrorHandler(new ErrorHandler() {
699 @Override
700 public void error(SAXParseException saxparseexception) throws SAXException {}
701
702 @Override
703 public void warning(SAXParseException saxparseexception) throws SAXException {}
704
705 @Override
706 public void fatalError(SAXParseException saxparseexception) throws SAXException {
707 throw saxparseexception;
708 }
709 });
710
711 File file = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
712 Document doc = db.parse(file);
713
714 Element root = doc.getDocumentElement();
715 if (! root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
716 return null;
717 }
718
719 NodeList nodeList = root.getChildNodes();
720 for (int i = 0; i < nodeList.getLength(); i++) {
721 Node node = nodeList.item(i);
722 if (node instanceof Element &&
723 node.getNodeName().equals(DEFINITION_ELEMENT) &&
724 definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {
725 return extractDefinition((Element) node);
726 }
727 }
728 } catch (ParserConfigurationException e) {
729 Activator.logError("Error loading CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
730 } catch (SAXException e) {
731 Activator.logError("Error loading CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
732 } catch (IOException e) {
733 Activator.logError("Error loading CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
734 }
735 return null;
736 }
737
738 /**
739 * Get the definition from a definition element.
740 *
741 * @param definitionElement
742 * The Element to extract from
743 * @return The loaded trace definition
744 */
745 public static CustomTxtTraceDefinition extractDefinition(Element definitionElement) {
746 CustomTxtTraceDefinition def = new CustomTxtTraceDefinition();
747
748 def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
749 if (def.definitionName == null) {
750 return null;
751 }
752
753 NodeList nodeList = definitionElement.getChildNodes();
754 for (int i = 0; i < nodeList.getLength(); i++) {
755 Node node = nodeList.item(i);
756 String nodeName = node.getNodeName();
757 if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {
758 Element formatElement = (Element) node;
759 def.timeStampOutputFormat = formatElement.getTextContent();
760 } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {
761 InputLine inputLine = extractInputLine((Element) node);
762 if (inputLine != null) {
763 def.inputs.add(inputLine);
764 }
765 } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {
766 Element outputColumnElement = (Element) node;
767 OutputColumn outputColumn = new OutputColumn();
768 outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE);
769 def.outputs.add(outputColumn);
770 }
771 }
772 return def;
773 }
774
775 private static InputLine extractInputLine(Element inputLineElement) {
776 InputLine inputLine = new InputLine();
777 NodeList nodeList = inputLineElement.getChildNodes();
778 for (int i = 0; i < nodeList.getLength(); i++) {
779 Node node = nodeList.item(i);
780 String nodeName = node.getNodeName();
781 if (nodeName.equals(CARDINALITY_ELEMENT)) {
782 Element cardinalityElement = (Element) node;
783 try {
784 int min = Integer.parseInt(cardinalityElement.getAttribute(MIN_ATTRIBUTE));
785 int max = Integer.parseInt(cardinalityElement.getAttribute(MAX_ATTRIBUTE));
786 inputLine.cardinality = new Cardinality(min, max);
787 } catch (NumberFormatException e) {
788 return null;
789 }
790 } else if (nodeName.equals(REGEX_ELEMENT)) {
791 Element regexElement = (Element) node;
792 inputLine.regex = regexElement.getTextContent();
793 } else if (nodeName.equals(INPUT_DATA_ELEMENT)) {
794 Element inputDataElement = (Element) node;
795 InputData inputData = new InputData();
796 inputData.name = inputDataElement.getAttribute(NAME_ATTRIBUTE);
797 inputData.action = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));
798 inputData.format = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);
799 inputLine.addColumn(inputData);
800 } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {
801 Element childInputLineElement = (Element) node;
802 InputLine childInputLine = extractInputLine(childInputLineElement);
803 if (childInputLine != null) {
804 inputLine.addChild(childInputLine);
805 }
806 }
807 }
808 return inputLine;
809 }
810
811 /**
812 * Delete a definition from the currently loaded ones.
813 *
814 * @param definitionName
815 * The name of the definition to delete
816 */
817 public static void delete(String definitionName) {
818 try {
819 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
820 DocumentBuilder db = dbf.newDocumentBuilder();
821
822 // The following allows xml parsing without access to the dtd
823 EntityResolver resolver = new EntityResolver() {
824 @Override
825 public InputSource resolveEntity(String publicId, String systemId) {
826 String empty = ""; //$NON-NLS-1$
827 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
828 return new InputSource(bais);
829 }
830 };
831 db.setEntityResolver(resolver);
832
833 // The following catches xml parsing exceptions
834 db.setErrorHandler(new ErrorHandler() {
835 @Override
836 public void error(SAXParseException saxparseexception) throws SAXException {}
837
838 @Override
839 public void warning(SAXParseException saxparseexception) throws SAXException {}
840
841 @Override
842 public void fatalError(SAXParseException saxparseexception) throws SAXException {
843 throw saxparseexception;
844 }
845 });
846
847 File file = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
848 Document doc = db.parse(file);
849
850 Element root = doc.getDocumentElement();
851 if (! root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
852 return;
853 }
854
855 NodeList nodeList = root.getChildNodes();
856 for (int i = 0; i < nodeList.getLength(); i++) {
857 Node node = nodeList.item(i);
858 if (node instanceof Element &&
859 node.getNodeName().equals(DEFINITION_ELEMENT) &&
860 definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {
861 root.removeChild(node);
862 }
863 }
864
865 Transformer transformer = TransformerFactory.newInstance().newTransformer();
866 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
867
868 //initialize StreamResult with File object to save to file
869 StreamResult result = new StreamResult(new StringWriter());
870 DOMSource source = new DOMSource(doc);
871 transformer.transform(source, result);
872 String xmlString = result.getWriter().toString();
873
874 try (FileWriter writer = new FileWriter(file);) {
875 writer.write(xmlString);
876 }
877
878 TmfTraceType.getInstance().removeCustomTraceType(TmfTraceType.CUSTOM_TXT_CATEGORY, definitionName);
879
880 } catch (ParserConfigurationException e) {
881 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
882 } catch (SAXException e) {
883 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName= " + definitionName, e); //$NON-NLS-1$
884 } catch (IOException e) {
885 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName= " + definitionName, e); //$NON-NLS-1$
886 } catch (TransformerConfigurationException e) {
887 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName= " + definitionName, e); //$NON-NLS-1$
888 } catch (TransformerFactoryConfigurationError e) {
889 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName= " + definitionName, e); //$NON-NLS-1$
890 } catch (TransformerException e) {
891 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName= " + definitionName, e); //$NON-NLS-1$
892 }
893 }
894 }
This page took 0.053452 seconds and 6 git commands to generate.