tmf: lttngControl: mi: basic listing support
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.control.ui / src / org / eclipse / linuxtools / internal / lttng2 / control / ui / views / service / LTTngControlServiceMI.java
1 /**********************************************************************
2 * Copyright (c) 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 * Jonathan Rajotte - Initial support for machine interface lttng 2.6
11 **********************************************************************/
12
13 package org.eclipse.linuxtools.internal.lttng2.control.ui.views.service;
14
15 import java.io.IOException;
16 import java.io.StringReader;
17 import java.net.URL;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.regex.Matcher;
21
22 import javax.xml.parsers.DocumentBuilder;
23 import javax.xml.parsers.DocumentBuilderFactory;
24 import javax.xml.parsers.ParserConfigurationException;
25
26 import org.eclipse.core.commands.ExecutionException;
27 import org.eclipse.core.runtime.IProgressMonitor;
28 import org.eclipse.linuxtools.internal.lttng2.control.core.model.IBaseEventInfo;
29 import org.eclipse.linuxtools.internal.lttng2.control.core.model.IChannelInfo;
30 import org.eclipse.linuxtools.internal.lttng2.control.core.model.IDomainInfo;
31 import org.eclipse.linuxtools.internal.lttng2.control.core.model.IFieldInfo;
32 import org.eclipse.linuxtools.internal.lttng2.control.core.model.ISessionInfo;
33 import org.eclipse.linuxtools.internal.lttng2.control.core.model.ISnapshotInfo;
34 import org.eclipse.linuxtools.internal.lttng2.control.core.model.IUstProviderInfo;
35 import org.eclipse.linuxtools.internal.lttng2.control.core.model.LogLevelType;
36 import org.eclipse.linuxtools.internal.lttng2.control.core.model.TraceLogLevel;
37 import org.eclipse.linuxtools.internal.lttng2.control.core.model.impl.BaseEventInfo;
38 import org.eclipse.linuxtools.internal.lttng2.control.core.model.impl.FieldInfo;
39 import org.eclipse.linuxtools.internal.lttng2.control.core.model.impl.SessionInfo;
40 import org.eclipse.linuxtools.internal.lttng2.control.core.model.impl.SnapshotInfo;
41 import org.eclipse.linuxtools.internal.lttng2.control.core.model.impl.UstProviderInfo;
42 import org.eclipse.linuxtools.internal.lttng2.control.ui.views.handlers.XmlMiValidationErrorHandler;
43 import org.eclipse.linuxtools.internal.lttng2.control.ui.views.messages.Messages;
44 import org.eclipse.linuxtools.internal.lttng2.control.ui.views.remote.ICommandResult;
45 import org.eclipse.linuxtools.internal.lttng2.control.ui.views.remote.ICommandShell;
46 import org.w3c.dom.Document;
47 import org.w3c.dom.Node;
48 import org.w3c.dom.NodeList;
49 import org.xml.sax.InputSource;
50 import org.xml.sax.SAXException;
51
52 /**
53 * Service for sending LTTng trace control commands to remote host via machine
54 * interface mode.
55 *
56 * @author Jonathan Rajotte
57 */
58 public class LTTngControlServiceMI extends LTTngControlService {
59
60 // ------------------------------------------------------------------------
61 // Attributes
62 // ------------------------------------------------------------------------
63
64 private final DocumentBuilder fDocumentBuilder;
65
66 // ------------------------------------------------------------------------
67 // Constructors
68 // ------------------------------------------------------------------------
69
70 /**
71 * Constructor
72 *
73 * @param shell
74 * the command shell implementation to use
75 * @param xsdUrl
76 * the xsd schema file for validation
77 * @throws ExecutionException
78 * if the creation of the Schema and DocumentBuilder objects
79 * fails
80 */
81 public LTTngControlServiceMI(ICommandShell shell, URL xsdUrl) throws ExecutionException {
82 super(shell);
83
84 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
85 docBuilderFactory.setValidating(false);
86
87 // TODO: Add xsd validation for machine interface via mi_lttng.xsd from LTTng
88 try {
89 fDocumentBuilder = docBuilderFactory.newDocumentBuilder();
90 } catch (ParserConfigurationException e) {
91 throw new ExecutionException(Messages.TraceControl_XmlDocumentBuilderError, e);
92 }
93
94 fDocumentBuilder.setErrorHandler(new XmlMiValidationErrorHandler());
95
96 }
97
98 /**
99 * Generate a Document object from an array of String.
100 *
101 * @param xmlStrings
102 * array of strings representing an xml input
103 * @return Document generated from strings input
104 * @throws ExecutionException
105 * when parsing has failed
106 */
107 private Document getDocumentFromStrings(String[] xmlStrings) throws ExecutionException {
108 StringBuilder concatenedString = new StringBuilder();
109 for (String string : xmlStrings) {
110 concatenedString.append(string);
111 }
112 InputSource stream = new InputSource(new StringReader(concatenedString.toString()));
113
114 Document document;
115 try {
116 document = fDocumentBuilder.parse(stream);
117 } catch (SAXException | IOException e) {
118 throw new ExecutionException(Messages.TraceControl_XmlParsingError, e);
119 }
120 return document;
121
122 }
123
124 /**
125 * Parse, populate and set the internal LTTngVersion variable
126 *
127 * @param xmlOutput
128 * the mi xml output of lttng version
129 * @throws ExecutionException
130 * when xml extraction fail
131 */
132 public void setVersion(String[] xmlOutput) throws ExecutionException {
133 Document doc = getDocumentFromStrings(xmlOutput);
134 NodeList element = doc.getElementsByTagName(MIStrings.VERSION);
135 int major = 0;
136 int minor = 0;
137 int patchLevel = 0;
138 String license = ""; //$NON-NLS-1$
139 String commit = ""; //$NON-NLS-1$
140 String name = ""; //$NON-NLS-1$
141 String description = ""; //$NON-NLS-1$
142 String url = ""; //$NON-NLS-1$
143 String fullVersion = ""; //$NON-NLS-1$
144 if (element.getLength() == 1) {
145 NodeList child = element.item(0).getChildNodes();
146 // Get basic information
147 for (int i = 0; i < child.getLength(); i++) {
148 Node node = child.item(i);
149 switch (node.getNodeName()) {
150 case MIStrings.VERSION_MAJOR:
151 major = Integer.parseInt(node.getTextContent());
152 break;
153 case MIStrings.VERSION_MINOR:
154 minor = Integer.parseInt(node.getTextContent());
155 break;
156 case MIStrings.VERSION_PATCH_LEVEL:
157 patchLevel = Integer.parseInt(node.getTextContent());
158 break;
159 case MIStrings.VERSION_COMMIT:
160 commit = node.getTextContent();
161 break;
162 case MIStrings.VERSION_DESCRIPTION:
163 description = node.getTextContent();
164 break;
165 case MIStrings.VERSION_LICENSE:
166 license = node.getTextContent();
167 break;
168 case MIStrings.VERSION_NAME:
169 name = node.getTextContent();
170 break;
171 case MIStrings.VERSION_STR:
172 fullVersion = node.getTextContent();
173 break;
174 case MIStrings.VERSION_WEB:
175 url = node.getTextContent();
176 break;
177 default:
178 break;
179 }
180 }
181 setVersion(new LttngVersion(major, minor, patchLevel, license, commit, name, description, url, fullVersion));
182 } else {
183 throw new ExecutionException(Messages.TraceControl_UnsupportedVersionError);
184 }
185 }
186
187 @Override
188 public String[] getSessionNames(IProgressMonitor monitor) throws ExecutionException {
189 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_LIST);
190 ICommandResult result = executeCommand(command.toString(), monitor);
191
192 Document doc = getDocumentFromStrings(result.getOutput());
193
194 NodeList elements = doc.getElementsByTagName(MIStrings.NAME);
195
196 ArrayList<String> retArray = new ArrayList<>();
197 for (int i = 0; i < elements.getLength(); i++) {
198 Node node = elements.item(i);
199 if (node.getParentNode().getNodeName().equalsIgnoreCase(MIStrings.SESSION)) {
200 retArray.add(node.getTextContent());
201 }
202 }
203 return retArray.toArray(new String[retArray.size()]);
204 }
205
206 @Override
207 public ISessionInfo getSession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
208 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_LIST, sessionName);
209 ICommandResult result = executeCommand(command.toString(), monitor);
210
211 ISessionInfo sessionInfo = new SessionInfo(sessionName);
212 Document document = getDocumentFromStrings(result.getOutput());
213
214 NodeList sessionsNode = document.getElementsByTagName(MIStrings.SESSION);
215 // There should be only one session
216 if (sessionsNode.getLength() != 1) {
217 throw new ExecutionException(Messages.TraceControl_MiInvalidNumberOfElementError);
218 }
219
220 // Populate session information
221 NodeList rawSessionInfos = sessionsNode.item(0).getChildNodes();
222 for (int i = 0; i < rawSessionInfos.getLength(); i++) {
223 Node rawInfo = rawSessionInfos.item(i);
224 switch (rawInfo.getNodeName()) {
225 case MIStrings.PATH:
226 sessionInfo.setSessionPath(rawInfo.getTextContent());
227 break;
228 case MIStrings.ENABLED:
229 sessionInfo.setSessionState(rawInfo.getTextContent());
230 break;
231 case MIStrings.SNAPSHOT_MODE:
232 if (rawInfo.getTextContent().equals(LTTngControlServiceConstants.TRUE_NUMERICAL)) {
233 // real name will be set later
234 ISnapshotInfo snapshotInfo = new SnapshotInfo(""); //$NON-NLS-1$
235 sessionInfo.setSnapshotInfo(snapshotInfo);
236 }
237 break;
238 case MIStrings.LIVE_TIMER_INTERVAL:
239 // TODO : live mode not supported yet in TMF:lttng-control
240 break;
241 case MIStrings.DOMAINS:
242 // Extract the domains node
243 NodeList rawDomains = rawInfo.getChildNodes();
244 IDomainInfo domain = null;
245 for (int j = 0; j < rawDomains.getLength(); j++) {
246 if (rawDomains.item(j).getNodeName().equalsIgnoreCase(MIStrings.DOMAIN)) {
247 domain = parseDomain(rawDomains.item(j));
248 sessionInfo.addDomain(domain);
249 }
250 }
251 break;
252 default:
253 break;
254 }
255 }
256
257 if (!sessionInfo.isSnapshotSession()) {
258 Matcher matcher = LTTngControlServiceConstants.TRACE_NETWORK_PATTERN.matcher(sessionInfo.getSessionPath());
259 if (matcher.matches()) {
260 sessionInfo.setStreamedTrace(true);
261 }
262 }
263
264
265 // Fetch the snapshot info
266 if (sessionInfo.isSnapshotSession()) {
267 ISnapshotInfo snapshot = getSnapshotInfo(sessionName, monitor);
268 sessionInfo.setSnapshotInfo(snapshot);
269 }
270
271 return sessionInfo;
272 }
273
274 /**
275 * @param domain
276 * a domain xml node
277 * @return {@link IDomainInfo}
278 */
279 protected IDomainInfo parseDomain(Node domain) {
280 // TODO JRJ - STUB
281 return null;
282 }
283
284 @Override
285 public ISnapshotInfo getSnapshotInfo(String sessionName, IProgressMonitor monitor) throws ExecutionException {
286 // TODO JRJ - STUB
287 return null;
288 }
289
290 @Override
291 public List<IBaseEventInfo> getKernelProvider(IProgressMonitor monitor) throws ExecutionException {
292 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_LIST_KERNEL);
293 ICommandResult result = executeCommand(command.toString(), monitor, false);
294 List<IBaseEventInfo> events = new ArrayList<>();
295
296 if (isError(result)) {
297 return events;
298 }
299
300 Document document = getDocumentFromStrings(result.getOutput());
301 NodeList rawEvents = document.getElementsByTagName(MIStrings.EVENT);
302 parseXmlEvents(rawEvents, events);
303 return events;
304 }
305
306 @Override
307 public List<IUstProviderInfo> getUstProvider(IProgressMonitor monitor) throws ExecutionException {
308 StringBuffer command = createCommand(LTTngControlServiceConstants.COMMAND_LIST_UST);
309 // Get the field to
310 command.append(LTTngControlServiceConstants.OPTION_FIELDS);
311
312 // Execute
313 ICommandResult result = executeCommand(command.toString(), monitor, false);
314 List<IUstProviderInfo> allProviders = new ArrayList<>();
315
316 if (isError(result)) {
317 return allProviders;
318 }
319
320 Document document = getDocumentFromStrings(result.getOutput());
321 NodeList rawProviders = document.getElementsByTagName(MIStrings.PID);
322
323 IUstProviderInfo providerInfo = null;
324
325 for (int i = 0; i < rawProviders.getLength(); i++) {
326 Node provider = rawProviders.item(i);
327 Node name = getFirstOf(provider.getChildNodes(), MIStrings.NAME);
328 if (name == null) {
329 throw new ExecutionException(Messages.TraceControl_MiInvalidProviderError);
330 }
331 providerInfo = new UstProviderInfo(name.getTextContent());
332
333 // Populate provider
334 NodeList infos = provider.getChildNodes();
335 for (int j = 0; j < infos.getLength(); j++) {
336 Node info = infos.item(j);
337 switch (info.getNodeName()) {
338 case MIStrings.PID_ID:
339 providerInfo.setPid(Integer.parseInt(info.getTextContent()));
340 break;
341 case MIStrings.EVENTS:
342 List<IBaseEventInfo> events = new ArrayList<>();
343 NodeList rawEvents = info.getChildNodes();
344 parseXmlEvents(rawEvents, events);
345 providerInfo.setEvents(events);
346 break;
347 default:
348 break;
349 }
350 }
351 allProviders.add(providerInfo);
352 }
353
354 return allProviders;
355 }
356
357 @Override
358 public ISessionInfo createSession(ISessionInfo sessionInfo, IProgressMonitor monitor) throws ExecutionException {
359 // TODO Auto-generated method stub
360 return null;
361 }
362
363 @Override
364 public void destroySession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
365 // TODO Auto-generated method stub
366
367 }
368
369 @Override
370 public void startSession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
371 // TODO Auto-generated method stub
372
373 }
374
375 @Override
376 public void stopSession(String sessionName, IProgressMonitor monitor) throws ExecutionException {
377 // TODO Auto-generated method stub
378
379 }
380
381 @Override
382 public void enableChannels(String sessionName, List<String> channelNames, boolean isKernel, IChannelInfo info, IProgressMonitor monitor) throws ExecutionException {
383 // TODO Auto-generated method stub
384
385 }
386
387 @Override
388 public void disableChannels(String sessionName, List<String> channelNames, boolean isKernel, IProgressMonitor monitor) throws ExecutionException {
389 // TODO Auto-generated method stub
390
391 }
392
393 @Override
394 public void enableEvents(String sessionName, String channelName, List<String> eventNames, boolean isKernel, String filterExpression, IProgressMonitor monitor) throws ExecutionException {
395 // TODO Auto-generated method stub
396
397 }
398
399 @Override
400 public void enableSyscalls(String sessionName, String channelName, IProgressMonitor monitor) throws ExecutionException {
401 // TODO Auto-generated method stub
402
403 }
404
405 @Override
406 public void enableProbe(String sessionName, String channelName, String eventName, boolean isFunction, String probe, IProgressMonitor monitor) throws ExecutionException {
407 // TODO Auto-generated method stub
408
409 }
410
411 @Override
412 public void enableLogLevel(String sessionName, String channelName, String eventName, LogLevelType logLevelType, TraceLogLevel level, String filterExpression, IProgressMonitor monitor) throws ExecutionException {
413 // TODO Auto-generated method stub
414
415 }
416
417 @Override
418 public void disableEvent(String sessionName, String channelName, List<String> eventNames, boolean isKernel, IProgressMonitor monitor) throws ExecutionException {
419 // TODO Auto-generated method stub
420
421 }
422
423 @Override
424 public List<String> getContextList(IProgressMonitor monitor) throws ExecutionException {
425 // TODO Auto-generated method stub
426 return null;
427 }
428
429 @Override
430 public void addContexts(String sessionName, String channelName, String eventName, boolean isKernel, List<String> contexts, IProgressMonitor monitor) throws ExecutionException {
431 // TODO Auto-generated method stub
432
433 }
434
435 @Override
436 public void calibrate(boolean isKernel, IProgressMonitor monitor) throws ExecutionException {
437 // TODO Auto-generated method stub
438
439 }
440
441 @Override
442 public void recordSnapshot(String sessionName, IProgressMonitor monitor) throws ExecutionException {
443 // TODO Auto-generated method stub
444
445 }
446
447 @Override
448 public void runCommands(IProgressMonitor monitor, List<String> commands) throws ExecutionException {
449 // TODO Auto-generated method stub
450
451 }
452
453 /**
454 * @param strings
455 * array of string that make up a command line
456 * @return string buffer with created command line
457 */
458 @Override
459 protected StringBuffer createCommand(String... strings) {
460 StringBuffer command = new StringBuffer();
461 command.append(LTTngControlServiceConstants.CONTROL_COMMAND_MI_XML);
462 command.append(getTracingGroupOption());
463 for (String string : strings) {
464 command.append(string);
465 }
466 return command;
467 }
468
469 /**
470 * @param xmlEvents
471 * a Node list of xml event element
472 * @param events
473 * list of event generated by the parsing of the xml event
474 * element
475 * @throws ExecutionException
476 * when a raw event is not a complete/valid xml event
477 */
478 protected void parseXmlEvents(NodeList xmlEvents, List<IBaseEventInfo> events) throws ExecutionException {
479 IBaseEventInfo eventInfo = null;
480 for (int i = 0; i < xmlEvents.getLength(); i++) {
481 NodeList rawInfos = xmlEvents.item(i).getChildNodes();
482 // Search for name
483 if (xmlEvents.item(i).getNodeName().equalsIgnoreCase(MIStrings.EVENT)) {
484 Node rawName = getFirstOf(rawInfos, MIStrings.NAME);
485 if (rawName == null) {
486 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
487 }
488 eventInfo = new BaseEventInfo(rawName.getTextContent());
489
490 // Populate the event
491 for (int j = 0; j < rawInfos.getLength(); j++) {
492 Node infoNode = rawInfos.item(j);
493 switch (infoNode.getNodeName()) {
494 case MIStrings.TYPE:
495 eventInfo.setEventType(infoNode.getTextContent());
496 break;
497 case MIStrings.LOGLEVEL:
498 eventInfo.setLogLevel(infoNode.getTextContent());
499 break;
500 case MIStrings.EVENT_FIELDS:
501 List<IFieldInfo> fields = new ArrayList<>();
502 getFieldInfo(infoNode.getChildNodes(), fields);
503 eventInfo.setFields(fields);
504 break;
505 default:
506 break;
507 }
508 }
509 events.add(eventInfo);
510 }
511 }
512 }
513
514 /**
515 * @param fieldsList
516 * a list of xml event_field element
517 * @param fields
518 * a list of field generated by xml parsing
519 * @throws ExecutionException
520 * when parsing fail or required elements are missing
521 */
522 private static void getFieldInfo(NodeList fieldsList, List<IFieldInfo> fields) throws ExecutionException {
523 IFieldInfo fieldInfo = null;
524 for (int i = 0; i < fieldsList.getLength(); i++) {
525 Node field = fieldsList.item(i);
526 if (field.getNodeName().equalsIgnoreCase(MIStrings.EVENT_FIELD)) {
527 // Get name
528 Node name = getFirstOf(field.getChildNodes(), MIStrings.NAME);
529 if (name == null) {
530 throw new ExecutionException(Messages.TraceControl_MiMissingRequiredError);
531 }
532 fieldInfo = new FieldInfo(name.getTextContent());
533
534 // Populate the field information
535 NodeList infos = field.getChildNodes();
536 for (int j = 0; j < infos.getLength(); j++) {
537 Node info = infos.item(j);
538 switch (info.getNodeName()) {
539 case MIStrings.TYPE:
540 fieldInfo.setFieldType(info.getTextContent());
541 break;
542 default:
543 break;
544 }
545 }
546 fields.add(fieldInfo);
547 }
548 }
549 }
550
551 /**
552 * Retrieve the fist instance of a given node with tag name equal to tagName
553 * parameter
554 *
555 * @param nodeList
556 * the list of Node to search against
557 * @param tagName
558 * the tag name of the desired node
559 * @return the first occurrence of a node with a tag name equals to tagName
560 */
561 private static Node getFirstOf(NodeList nodeList, String tagName) {
562 Node node = null;
563 for (int i = 0; i < nodeList.getLength(); i++) {
564 if (nodeList.item(i).getNodeName() == tagName) {
565 node = nodeList.item(i);
566 break;
567 }
568 }
569 return node;
570 }
571
572 }
This page took 0.075133 seconds and 5 git commands to generate.