1 /**********************************************************************
2 * Copyright (c) 2012, 2015 Ericsson
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
10 * Bernd Hufmann - Initial API and implementation
11 * Markus Schorn - Bug 448058: Use org.eclipse.remote in favor of RSE
12 **********************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.lttng2
.control
.stubs
.shells
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import java
.io
.BufferedReader
;
18 import java
.io
.DataInputStream
;
19 import java
.io
.FileInputStream
;
20 import java
.io
.IOException
;
21 import java
.io
.InputStreamReader
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Collection
;
24 import java
.util
.HashMap
;
25 import java
.util
.Iterator
;
26 import java
.util
.List
;
28 import java
.util
.regex
.Matcher
;
29 import java
.util
.regex
.Pattern
;
31 import org
.eclipse
.core
.commands
.ExecutionException
;
32 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
33 import org
.eclipse
.jdt
.annotation
.NonNull
;
34 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.core
.stubs
.shells
.TestCommandShell
;
35 import org
.eclipse
.tracecompass
.tmf
.remote
.core
.shell
.ICommandInput
;
36 import org
.eclipse
.tracecompass
.tmf
.remote
.core
.shell
.ICommandOutputListener
;
37 import org
.eclipse
.tracecompass
.tmf
.remote
.core
.shell
.ICommandResult
;
39 @SuppressWarnings("javadoc")
40 public class LTTngToolsFileShell
extends TestCommandShell
{
42 // ------------------------------------------------------------------------
44 // ------------------------------------------------------------------------
45 private final static String SCENARIO_KEY
= "<SCENARIO>";
46 private final static String SCENARIO_END_KEY
= "</SCENARIO>";
47 private final static String INPUT_KEY
= "<COMMAND_INPUT>";
48 private final static String INPUT_END_KEY
= "</COMMAND_INPUT>";
49 private final static String RESULT_KEY
= "<COMMAND_RESULT>";
50 private final static String OUTPUT_KEY
= "<COMMAND_OUTPUT>";
51 private final static String OUTPUT_END_KEY
= "</COMMAND_OUTPUT>";
52 private final static String ERROR_OUTPUT_KEY
= "<COMMAND_ERROR_OUTPUT>";
53 private final static String ERROR_OUTPUT_END_KEY
= "</COMMAND_ERROR_OUTPUT>";
54 private final static String COMMENT_KEY
= "#.*";
56 private final static Pattern LTTNG_LIST_SESSION_PATTERN
= Pattern
.compile("lttng\\s+list\\s+(.+)");
57 private final static String LTTNG_LIST_PROVIDER_PATTERN
= "lttng\\s+list\\s+(-u|-k)";
59 private final static Pattern LTTNG_LIST_SESSION_MI_PATTERN
= Pattern
.compile("lttng\\s+--mi xml\\s+list\\s+(.+)");
60 private final static String LTTNG_LIST_PROVIDER_MI_PATTERN
= "lttng\\s+--mi xml\\s+list\\s+(-u|-k)";
62 // ------------------------------------------------------------------------
64 // ------------------------------------------------------------------------
65 private String fScenariofile
;
66 private String fScenario
;
68 private final Map
<String
, Map
<String
, ICommandResult
>> fScenarioMap
= new HashMap
<>();
69 private final Map
<String
, Integer
> fSessionNameMap
= new HashMap
<>();
72 * Parse a scenario file with the format:
78 * <COMMAND_INPUT>
80 * </COMMAND_INPUT>
82 * <COMMAND_RESULT>
84 * </COMMAND_RESULT>
86 * <COMMAND_OUTPUT>
88 * <COMMAND_ERROR_OUTPUT>
90 * </COMMAND_ERROR_OUTPUT>
91 * </COMMAND_OUTPUT>
95 * Where: ScenarioName - is the scenario name
96 * Command - the command line string
97 * CommandResult - the result integer of the command (0 for success, 1 for failure)
98 * CommandOutput - the command output string (multi-line possible)
99 * CommandErrorOutput - the command error output string (multi-line possible)
101 * Note: 1) There can be many scenarios per file
102 * 2) There can be many (Command-CommandResult-CommandOutput) triples per scenario
103 * 3) Lines starting with # will be ignored (comments)
106 * @param scenariofile - path to scenario file
108 public synchronized void loadScenarioFile(String scenariofile
) {
109 fScenariofile
= scenariofile
;
112 Collection
<Map
<String
, ICommandResult
>> values
= fScenarioMap
.values();
113 for (Iterator
<Map
<String
, ICommandResult
>> iterator
= values
.iterator(); iterator
.hasNext();) {
114 Map
<String
, ICommandResult
> map
= iterator
.next();
117 fScenarioMap
.clear();
122 try (FileInputStream fstream
= new FileInputStream(fScenariofile
);
123 DataInputStream in
= new DataInputStream(fstream
);
124 BufferedReader br
= new BufferedReader(new InputStreamReader(in
));) {
127 // Read File Line by Line
129 // Temporary map for generating instance numbers for lttng list
130 // <session> commands.
131 // The numbers are per scenario.
132 Map
<String
, Integer
> tmpSessionNameMap
= new HashMap
<>();
133 while ((strLine
= br
.readLine()) != null) {
136 if (isComment(strLine
)) {
140 if (SCENARIO_KEY
.equals(strLine
)) {
144 strLine
= br
.readLine();
145 while (isComment(strLine
)) {
146 strLine
= br
.readLine();
149 String scenario
= strLine
;
150 Map
<String
, ICommandResult
> commandMap
= new HashMap
<>();
151 fScenarioMap
.put(scenario
, commandMap
);
152 List
<String
> output
= null;
153 List
<String
> errorOutput
= null;
155 boolean inOutput
= false;
156 boolean inErrorOutput
= false;
158 tmpSessionNameMap
.clear();
159 while ((strLine
= br
.readLine()) != null) {
161 if (isComment(strLine
)) {
165 if (SCENARIO_END_KEY
.equals(strLine
)) {
166 // Scenario is finished
169 if (INPUT_KEY
.equals(strLine
)) {
170 strLine
= br
.readLine();
172 while (isComment(strLine
)) {
173 strLine
= br
.readLine();
178 // Handle instances of 'lttng list
180 Matcher matcher
= LTTNG_LIST_SESSION_PATTERN
.matcher(strLine
);
181 Matcher miMatcher
= LTTNG_LIST_SESSION_MI_PATTERN
.matcher(strLine
);
182 if (matcher
.matches() && !input
.matches(LTTNG_LIST_PROVIDER_PATTERN
)) {
183 String sessionName
= matcher
.group(1).trim();
184 input
+= updateSessionMap(tmpSessionNameMap
, input
, sessionName
);
185 } else if (miMatcher
.matches() && !input
.matches(LTTNG_LIST_PROVIDER_MI_PATTERN
)) {
186 String sessionName
= miMatcher
.group(1).trim();
187 input
+= updateSessionMap(tmpSessionNameMap
, input
, sessionName
);
189 } else if (INPUT_END_KEY
.equals(strLine
)) {
190 // Initialize output array
191 output
= new ArrayList
<>();
192 errorOutput
= new ArrayList
<>();
193 } else if (RESULT_KEY
.equals(strLine
)) {
194 strLine
= br
.readLine();
196 while (isComment(strLine
)) {
197 strLine
= br
.readLine();
200 result
= Integer
.parseInt(strLine
);
201 } else if (OUTPUT_END_KEY
.equals(strLine
)) {
202 // Save output/result in command map
203 if (output
!= null && errorOutput
!= null) {
204 commandMap
.put(input
, createCommandResult(result
,
205 checkNotNull(output
.toArray(new @NonNull String
[output
.size()])),
206 checkNotNull(errorOutput
.toArray(new @NonNull String
[errorOutput
.size()]))));
209 } else if (OUTPUT_KEY
.equals(strLine
)) {
210 // first line of output
212 } else if (ERROR_OUTPUT_KEY
.equals(strLine
)) {
213 // first line of output
214 inErrorOutput
= true;
215 } else if (ERROR_OUTPUT_END_KEY
.equals(strLine
)) {
216 inErrorOutput
= false;
217 } else if (inOutput
) {
218 while (isComment(strLine
)) {
219 strLine
= br
.readLine();
221 // lines of output/error output
222 if (errorOutput
!= null && inErrorOutput
) {
223 errorOutput
.add(strLine
);
224 } else if (output
!= null) {
229 // if (RESULT_END_KEY.equals(strLine)) {
235 } catch (IOException e
) {
240 private static String
updateSessionMap(Map
<String
, Integer
> tmpSessionNameMap
, String input
, String sessionName
) {
241 Integer i
= tmpSessionNameMap
.get(sessionName
);
247 tmpSessionNameMap
.put(sessionName
, i
);
248 return String
.valueOf(i
);
251 // Set the scenario to consider in executeCommand()
252 public synchronized void setScenario(String scenario
) {
253 fScenario
= scenario
;
254 fSessionNameMap
.clear();
255 if (!fScenarioMap
.containsKey(fScenario
)) {
256 throw new IllegalArgumentException();
261 public synchronized ICommandResult
executeCommand(ICommandInput command
, IProgressMonitor monitor
) throws ExecutionException
{
262 return executeCommand(command
, monitor
, null);
266 public synchronized ICommandResult
executeCommand(ICommandInput command
, IProgressMonitor monitor
, ICommandOutputListener listener
) throws ExecutionException
{
267 Map
<String
, ICommandResult
> commands
= checkNotNull(fScenarioMap
.get(fScenario
));
268 String commandLine
= command
.toString();
269 String fullCommand
= commandLine
;
271 Matcher matcher
= LTTNG_LIST_SESSION_PATTERN
.matcher(commandLine
);
272 Matcher miMatcher
= LTTNG_LIST_SESSION_MI_PATTERN
.matcher(commandLine
);
273 if (matcher
.matches() && !commandLine
.matches(LTTNG_LIST_PROVIDER_PATTERN
)) {
274 String sessionName
= matcher
.group(1).trim();
275 fullCommand
+= updateSessionMap(fSessionNameMap
, fullCommand
, sessionName
);
276 } else if (miMatcher
.matches() && !commandLine
.matches(LTTNG_LIST_PROVIDER_MI_PATTERN
)) {
277 String sessionName
= miMatcher
.group(1).trim();
278 fullCommand
+= updateSessionMap(fSessionNameMap
, fullCommand
, sessionName
);
281 if (commands
.containsKey(fullCommand
)) {
282 return checkNotNull(commands
.get(fullCommand
));
285 @NonNull String
[] output
= new @NonNull String
[1];
286 output
[0] = String
.valueOf("Command not found");
287 ICommandResult result
= createCommandResult(1, output
, output
);
291 // ------------------------------------------------------------------------
293 // ------------------------------------------------------------------------
295 private static boolean isComment(String line
) {
297 throw new RuntimeException("line is null");
299 return line
.matches(COMMENT_KEY
);