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
;
20 import java
.io
.FileInputStream
;
21 import java
.io
.IOException
;
22 import java
.io
.InputStreamReader
;
23 import java
.io
.PrintWriter
;
24 import java
.util
.ArrayList
;
25 import java
.util
.Collection
;
26 import java
.util
.HashMap
;
27 import java
.util
.Iterator
;
28 import java
.util
.List
;
30 import java
.util
.regex
.Matcher
;
31 import java
.util
.regex
.Pattern
;
33 import org
.eclipse
.core
.commands
.ExecutionException
;
34 import org
.eclipse
.core
.resources
.IWorkspace
;
35 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
36 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
37 import org
.eclipse
.jdt
.annotation
.NonNull
;
38 import org
.eclipse
.tracecompass
.internal
.tmf
.remote
.core
.stubs
.shells
.TestCommandShell
;
39 import org
.eclipse
.tracecompass
.tmf
.remote
.core
.shell
.ICommandInput
;
40 import org
.eclipse
.tracecompass
.tmf
.remote
.core
.shell
.ICommandOutputListener
;
41 import org
.eclipse
.tracecompass
.tmf
.remote
.core
.shell
.ICommandResult
;
43 @SuppressWarnings("javadoc")
44 public class LTTngToolsFileShell
extends TestCommandShell
{
46 // ------------------------------------------------------------------------
48 // ------------------------------------------------------------------------
49 private final static String SCENARIO_KEY
= "<SCENARIO>";
50 private final static String SCENARIO_END_KEY
= "</SCENARIO>";
51 private final static String INPUT_KEY
= "<COMMAND_INPUT>";
52 private final static String INPUT_END_KEY
= "</COMMAND_INPUT>";
53 private final static String RESULT_KEY
= "<COMMAND_RESULT>";
54 private final static String OUTPUT_KEY
= "<COMMAND_OUTPUT>";
55 private final static String OUTPUT_END_KEY
= "</COMMAND_OUTPUT>";
56 private final static String ERROR_OUTPUT_KEY
= "<COMMAND_ERROR_OUTPUT>";
57 private final static String ERROR_OUTPUT_END_KEY
= "</COMMAND_ERROR_OUTPUT>";
58 private final static String COMMENT_KEY
= "#.*";
60 private final static Pattern LTTNG_LIST_SESSION_PATTERN
= Pattern
.compile("lttng\\s+list\\s+(.+)");
61 private final static String LTTNG_LIST_PROVIDER_PATTERN
= "lttng\\s+list\\s+(-u|-k)";
63 private final static Pattern LTTNG_LIST_SESSION_MI_PATTERN
= Pattern
.compile("lttng\\s+--mi xml\\s+list\\s+(.+)");
64 private final static String LTTNG_LIST_PROVIDER_MI_PATTERN
= "lttng\\s+--mi xml\\s+list\\s+(-u|-k)";
66 private final static String LTTNG_USER_HOME_PATTERN
= "\\$\\{userhome\\}";
67 private final static String LTTNG_WORKSPACE_PATTERN
= "\\$\\{workspace\\}";
68 private final static String SESSION_NAME_PATTERN
= "\\$\\{sessionname\\}";
70 private final static String USER_HOME
= System
.getProperty("user.home");
71 private final static String WORKSPACE_HOME
;
73 private final static Pattern LTTNG_SAVE_MI_PATTERN
= Pattern
.compile("lttng\\s+--mi xml\\s+save\\s+-f");
75 private final static String PROFILE_PATH_STRING
= USER_HOME
+ '/' + ".lttng" + '/' + "sessions";
78 IWorkspace workspace
= ResourcesPlugin
.getWorkspace();
79 //get location of workspace (java.io.File)
80 File workspaceDirectory
= workspace
.getRoot().getLocation().toFile();
81 WORKSPACE_HOME
= workspaceDirectory
.toString();
84 // ------------------------------------------------------------------------
86 // ------------------------------------------------------------------------
87 private String fScenariofile
;
88 private String fScenario
;
89 private String fProfileName
= null;
90 private File fProfileFile
= null;
91 private String fSessionName
= null;
93 private final Map
<String
, Map
<String
, ICommandResult
>> fScenarioMap
= new HashMap
<>();
94 private final Map
<String
, Integer
> fSessionNameMap
= new HashMap
<>();
97 * Parse a scenario file with the format:
103 * <COMMAND_INPUT>
105 * </COMMAND_INPUT>
107 * <COMMAND_RESULT>
109 * </COMMAND_RESULT>
111 * <COMMAND_OUTPUT>
113 * <COMMAND_ERROR_OUTPUT>
115 * </COMMAND_ERROR_OUTPUT>
116 * </COMMAND_OUTPUT>
120 * Where: ScenarioName - is the scenario name
121 * Command - the command line string
122 * CommandResult - the result integer of the command (0 for success, 1 for failure)
123 * CommandOutput - the command output string (multi-line possible)
124 * CommandErrorOutput - the command error output string (multi-line possible)
126 * Note: 1) There can be many scenarios per file
127 * 2) There can be many (Command-CommandResult-CommandOutput) triples per scenario
128 * 3) Lines starting with # will be ignored (comments)
131 * @param scenariofile - path to scenario file
133 public synchronized void loadScenarioFile(String scenariofile
) {
134 fScenariofile
= scenariofile
;
137 Collection
<Map
<String
, ICommandResult
>> values
= fScenarioMap
.values();
138 for (Iterator
<Map
<String
, ICommandResult
>> iterator
= values
.iterator(); iterator
.hasNext();) {
139 Map
<String
, ICommandResult
> map
= iterator
.next();
142 fScenarioMap
.clear();
147 try (FileInputStream fstream
= new FileInputStream(fScenariofile
);
148 DataInputStream in
= new DataInputStream(fstream
);
149 BufferedReader br
= new BufferedReader(new InputStreamReader(in
));) {
152 // Read File Line by Line
154 // Temporary map for generating instance numbers for lttng list
155 // <session> commands.
156 // The numbers are per scenario.
157 Map
<String
, Integer
> tmpSessionNameMap
= new HashMap
<>();
158 while ((strLine
= br
.readLine()) != null) {
161 if (isComment(strLine
)) {
165 if (SCENARIO_KEY
.equals(strLine
)) {
169 strLine
= br
.readLine();
170 while (isComment(strLine
)) {
171 strLine
= br
.readLine();
174 String scenario
= strLine
;
175 Map
<String
, ICommandResult
> commandMap
= new HashMap
<>();
176 fScenarioMap
.put(scenario
, commandMap
);
177 List
<String
> output
= null;
178 List
<String
> errorOutput
= null;
180 boolean inOutput
= false;
181 boolean inErrorOutput
= false;
183 tmpSessionNameMap
.clear();
184 while ((strLine
= br
.readLine()) != null) {
186 if (isComment(strLine
)) {
190 if (SCENARIO_END_KEY
.equals(strLine
)) {
191 // Scenario is finished
194 if (INPUT_KEY
.equals(strLine
)) {
195 strLine
= br
.readLine();
197 while (isComment(strLine
)) {
198 strLine
= br
.readLine();
204 input
= input
.replaceAll(LTTNG_USER_HOME_PATTERN
, USER_HOME
);
207 input
= input
.replaceAll(LTTNG_WORKSPACE_PATTERN
, WORKSPACE_HOME
);
209 // Update session variable
210 if (fSessionName
!= null) {
211 input
= input
.replaceAll(SESSION_NAME_PATTERN
, fSessionName
);
214 // Handle instances of 'lttng list
216 Matcher matcher
= LTTNG_LIST_SESSION_PATTERN
.matcher(strLine
);
217 Matcher miMatcher
= LTTNG_LIST_SESSION_MI_PATTERN
.matcher(strLine
);
219 if (matcher
.matches() && !input
.matches(LTTNG_LIST_PROVIDER_PATTERN
)) {
220 String sessionName
= matcher
.group(1).trim();
221 input
+= updateSessionMap(tmpSessionNameMap
, input
, sessionName
);
222 } else if (miMatcher
.matches() && !input
.matches(LTTNG_LIST_PROVIDER_MI_PATTERN
)) {
223 String sessionName
= miMatcher
.group(1).trim();
224 input
+= updateSessionMap(tmpSessionNameMap
, input
, sessionName
);
226 } else if (INPUT_END_KEY
.equals(strLine
)) {
227 // Initialize output array
228 output
= new ArrayList
<>();
229 errorOutput
= new ArrayList
<>();
230 } else if (RESULT_KEY
.equals(strLine
)) {
231 strLine
= br
.readLine();
233 while (isComment(strLine
)) {
234 strLine
= br
.readLine();
237 result
= Integer
.parseInt(strLine
);
238 } else if (OUTPUT_END_KEY
.equals(strLine
)) {
239 // Save output/result in command map
240 if (output
!= null && errorOutput
!= null) {
241 commandMap
.put(input
, createCommandResult(result
,
242 output
.toArray(new @NonNull String
[output
.size()]),
243 errorOutput
.toArray(new @NonNull String
[errorOutput
.size()])));
246 } else if (OUTPUT_KEY
.equals(strLine
)) {
247 // first line of output
249 } else if (ERROR_OUTPUT_KEY
.equals(strLine
)) {
250 // first line of output
251 inErrorOutput
= true;
252 } else if (ERROR_OUTPUT_END_KEY
.equals(strLine
)) {
253 inErrorOutput
= false;
254 } else if (inOutput
) {
255 while (isComment(strLine
)) {
256 strLine
= br
.readLine();
260 strLine
= strLine
.replaceAll(LTTNG_USER_HOME_PATTERN
, USER_HOME
);
263 strLine
= strLine
.replaceAll(LTTNG_WORKSPACE_PATTERN
, WORKSPACE_HOME
);
265 // Update session variable
266 if (fSessionName
!= null) {
267 strLine
= strLine
.replaceAll(SESSION_NAME_PATTERN
, fSessionName
);
270 // lines of output/error output
271 if (errorOutput
!= null && inErrorOutput
) {
272 errorOutput
.add(strLine
);
273 } else if (output
!= null) {
278 // if (RESULT_END_KEY.equals(strLine)) {
284 } catch (IOException e
) {
289 private static String
updateSessionMap(Map
<String
, Integer
> tmpSessionNameMap
, String input
, String sessionName
) {
290 Integer i
= tmpSessionNameMap
.get(sessionName
);
296 tmpSessionNameMap
.put(sessionName
, i
);
297 return String
.valueOf(i
);
300 // Set the scenario to consider in executeCommand()
301 public synchronized void setScenario(String scenario
) {
302 fScenario
= scenario
;
303 fSessionNameMap
.clear();
304 if (!fScenarioMap
.containsKey(fScenario
)) {
305 throw new IllegalArgumentException();
310 public synchronized ICommandResult
executeCommand(ICommandInput command
, IProgressMonitor monitor
) throws ExecutionException
{
311 return executeCommand(command
, monitor
, null);
315 public synchronized ICommandResult
executeCommand(ICommandInput command
, IProgressMonitor monitor
, ICommandOutputListener listener
) throws ExecutionException
{
316 Map
<String
, ICommandResult
> commands
= checkNotNull(fScenarioMap
.get(fScenario
));
317 String commandLine
= command
.toString();
318 String fullCommand
= commandLine
;
320 Matcher matcher
= LTTNG_LIST_SESSION_PATTERN
.matcher(commandLine
);
321 Matcher miMatcher
= LTTNG_LIST_SESSION_MI_PATTERN
.matcher(commandLine
);
322 if (matcher
.matches() && !commandLine
.matches(LTTNG_LIST_PROVIDER_PATTERN
)) {
323 String sessionName
= matcher
.group(1).trim();
324 fullCommand
+= updateSessionMap(fSessionNameMap
, fullCommand
, sessionName
);
325 } else if (miMatcher
.matches() && !commandLine
.matches(LTTNG_LIST_PROVIDER_MI_PATTERN
)) {
326 String sessionName
= miMatcher
.group(1).trim();
327 fullCommand
+= updateSessionMap(fSessionNameMap
, fullCommand
, sessionName
);
330 if (commands
.containsKey(fullCommand
)) {
331 Matcher saveMatcher
= LTTNG_SAVE_MI_PATTERN
.matcher(fullCommand
);
332 if (fProfileName
!= null && saveMatcher
.matches()) {
335 } catch (IOException e
) {
336 throw new ExecutionException("Profile file can't be created", e
);
339 return checkNotNull(commands
.get(fullCommand
));
342 @NonNull String
[] output
= new @NonNull String
[1];
343 output
[0] = String
.valueOf("Command not found");
344 ICommandResult result
= createCommandResult(1, output
, output
);
348 // ------------------------------------------------------------------------
350 // ------------------------------------------------------------------------
352 private static boolean isComment(String line
) {
354 throw new RuntimeException("line is null");
356 return line
.matches(COMMENT_KEY
);
359 private void createProfileFile() throws IOException
{
360 if (fProfileName
!= null) {
361 File path
= new File(PROFILE_PATH_STRING
);
362 if (!path
.exists()) {
363 if (!path
.mkdirs()) {
364 throw new RuntimeException();
367 File profileFile
= new File(PROFILE_PATH_STRING
+ '/' + fProfileName
+ ".lttng");
368 if (!profileFile
.exists()) {
369 try (PrintWriter writer
= new PrintWriter(profileFile
)) {
370 writer
.println("This file is created by JUnit test using " + LTTngToolsFileShell
.class.getCanonicalName());
371 writer
.println("Can be deleted!");
375 fProfileFile
= profileFile
;
379 public void setProfileName(String profileName
) {
380 fProfileName
= profileName
;
383 public void deleteProfileFile() {
384 if (fProfileFile
!= null && fProfileFile
.exists()) {
385 fProfileFile
.delete();
389 public void setSessionName(String sessionName
) {
390 fSessionName
= sessionName
;