Commit | Line | Data |
---|---|---|
d132bcc7 | 1 | /********************************************************************** |
ed902a2b | 2 | * Copyright (c) 2012, 2015 Ericsson |
cfdb727a | 3 | * |
d132bcc7 BH |
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 | |
cfdb727a AM |
8 | * |
9 | * Contributors: | |
d132bcc7 | 10 | * Bernd Hufmann - Initial API and implementation |
b732adaa | 11 | * Markus Schorn - Bug 448058: Use org.eclipse.remote in favor of RSE |
d132bcc7 | 12 | **********************************************************************/ |
9bc60be7 | 13 | package org.eclipse.tracecompass.internal.lttng2.control.stubs.shells; |
d132bcc7 | 14 | |
13729cbc BH |
15 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
16 | ||
d132bcc7 BH |
17 | import java.io.BufferedReader; |
18 | import java.io.DataInputStream; | |
19 | import java.io.FileInputStream; | |
13729cbc | 20 | import java.io.IOException; |
d132bcc7 BH |
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; | |
27 | import java.util.Map; | |
28 | import java.util.regex.Matcher; | |
29 | import java.util.regex.Pattern; | |
30 | ||
31 | import org.eclipse.core.commands.ExecutionException; | |
32 | import org.eclipse.core.runtime.IProgressMonitor; | |
aa353506 | 33 | import org.eclipse.jdt.annotation.NonNull; |
1d6a2139 | 34 | import org.eclipse.tracecompass.internal.tmf.remote.core.stubs.shells.TestCommandShell; |
364dcfaf | 35 | import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandInput; |
90700072 | 36 | import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandOutputListener; |
ec619615 | 37 | import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandResult; |
d132bcc7 | 38 | |
cfdb727a | 39 | @SuppressWarnings("javadoc") |
d132bcc7 BH |
40 | public class LTTngToolsFileShell extends TestCommandShell { |
41 | ||
42 | // ------------------------------------------------------------------------ | |
43 | // CONSTANTS | |
44 | // ------------------------------------------------------------------------ | |
4e0b52e0 AM |
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>"; | |
4e0b52e0 AM |
50 | private final static String OUTPUT_KEY = "<COMMAND_OUTPUT>"; |
51 | private final static String OUTPUT_END_KEY = "</COMMAND_OUTPUT>"; | |
6418ef54 JRJ |
52 | private final static String ERROR_OUTPUT_KEY = "<COMMAND_ERROR_OUTPUT>"; |
53 | private final static String ERROR_OUTPUT_END_KEY = "</COMMAND_ERROR_OUTPUT>"; | |
4e0b52e0 | 54 | private final static String COMMENT_KEY = "#.*"; |
cfdb727a | 55 | |
774a7993 | 56 | private final static Pattern LTTNG_LIST_SESSION_PATTERN = Pattern.compile("lttng\\s+list\\s+(.+)"); |
4e0b52e0 | 57 | private final static String LTTNG_LIST_PROVIDER_PATTERN = "lttng\\s+list\\s+(-u|-k)"; |
d132bcc7 | 58 | |
2e65d221 BH |
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)"; | |
61 | ||
d132bcc7 BH |
62 | // ------------------------------------------------------------------------ |
63 | // Attributes | |
64 | // ------------------------------------------------------------------------ | |
65 | private String fScenariofile; | |
66 | private String fScenario; | |
67 | ||
e0838ca1 AM |
68 | private final Map<String, Map<String, ICommandResult>> fScenarioMap = new HashMap<>(); |
69 | private final Map<String, Integer> fSessionNameMap = new HashMap<>(); | |
d132bcc7 BH |
70 | |
71 | /** | |
72 | * Parse a scenario file with the format: | |
774a7993 | 73 | * |
6418ef54 JRJ |
74 | * <pre> |
75 | * <SCENARIO> | |
d132bcc7 | 76 | * ScenarioName |
cfdb727a | 77 | * |
6418ef54 | 78 | * <COMMAND_INPUT> |
d132bcc7 | 79 | * Command |
4888aef9 | 80 | * </COMMAND_INPUT> |
cfdb727a | 81 | * |
6418ef54 | 82 | * <COMMAND_RESULT> |
d132bcc7 | 83 | * CommandResult |
6418ef54 | 84 | * </COMMAND_RESULT> |
cfdb727a | 85 | * |
6418ef54 | 86 | * <COMMAND_OUTPUT> |
d132bcc7 | 87 | * CommandOutput |
6418ef54 JRJ |
88 | * <COMMAND_ERROR_OUTPUT> |
89 | * CommandErrorOutput | |
90 | * </COMMAND_ERROR_OUTPUT> | |
91 | * </COMMAND_OUTPUT> | |
cfdb727a | 92 | * |
6418ef54 | 93 | * </SCENARIO> |
cfdb727a | 94 | * |
d132bcc7 BH |
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) | |
4888aef9 MAL |
98 | * CommandOutput - the command output string (multi-line possible) |
99 | * CommandErrorOutput - the command error output string (multi-line possible) | |
cfdb727a | 100 | * |
d132bcc7 BH |
101 | * Note: 1) There can be many scenarios per file |
102 | * 2) There can be many (Command-CommandResult-CommandOutput) triples per scenario | |
774a7993 BH |
103 | * 3) Lines starting with # will be ignored (comments) |
104 | * | |
6418ef54 | 105 | * <pre> |
d132bcc7 | 106 | * @param scenariofile - path to scenario file |
d132bcc7 | 107 | */ |
13729cbc | 108 | public synchronized void loadScenarioFile(String scenariofile) { |
d132bcc7 | 109 | fScenariofile = scenariofile; |
cfdb727a | 110 | |
d132bcc7 BH |
111 | // clean up map |
112 | Collection<Map<String, ICommandResult>> values = fScenarioMap.values(); | |
113 | for (Iterator<Map<String, ICommandResult>> iterator = values.iterator(); iterator.hasNext();) { | |
cfdb727a | 114 | Map<String, ICommandResult> map = iterator.next(); |
d132bcc7 BH |
115 | map.clear(); |
116 | } | |
117 | fScenarioMap.clear(); | |
cfdb727a | 118 | |
d132bcc7 | 119 | // load from file |
cfdb727a | 120 | |
d132bcc7 | 121 | // Open the file |
e0838ca1 AM |
122 | try (FileInputStream fstream = new FileInputStream(fScenariofile); |
123 | DataInputStream in = new DataInputStream(fstream); | |
124 | BufferedReader br = new BufferedReader(new InputStreamReader(in));) { | |
125 | String strLine; | |
cfdb727a | 126 | |
e0838ca1 | 127 | // Read File Line by Line |
cfdb727a | 128 | |
e0838ca1 AM |
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) { | |
d132bcc7 BH |
134 | |
135 | // Ignore comments | |
e0838ca1 AM |
136 | if (isComment(strLine)) { |
137 | continue; | |
d132bcc7 BH |
138 | } |
139 | ||
e0838ca1 AM |
140 | if (SCENARIO_KEY.equals(strLine)) { |
141 | // scenario start | |
142 | ||
cfdb727a | 143 | // Ignore comments |
e0838ca1 AM |
144 | strLine = br.readLine(); |
145 | while (isComment(strLine)) { | |
146 | strLine = br.readLine(); | |
d132bcc7 BH |
147 | } |
148 | ||
e0838ca1 AM |
149 | String scenario = strLine; |
150 | Map<String, ICommandResult> commandMap = new HashMap<>(); | |
151 | fScenarioMap.put(scenario, commandMap); | |
152 | List<String> output = null; | |
6418ef54 | 153 | List<String> errorOutput = null; |
e0838ca1 AM |
154 | String input = null; |
155 | boolean inOutput = false; | |
6418ef54 | 156 | boolean inErrorOutput = false; |
e0838ca1 AM |
157 | int result = 0; |
158 | tmpSessionNameMap.clear(); | |
159 | while ((strLine = br.readLine()) != null) { | |
d132bcc7 | 160 | // Ignore comments |
e0838ca1 AM |
161 | if (isComment(strLine)) { |
162 | continue; | |
d132bcc7 | 163 | } |
e0838ca1 AM |
164 | |
165 | if (SCENARIO_END_KEY.equals(strLine)) { | |
166 | // Scenario is finished | |
167 | break; | |
d132bcc7 | 168 | } |
e0838ca1 | 169 | if (INPUT_KEY.equals(strLine)) { |
d132bcc7 | 170 | strLine = br.readLine(); |
e0838ca1 AM |
171 | // Ignore comments |
172 | while (isComment(strLine)) { | |
173 | strLine = br.readLine(); | |
174 | } | |
175 | // Read command | |
176 | input = strLine; | |
177 | ||
178 | // Handle instances of 'lttng list | |
4888aef9 | 179 | // <session"-command |
e0838ca1 | 180 | Matcher matcher = LTTNG_LIST_SESSION_PATTERN.matcher(strLine); |
2e65d221 | 181 | Matcher miMatcher = LTTNG_LIST_SESSION_MI_PATTERN.matcher(strLine); |
e0838ca1 AM |
182 | if (matcher.matches() && !input.matches(LTTNG_LIST_PROVIDER_PATTERN)) { |
183 | String sessionName = matcher.group(1).trim(); | |
2e65d221 BH |
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); | |
e0838ca1 AM |
188 | } |
189 | } else if (INPUT_END_KEY.equals(strLine)) { | |
190 | // Initialize output array | |
191 | output = new ArrayList<>(); | |
6418ef54 | 192 | errorOutput = new ArrayList<>(); |
e0838ca1 | 193 | } else if (RESULT_KEY.equals(strLine)) { |
d132bcc7 | 194 | strLine = br.readLine(); |
e0838ca1 AM |
195 | // Ignore comments |
196 | while (isComment(strLine)) { | |
197 | strLine = br.readLine(); | |
198 | } | |
199 | // Save result value | |
200 | result = Integer.parseInt(strLine); | |
201 | } else if (OUTPUT_END_KEY.equals(strLine)) { | |
202 | // Save output/result in command map | |
6418ef54 | 203 | if (output != null && errorOutput != null) { |
1d6a2139 | 204 | commandMap.put(input, createCommandResult(result, |
aa353506 AM |
205 | checkNotNull(output.toArray(new @NonNull String[output.size()])), |
206 | checkNotNull(errorOutput.toArray(new @NonNull String[errorOutput.size()])))); | |
e0838ca1 AM |
207 | } |
208 | inOutput = false; | |
209 | } else if (OUTPUT_KEY.equals(strLine)) { | |
210 | // first line of output | |
211 | inOutput = true; | |
6418ef54 JRJ |
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) { | |
e0838ca1 AM |
218 | while (isComment(strLine)) { |
219 | strLine = br.readLine(); | |
220 | } | |
6418ef54 JRJ |
221 | // lines of output/error output |
222 | if (errorOutput != null && inErrorOutput) { | |
223 | errorOutput.add(strLine); | |
224 | } else if (output != null) { | |
e0838ca1 AM |
225 | output.add(strLine); |
226 | } | |
d132bcc7 | 227 | } |
e0838ca1 AM |
228 | // else { |
229 | // if (RESULT_END_KEY.equals(strLine)) { | |
d132bcc7 | 230 | // nothing to do |
e0838ca1 AM |
231 | // } |
232 | } | |
d132bcc7 BH |
233 | } |
234 | } | |
13729cbc BH |
235 | } catch (IOException e) { |
236 | e.printStackTrace(); | |
d132bcc7 | 237 | } |
d132bcc7 BH |
238 | } |
239 | ||
2e65d221 BH |
240 | private static String updateSessionMap(Map<String, Integer> tmpSessionNameMap, String input, String sessionName) { |
241 | Integer i = tmpSessionNameMap.get(sessionName); | |
242 | if (i != null) { | |
243 | i++; | |
244 | } else { | |
245 | i = 0; | |
246 | } | |
247 | tmpSessionNameMap.put(sessionName, i); | |
248 | return String.valueOf(i); | |
249 | } | |
250 | ||
d132bcc7 BH |
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(); | |
257 | } | |
258 | } | |
259 | ||
d132bcc7 | 260 | @Override |
364dcfaf | 261 | public synchronized ICommandResult executeCommand(ICommandInput command, IProgressMonitor monitor) throws ExecutionException { |
90700072 BH |
262 | return executeCommand(command, monitor, null); |
263 | } | |
264 | ||
265 | @Override | |
266 | public synchronized ICommandResult executeCommand(ICommandInput command, IProgressMonitor monitor, ICommandOutputListener listener) throws ExecutionException { | |
202956f1 | 267 | Map<String, ICommandResult> commands = checkNotNull(fScenarioMap.get(fScenario)); |
364dcfaf | 268 | String commandLine = command.toString(); |
774a7993 | 269 | String fullCommand = commandLine; |
d132bcc7 | 270 | |
774a7993 | 271 | Matcher matcher = LTTNG_LIST_SESSION_PATTERN.matcher(commandLine); |
2e65d221 | 272 | Matcher miMatcher = LTTNG_LIST_SESSION_MI_PATTERN.matcher(commandLine); |
774a7993 | 273 | if (matcher.matches() && !commandLine.matches(LTTNG_LIST_PROVIDER_PATTERN)) { |
d132bcc7 | 274 | String sessionName = matcher.group(1).trim(); |
2e65d221 BH |
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); | |
d132bcc7 BH |
279 | } |
280 | ||
41b5c37f | 281 | if (commands.containsKey(fullCommand)) { |
13729cbc | 282 | return checkNotNull(commands.get(fullCommand)); |
cfdb727a | 283 | } |
d132bcc7 | 284 | |
aa353506 | 285 | @NonNull String[] output = new @NonNull String[1]; |
4e0b52e0 | 286 | output[0] = String.valueOf("Command not found"); |
1d6a2139 | 287 | ICommandResult result = createCommandResult(1, output, output); |
4ea599a5 | 288 | return result; |
774a7993 | 289 | } |
cfdb727a | 290 | |
d132bcc7 BH |
291 | // ------------------------------------------------------------------------ |
292 | // Helper methods | |
293 | // ------------------------------------------------------------------------ | |
11252342 | 294 | |
0a78d11a | 295 | private static boolean isComment(String line) { |
1f2f091b | 296 | if (line == null) { |
4e0b52e0 | 297 | throw new RuntimeException("line is null"); |
1f2f091b | 298 | } |
d132bcc7 BH |
299 | return line.matches(COMMENT_KEY); |
300 | } | |
301 | } |