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