tmf.ui clean up CustomXmlTraceDefinition a bit
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / parsers / custom / CustomXmlTraceDefinition.java
CommitLineData
be222f56 1/*******************************************************************************
70b7bc9c 2 * Copyright (c) 2010, 2014 Ericsson
be222f56
PT
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Patrick Tasse - Initial API and implementation
70b7bc9c 11 * Matthew Khouzam - Add support for default xml parsers
be222f56
PT
12 *******************************************************************************/
13
2bdf0193 14package org.eclipse.tracecompass.tmf.core.parsers.custom;
be222f56
PT
15
16import java.io.ByteArrayInputStream;
17import java.io.File;
1d8ab692 18import java.io.FileInputStream;
be222f56
PT
19import java.io.FileWriter;
20import java.io.IOException;
1d8ab692 21import java.io.InputStream;
be222f56
PT
22import java.io.StringWriter;
23import java.util.ArrayList;
70b7bc9c
MK
24import java.util.Arrays;
25import java.util.Comparator;
be222f56 26import java.util.List;
70b7bc9c
MK
27import java.util.Set;
28import java.util.TreeSet;
be222f56
PT
29
30import javax.xml.parsers.DocumentBuilder;
31import javax.xml.parsers.DocumentBuilderFactory;
32import javax.xml.parsers.ParserConfigurationException;
33import javax.xml.transform.OutputKeys;
34import javax.xml.transform.Transformer;
be222f56
PT
35import javax.xml.transform.TransformerException;
36import javax.xml.transform.TransformerFactory;
37import javax.xml.transform.TransformerFactoryConfigurationError;
38import javax.xml.transform.dom.DOMSource;
39import javax.xml.transform.stream.StreamResult;
40
70b7bc9c 41import org.eclipse.core.runtime.Platform;
2bdf0193
AM
42import org.eclipse.tracecompass.internal.tmf.core.Activator;
43import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
be222f56
PT
44import org.w3c.dom.Document;
45import org.w3c.dom.Element;
46import org.w3c.dom.Node;
47import org.w3c.dom.NodeList;
48import org.xml.sax.EntityResolver;
49import org.xml.sax.ErrorHandler;
50import org.xml.sax.InputSource;
51import org.xml.sax.SAXException;
52import org.xml.sax.SAXParseException;
53
a0a88f65
AM
54/**
55 * Trace definition for custom XML traces.
56 *
57 * @author Patrick Tassé
47aafe74 58 * @since 3.0
a0a88f65 59 */
be222f56
PT
60public class CustomXmlTraceDefinition extends CustomTraceDefinition {
61
a0a88f65
AM
62 /** "ignore" tag */
63 public static final String TAG_IGNORE = Messages.CustomXmlTraceDefinition_ignoreTag;
64
70b7bc9c
MK
65 /** Name of the default XML definitions file */
66 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME = "custom_xml_default_parsers.xml"; //$NON-NLS-1$
67
a0a88f65 68 /** Name of the XML definitions file */
be222f56 69 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME = "custom_xml_parsers.xml"; //$NON-NLS-1$
a0a88f65 70
70b7bc9c
MK
71 /** Path to the XML definitions file */
72 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME =
cb1cf0e8
MK
73 Platform.getInstallLocation().getURL().getPath() + "templates/org.eclipse.linuxtools.tmf.core/" + //$NON-NLS-1$
74 CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME;
70b7bc9c 75
a0a88f65 76 /** Path to the XML definitions file */
be222f56 77 protected static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME =
70b7bc9c 78 Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();
be222f56 79
cb1cf0e8
MK
80 /**
81 * Legacy path to the XML definitions file (in the UI plug-in) TODO Remove
82 * once we feel the transition phase is over.
83 */
03573754
AM
84 private static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY =
85 Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
86 .append("org.eclipse.linuxtools.tmf.ui") //$NON-NLS-1$
87 .append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();
88
332527a4 89 // TODO: These strings should not be externalized
be222f56
PT
90 private static final String CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomXmlTraceDefinition_definitionRootElement;
91 private static final String DEFINITION_ELEMENT = Messages.CustomXmlTraceDefinition_definition;
332527a4 92 private static final String CATEGORY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_category;
be222f56
PT
93 private static final String NAME_ATTRIBUTE = Messages.CustomXmlTraceDefinition_name;
94 private static final String LOG_ENTRY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_logEntry;
95 private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = Messages.CustomXmlTraceDefinition_timestampOutputFormat;
96 private static final String INPUT_ELEMENT_ELEMENT = Messages.CustomXmlTraceDefinition_inputElement;
97 private static final String ATTRIBUTE_ELEMENT = Messages.CustomXmlTraceDefinition_attribute;
98 private static final String INPUT_DATA_ELEMENT = Messages.CustomXmlTraceDefinition_inputData;
99 private static final String ACTION_ATTRIBUTE = Messages.CustomXmlTraceDefinition_action;
100 private static final String FORMAT_ATTRIBUTE = Messages.CustomXmlTraceDefinition_format;
101 private static final String OUTPUT_COLUMN_ELEMENT = Messages.CustomXmlTraceDefinition_outputColumn;
102
a0a88f65 103 /** Top-level input element */
a7418109 104 public CustomXmlInputElement rootInputElement;
be222f56 105
a0a88f65
AM
106 /**
107 * Default constructor
108 */
be222f56 109 public CustomXmlTraceDefinition() {
332527a4 110 this(TmfTraceType.CUSTOM_XML_CATEGORY, "", null, new ArrayList<OutputColumn>(), ""); //$NON-NLS-1$ //$NON-NLS-2$
be222f56
PT
111 }
112
a0a88f65
AM
113 /**
114 * Full constructor
115 *
332527a4
PT
116 * @param traceType
117 * Name of the trace type
a0a88f65
AM
118 * @param rootElement
119 * The top-level XML element
120 * @param outputs
121 * The list of output columns
122 * @param timeStampOutputFormat
123 * The timestamp format to use
a7418109
MK
124 * @deprecated Use
125 * {@link #CustomXmlTraceDefinition(String, String, CustomXmlInputElement, List, String)}
a0a88f65 126 */
332527a4 127 @Deprecated
a7418109 128 public CustomXmlTraceDefinition(String traceType, CustomXmlInputElement rootElement,
a0a88f65 129 List<OutputColumn> outputs, String timeStampOutputFormat) {
332527a4
PT
130 this.definitionName = traceType;
131 this.rootInputElement = rootElement;
132 this.outputs = outputs;
133 this.timeStampOutputFormat = timeStampOutputFormat;
134 }
135
136 /**
137 * Full constructor
138 *
139 * @param category
140 * Category of the trace type
141 * @param traceType
142 * Name of the trace type
143 * @param rootElement
144 * The top-level XML element
145 * @param outputs
146 * The list of output columns
147 * @param timeStampOutputFormat
148 * The timestamp format to use
a465519a 149 * @since 3.2
332527a4 150 */
a7418109 151 public CustomXmlTraceDefinition(String category, String traceType, CustomXmlInputElement rootElement,
332527a4
PT
152 List<OutputColumn> outputs, String timeStampOutputFormat) {
153 this.categoryName = category;
154 this.definitionName = traceType;
be222f56
PT
155 this.rootInputElement = rootElement;
156 this.outputs = outputs;
157 this.timeStampOutputFormat = timeStampOutputFormat;
158 }
159
a0a88f65 160 @Override
be222f56
PT
161 public void save() {
162 save(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
163 }
164
70b7bc9c 165 @Override
be222f56
PT
166 public void save(String path) {
167 try {
168 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
169 DocumentBuilder db = dbf.newDocumentBuilder();
170
171 // The following allows xml parsing without access to the dtd
cb1cf0e8 172 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
173
174 // The following catches xml parsing exceptions
cb1cf0e8 175 db.setErrorHandler(createErrorHandler());
be222f56
PT
176
177 Document doc = null;
178 File file = new File(path);
179 if (file.canRead()) {
180 doc = db.parse(file);
70b7bc9c 181 if (!doc.getDocumentElement().getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
182 return;
183 }
184 } else {
185 doc = db.newDocument();
186 Node node = doc.createElement(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT);
187 doc.appendChild(node);
188 }
189
190 Element root = doc.getDocumentElement();
191
332527a4
PT
192 Element oldDefinitionElement = findDefinitionElement(root, categoryName, definitionName);
193 if (oldDefinitionElement != null) {
194 root.removeChild(oldDefinitionElement);
be222f56
PT
195 }
196 Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
197 root.appendChild(definitionElement);
332527a4 198 definitionElement.setAttribute(CATEGORY_ATTRIBUTE, categoryName);
be222f56
PT
199 definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);
200
201 Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);
202 definitionElement.appendChild(formatElement);
203 formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));
204
205 if (rootInputElement != null) {
206 definitionElement.appendChild(createInputElementElement(rootInputElement, doc));
207 }
208
209 if (outputs != null) {
210 for (OutputColumn output : outputs) {
211 Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);
212 definitionElement.appendChild(outputColumnElement);
213 outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);
214 }
215 }
216
217 Transformer transformer = TransformerFactory.newInstance().newTransformer();
218 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
219
70b7bc9c 220 // initialize StreamResult with File object to save to file
be222f56
PT
221 StreamResult result = new StreamResult(new StringWriter());
222 DOMSource source = new DOMSource(doc);
223 transformer.transform(source, result);
224 String xmlString = result.getWriter().toString();
225
507b1336
AM
226 try (FileWriter writer = new FileWriter(file);) {
227 writer.write(xmlString);
228 }
52885aeb 229
4b3b667b 230 TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
52885aeb 231
cb1cf0e8 232 } catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException | IOException | SAXException e) {
47aafe74 233 Activator.logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56
PT
234 }
235 }
236
a7418109 237 private Element createInputElementElement(CustomXmlInputElement inputElement, Document doc) {
be222f56 238 Element inputElementElement = doc.createElement(INPUT_ELEMENT_ELEMENT);
a7418109 239 inputElementElement.setAttribute(NAME_ATTRIBUTE, inputElement.getElementName());
be222f56 240
a7418109
MK
241 if (inputElement.isLogEntry()) {
242 inputElementElement.setAttribute(LOG_ENTRY_ATTRIBUTE, Boolean.toString(inputElement.isLogEntry()));
be222f56
PT
243 }
244
a7418109 245 if (inputElement.getParentElement() != null) {
be222f56
PT
246 Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
247 inputElementElement.appendChild(inputDataElement);
a7418109
MK
248 inputDataElement.setAttribute(NAME_ATTRIBUTE, inputElement.getInputName());
249 inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputElement.getInputAction()));
250 if (inputElement.getInputFormat() != null) {
251 inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputElement.getInputFormat());
be222f56
PT
252 }
253 }
254
a7418109
MK
255 if (inputElement.getAttributes() != null) {
256 for (CustomXmlInputAttribute attribute : inputElement.getAttributes()) {
be222f56
PT
257 Element inputAttributeElement = doc.createElement(ATTRIBUTE_ELEMENT);
258 inputElementElement.appendChild(inputAttributeElement);
a7418109 259 inputAttributeElement.setAttribute(NAME_ATTRIBUTE, attribute.getAttributeName());
be222f56
PT
260 Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
261 inputAttributeElement.appendChild(inputDataElement);
a7418109
MK
262 inputDataElement.setAttribute(NAME_ATTRIBUTE, attribute.getInputName());
263 inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(attribute.getInputAction()));
264 if (attribute.getInputFormat() != null) {
265 inputDataElement.setAttribute(FORMAT_ATTRIBUTE, attribute.getInputFormat());
be222f56
PT
266 }
267 }
268 }
269
a7418109
MK
270 if (inputElement.getChildElements() != null) {
271 for (CustomXmlInputElement childInputElement : inputElement.getChildElements()) {
be222f56
PT
272 inputElementElement.appendChild(createInputElementElement(childInputElement, doc));
273 }
274 }
275
276 return inputElementElement;
277 }
278
a0a88f65 279 /**
54af96ab
PT
280 * Load all custom XML trace definitions, including the user-defined and
281 * default (built-in) parsers.
a0a88f65
AM
282 *
283 * @return The loaded trace definitions
284 */
be222f56 285 public static CustomXmlTraceDefinition[] loadAll() {
54af96ab
PT
286 return loadAll(true);
287 }
288
289 /**
290 * Load all custom XML trace definitions, including the user-defined and,
291 * optionally, the default (built-in) parsers.
292 *
293 * @param includeDefaults
294 * if true, the default (built-in) parsers are included
295 *
296 * @return The loaded trace definitions
a465519a 297 * @since 3.2
54af96ab
PT
298 */
299 public static CustomXmlTraceDefinition[] loadAll(boolean includeDefaults) {
03573754
AM
300 File defaultFile = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
301 File legacyFile = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY);
302
303 /*
304 * If there is no file at the expected location, check the legacy
305 * location instead.
306 */
307 if (!defaultFile.exists() && legacyFile.exists()) {
308 CustomXmlTraceDefinition[] oldDefs = loadAll(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY);
309 for (CustomXmlTraceDefinition def : oldDefs) {
310 /* Save in the new location */
311 def.save();
312 }
313 }
314
70b7bc9c 315 Set<CustomXmlTraceDefinition> defs = new TreeSet<>(new Comparator<CustomXmlTraceDefinition>() {
70b7bc9c
MK
316 @Override
317 public int compare(CustomXmlTraceDefinition o1, CustomXmlTraceDefinition o2) {
c22ca172
PT
318 int result = o1.categoryName.compareTo(o2.categoryName);
319 if (result != 0) {
320 return result;
321 }
70b7bc9c
MK
322 return o1.definitionName.compareTo(o2.definitionName);
323 }
324 });
325 defs.addAll(Arrays.asList(loadAll(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME)));
54af96ab
PT
326 if (includeDefaults) {
327 defs.addAll(Arrays.asList(loadAll(CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME)));
328 }
70b7bc9c 329 return defs.toArray(new CustomXmlTraceDefinition[0]);
be222f56
PT
330 }
331
a0a88f65
AM
332 /**
333 * Load all the XML trace definitions in the given definitions file.
334 *
335 * @param path
336 * Path to the definitions file to load
337 * @return The loaded trace definitions
338 */
be222f56 339 public static CustomXmlTraceDefinition[] loadAll(String path) {
1d8ab692
GB
340 File file = new File(path);
341 if (!file.canRead()) {
342 return new CustomXmlTraceDefinition[0];
343 }
344 try (FileInputStream fis = new FileInputStream(file);) {
345 return loadAll(fis);
346 } catch (IOException e) {
347 Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
348 }
349 return new CustomXmlTraceDefinition[0];
350 }
351
352 /**
353 * Load all the XML trace definitions from the given stream
354 *
355 * @param stream
356 * An input stream from which to read the definitions
357 * @return The loaded trace definitions
a465519a 358 * @since 3.2
1d8ab692
GB
359 */
360 public static CustomXmlTraceDefinition[] loadAll(InputStream stream) {
be222f56
PT
361 try {
362 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
363 DocumentBuilder db = dbf.newDocumentBuilder();
364
365 // The following allows xml parsing without access to the dtd
cb1cf0e8 366 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
367
368 // The following catches xml parsing exceptions
cb1cf0e8 369 db.setErrorHandler(createErrorHandler());
be222f56 370
1d8ab692 371 Document doc = db.parse(stream);
be222f56 372 Element root = doc.getDocumentElement();
70b7bc9c 373 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
374 return new CustomXmlTraceDefinition[0];
375 }
376
507b1336 377 ArrayList<CustomXmlTraceDefinition> defList = new ArrayList<>();
be222f56
PT
378 NodeList nodeList = root.getChildNodes();
379 for (int i = 0; i < nodeList.getLength(); i++) {
380 Node node = nodeList.item(i);
381 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
382 CustomXmlTraceDefinition def = extractDefinition((Element) node);
383 if (def != null) {
384 defList.add(def);
385 }
386 }
387 }
388 return defList.toArray(new CustomXmlTraceDefinition[0]);
cb1cf0e8 389 } catch (ParserConfigurationException | SAXException | IOException e) {
1d8ab692 390 Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + stream, e); //$NON-NLS-1$
be222f56
PT
391 }
392 return new CustomXmlTraceDefinition[0];
393 }
394
a0a88f65
AM
395 /**
396 * Load the given trace definition.
397 *
398 * @param definitionName
399 * Name of the XML trace definition to load
400 * @return The loaded trace definition
332527a4 401 * @deprecated Use {@link #load(String, String)}
a0a88f65 402 */
332527a4 403 @Deprecated
be222f56 404 public static CustomXmlTraceDefinition load(String definitionName) {
332527a4
PT
405 return load(TmfTraceType.CUSTOM_XML_CATEGORY, definitionName);
406 }
407
408 /**
409 * Load the given trace definition.
410 *
411 * @param categoryName
412 * Category of the definition to load
413 * @param definitionName
414 * Name of the XML trace definition to load
415 * @return The loaded trace definition
a465519a 416 * @since 3.2
332527a4
PT
417 */
418 public static CustomXmlTraceDefinition load(String categoryName, String definitionName) {
be222f56
PT
419 try {
420 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
421 DocumentBuilder db = dbf.newDocumentBuilder();
422
423 // The following allows xml parsing without access to the dtd
a0a88f65 424 EntityResolver resolver = new EntityResolver() {
be222f56 425 @Override
a0a88f65 426 public InputSource resolveEntity(String publicId, String systemId) {
be222f56
PT
427 String empty = ""; //$NON-NLS-1$
428 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
429 return new InputSource(bais);
430 }
431 };
432 db.setEntityResolver(resolver);
433
434 // The following catches xml parsing exceptions
a0a88f65 435 db.setErrorHandler(new ErrorHandler() {
be222f56 436 @Override
70b7bc9c
MK
437 public void error(SAXParseException saxparseexception) throws SAXException {
438 }
a0a88f65 439
be222f56 440 @Override
70b7bc9c
MK
441 public void warning(SAXParseException saxparseexception) throws SAXException {
442 }
a0a88f65 443
be222f56 444 @Override
a0a88f65 445 public void fatalError(SAXParseException saxparseexception) throws SAXException {
be222f56 446 throw saxparseexception;
a0a88f65
AM
447 }
448 });
be222f56 449
332527a4 450 CustomXmlTraceDefinition value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
70b7bc9c 451 if (value == null) {
332527a4 452 value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME);
be222f56 453 }
70b7bc9c 454 return value;
cb1cf0e8 455 } catch (ParserConfigurationException | SAXException | IOException e) {
47aafe74 456 Activator.logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
457 }
458 return null;
459 }
460
332527a4 461 private static CustomXmlTraceDefinition lookupXmlDefinition(String categoryName, String definitionName, DocumentBuilder db, String source) throws SAXException, IOException {
70b7bc9c
MK
462 File file = new File(source);
463 if (!file.exists()) {
464 return null;
465 }
466
467 Document doc = db.parse(file);
468
469 Element root = doc.getDocumentElement();
470 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
471 return null;
472 }
473
332527a4
PT
474 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
475 if (definitionElement != null) {
476 return extractDefinition(definitionElement);
477 }
478 return null;
479 }
480
481 private static Element findDefinitionElement(Element root, String categoryName, String definitionName) {
70b7bc9c
MK
482 NodeList nodeList = root.getChildNodes();
483 for (int i = 0; i < nodeList.getLength(); i++) {
484 Node node = nodeList.item(i);
332527a4
PT
485 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
486 Element element = (Element) node;
487 String categoryAttribute = element.getAttribute(CATEGORY_ATTRIBUTE);
488 if (categoryAttribute.isEmpty()) {
489 categoryAttribute = TmfTraceType.CUSTOM_XML_CATEGORY;
490 }
491 String nameAttribute = element.getAttribute(NAME_ATTRIBUTE);
492 if (categoryName.equals(categoryAttribute) &&
493 definitionName.equals(nameAttribute)) {
494 return element;
495 }
70b7bc9c
MK
496 }
497 }
498 return null;
499 }
500
a0a88f65
AM
501 /**
502 * Extract a trace definition from an XML element.
503 *
504 * @param definitionElement
505 * Definition element
506 * @return The extracted trace definition
507 */
be222f56
PT
508 public static CustomXmlTraceDefinition extractDefinition(Element definitionElement) {
509 CustomXmlTraceDefinition def = new CustomXmlTraceDefinition();
510
332527a4
PT
511 def.categoryName = definitionElement.getAttribute(CATEGORY_ATTRIBUTE);
512 if (def.categoryName.isEmpty()) {
513 def.categoryName = TmfTraceType.CUSTOM_XML_CATEGORY;
514 }
be222f56 515 def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
332527a4 516 if (def.definitionName.isEmpty()) {
be222f56
PT
517 return null;
518 }
519
520 NodeList nodeList = definitionElement.getChildNodes();
521 for (int i = 0; i < nodeList.getLength(); i++) {
522 Node node = nodeList.item(i);
523 String nodeName = node.getNodeName();
524 if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {
525 Element formatElement = (Element) node;
526 def.timeStampOutputFormat = formatElement.getTextContent();
527 } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {
a7418109 528 CustomXmlInputElement inputElement = extractInputElement((Element) node);
be222f56
PT
529 if (inputElement != null) {
530 if (def.rootInputElement == null) {
531 def.rootInputElement = inputElement;
532 } else {
533 return null;
534 }
535 }
536 } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {
537 Element outputColumnElement = (Element) node;
538 OutputColumn outputColumn = new OutputColumn();
539 outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE);
540 def.outputs.add(outputColumn);
541 }
542 }
543 return def;
544 }
545
a7418109
MK
546 private static CustomXmlInputElement extractInputElement(Element inputElementElement) {
547 CustomXmlInputElement inputElement = new CustomXmlInputElement();
548 inputElement.setElementName(inputElementElement.getAttribute(NAME_ATTRIBUTE));
549 inputElement.setLogEntry((Boolean.toString(true).equals(inputElementElement.getAttribute(LOG_ENTRY_ATTRIBUTE))) ? true : false);
be222f56
PT
550 NodeList nodeList = inputElementElement.getChildNodes();
551 for (int i = 0; i < nodeList.getLength(); i++) {
552 Node node = nodeList.item(i);
553 String nodeName = node.getNodeName();
554 if (nodeName.equals(INPUT_DATA_ELEMENT)) {
555 Element inputDataElement = (Element) node;
a7418109
MK
556 inputElement.setInputName(inputDataElement.getAttribute(NAME_ATTRIBUTE));
557 inputElement.setInputAction(Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE)));
558 inputElement.setInputFormat(inputDataElement.getAttribute(FORMAT_ATTRIBUTE));
be222f56
PT
559 } else if (nodeName.equals(ATTRIBUTE_ELEMENT)) {
560 Element attributeElement = (Element) node;
a7418109
MK
561
562 String attributeName = attributeElement.getAttribute(NAME_ATTRIBUTE);
563 String inputName = null;
564 int inputAction = 0;
565 String inputFormat = null;
be222f56
PT
566 NodeList attributeNodeList = attributeElement.getChildNodes();
567 for (int j = 0; j < attributeNodeList.getLength(); j++) {
568 Node attributeNode = attributeNodeList.item(j);
569 String attributeNodeName = attributeNode.getNodeName();
570 if (attributeNodeName.equals(INPUT_DATA_ELEMENT)) {
571 Element inputDataElement = (Element) attributeNode;
a7418109
MK
572 inputName = inputDataElement.getAttribute(NAME_ATTRIBUTE);
573 inputAction = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));
574 inputFormat = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);
be222f56
PT
575 }
576 }
a7418109 577 inputElement.addAttribute(new CustomXmlInputAttribute(attributeName, inputName, inputAction, inputFormat));
be222f56
PT
578 } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {
579 Element childInputElementElement = (Element) node;
a7418109 580 CustomXmlInputElement childInputElement = extractInputElement(childInputElementElement);
be222f56
PT
581 if (childInputElement != null) {
582 inputElement.addChild(childInputElement);
583 }
584 }
585 }
586 return inputElement;
587 }
588
a0a88f65 589 /**
332527a4 590 * Delete a definition from the currently loaded ones.
a0a88f65
AM
591 *
592 * @param definitionName
332527a4
PT
593 * The name of the definition to delete
594 * @deprecated Use {@link #delete(String, String)}
a0a88f65 595 */
332527a4 596 @Deprecated
be222f56 597 public static void delete(String definitionName) {
332527a4
PT
598 delete(TmfTraceType.CUSTOM_XML_CATEGORY, definitionName);
599 }
600
601 /**
602 * Delete a definition from the currently loaded ones.
603 *
604 * @param categoryName
605 * The category of the definition to delete
606 * @param definitionName
607 * The name of the definition to delete
a465519a 608 * @since 3.2
332527a4
PT
609 */
610 public static void delete(String categoryName, String definitionName) {
be222f56
PT
611 try {
612 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
613 DocumentBuilder db = dbf.newDocumentBuilder();
614
615 // The following allows xml parsing without access to the dtd
a0a88f65 616 EntityResolver resolver = new EntityResolver() {
be222f56 617 @Override
a0a88f65 618 public InputSource resolveEntity(String publicId, String systemId) {
be222f56
PT
619 String empty = ""; //$NON-NLS-1$
620 ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
621 return new InputSource(bais);
622 }
623 };
624 db.setEntityResolver(resolver);
625
626 // The following catches xml parsing exceptions
a0a88f65 627 db.setErrorHandler(new ErrorHandler() {
be222f56 628 @Override
70b7bc9c
MK
629 public void error(SAXParseException saxparseexception) throws SAXException {
630 }
a0a88f65 631
be222f56 632 @Override
70b7bc9c
MK
633 public void warning(SAXParseException saxparseexception) throws SAXException {
634 }
a0a88f65 635
be222f56 636 @Override
a0a88f65 637 public void fatalError(SAXParseException saxparseexception) throws SAXException {
be222f56 638 throw saxparseexception;
a0a88f65
AM
639 }
640 });
be222f56
PT
641
642 File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
643 Document doc = db.parse(file);
644
645 Element root = doc.getDocumentElement();
70b7bc9c 646 if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
647 return;
648 }
649
332527a4
PT
650 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
651 if (definitionElement != null) {
652 root.removeChild(definitionElement);
be222f56
PT
653 }
654
655 Transformer transformer = TransformerFactory.newInstance().newTransformer();
656 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
657
70b7bc9c 658 // initialize StreamResult with File object to save to file
be222f56
PT
659 StreamResult result = new StreamResult(new StringWriter());
660 DOMSource source = new DOMSource(doc);
661 transformer.transform(source, result);
662 String xmlString = result.getWriter().toString();
663
507b1336
AM
664 try (FileWriter writer = new FileWriter(file);) {
665 writer.write(xmlString);
666 }
52885aeb 667
4b3b667b 668 TmfTraceType.removeCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
0621dbae 669 // Check if default definition needs to be reloaded
4b3b667b 670 TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
52885aeb 671
cb1cf0e8 672 } catch (ParserConfigurationException | SAXException | IOException | TransformerFactoryConfigurationError | TransformerException e) {
47aafe74 673 Activator.logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
674 }
675 }
676}
This page took 0.09112 seconds and 5 git commands to generate.