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