lttng: Fix Javadoc and formatting in lttng2.ui
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.ui / src / org / eclipse / linuxtools / internal / lttng2 / ui / views / control / remote / CommandShell.java
1 /**********************************************************************
2 * Copyright (c) 2012 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 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated using Executor Framework
12 **********************************************************************/
13 package org.eclipse.linuxtools.internal.lttng2.ui.views.control.remote;
14
15 import java.io.BufferedReader;
16 import java.io.IOException;
17 import java.io.InputStreamReader;
18 import java.util.ArrayList;
19 import java.util.concurrent.Callable;
20 import java.util.concurrent.CancellationException;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.FutureTask;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.TimeoutException;
26
27 import org.eclipse.core.commands.ExecutionException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.NullProgressMonitor;
30 import org.eclipse.linuxtools.internal.lttng2.ui.views.control.messages.Messages;
31 import org.eclipse.rse.services.shells.HostShellProcessAdapter;
32 import org.eclipse.rse.services.shells.IHostShell;
33 import org.eclipse.rse.services.shells.IShellService;
34
35 /**
36 * <p>
37 * Implementation of remote command execution using RSE's shell service.
38 * </p>
39 *
40 * @author Patrick Tasse
41 * @author Bernd Hufmann
42 */
43 public class CommandShell implements ICommandShell {
44
45 // ------------------------------------------------------------------------
46 // Constants
47 // ------------------------------------------------------------------------
48
49 /** String to be echo'ed when running command in shell, used to indicate that the command has finished running */
50 public final static String DONE_MARKUP_STRING = "--RSE:donedonedone:--"; //$NON-NLS-1$
51
52 /** Command delimiter for shell */
53 public final static String CMD_DELIMITER = "\n"; //$NON-NLS-1$
54
55 /** Shell "echo" command */
56 public final static String SHELL_ECHO_CMD = " echo "; //$NON-NLS-1$
57
58 /** Default timeout, in milliseconds */
59 private final static int DEFAULT_TIMEOUT_VALUE = 15000;
60
61 // ------------------------------------------------------------------------
62 // Attributes
63 // ------------------------------------------------------------------------
64 private IRemoteSystemProxy fProxy = null;
65 private IHostShell fHostShell = null;
66 private BufferedReader fBufferReader = null;
67 private final ExecutorService fExecutor = Executors.newFixedThreadPool(1);
68 private boolean fIsConnected = false;
69
70 // ------------------------------------------------------------------------
71 // Constructors
72 // ------------------------------------------------------------------------
73
74 /**
75 * Constructor
76 *
77 * @param proxy
78 * The Remote System proxy
79 */
80 public CommandShell(IRemoteSystemProxy proxy) {
81 fProxy = proxy;
82 }
83
84 // ------------------------------------------------------------------------
85 // Operations
86 // ------------------------------------------------------------------------
87 /*
88 * (non-Javadoc)
89 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#connect()
90 */
91 @Override
92 public void connect() throws ExecutionException {
93 IShellService shellService = fProxy.getShellService();
94 Process p = null;
95 try {
96 fHostShell = shellService.launchShell("", new String[0], new NullProgressMonitor()); //$NON-NLS-1$
97 p = new HostShellProcessAdapter(fHostShell);
98 } catch (Exception e) {
99 throw new ExecutionException(Messages.TraceControl_CommandShellError, e);
100 }
101 fBufferReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
102 fIsConnected = true;
103
104 // Flush Login messages
105 executeCommand(" ", new NullProgressMonitor(), false); //$NON-NLS-1$
106 }
107
108 /*
109 * (non-Javadoc)
110 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#disconnect()
111 */
112 @Override
113 public void disconnect() {
114 fIsConnected = false;
115 try {
116 fBufferReader.close();
117 } catch (IOException e) {
118 // ignore
119 }
120 }
121
122 /*
123 * (non-Javadoc)
124 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#executeCommand(java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
125 */
126 @Override
127 public ICommandResult executeCommand(String command, IProgressMonitor monitor) throws ExecutionException {
128 return executeCommand(command, monitor, true);
129 }
130
131 /*
132 * (non-Javadoc)
133 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#executeCommand(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, boolean)
134 */
135 @Override
136 public ICommandResult executeCommand(final String command, final IProgressMonitor monitor, final boolean checkReturnValue) throws ExecutionException {
137 if (fIsConnected) {
138 FutureTask<CommandResult> future = new FutureTask<CommandResult>(new Callable<CommandResult>() {
139 @Override
140 public CommandResult call() throws IOException, CancellationException {
141 final ArrayList<String> result = new ArrayList<String>();
142 int returnValue = 0;
143
144 synchronized (fHostShell) {
145 fHostShell.writeToShell(formatShellCommand(command));
146 String nextLine;
147 while ((nextLine = fBufferReader.readLine()) != null) {
148
149 if (monitor.isCanceled()) {
150 flushInput();
151 throw new CancellationException();
152 }
153
154 if (nextLine.contains(DONE_MARKUP_STRING) && nextLine.contains(SHELL_ECHO_CMD)) {
155 break;
156 }
157 }
158
159 while ((nextLine = fBufferReader.readLine()) != null) {
160 // check if job was cancelled
161 if (monitor.isCanceled()) {
162 flushInput();
163 throw new CancellationException();
164 }
165
166 if (!nextLine.contains(DONE_MARKUP_STRING)) {
167 result.add(nextLine);
168 } else {
169 if (checkReturnValue) {
170 returnValue = Integer.valueOf(nextLine.substring(DONE_MARKUP_STRING.length()+1));
171 }
172 break;
173 }
174 }
175
176 flushInput();
177 }
178 return new CommandResult(returnValue, result.toArray(new String[result.size()]));
179 }
180 });
181
182 fExecutor.execute(future);
183
184 try {
185 return future.get(DEFAULT_TIMEOUT_VALUE, TimeUnit.MILLISECONDS);
186 } catch (java.util.concurrent.ExecutionException ex) {
187 throw new ExecutionException(Messages.TraceControl_ExecutionFailure, ex);
188 } catch (InterruptedException ex) {
189 throw new ExecutionException(Messages.TraceControl_ExecutionCancelled, ex);
190 } catch (TimeoutException ex) {
191 throw new ExecutionException(Messages.TraceControl_ExecutionTimeout, ex);
192 }
193 }
194 throw new ExecutionException(Messages.TraceControl_ShellNotConnected, null);
195 }
196
197 // ------------------------------------------------------------------------
198 // Helper methods
199 // ------------------------------------------------------------------------
200 /**
201 * Flushes the buffer reader
202 * @throws IOException
203 */
204 private void flushInput() throws IOException {
205 char[] cbuf = new char[1];
206 while (fBufferReader.ready()) {
207 if (fBufferReader.read(cbuf, 0, 1) == -1) {
208 break;
209 }
210 }
211 }
212
213 /**
214 * Format the command to be sent into the shell command with the done markup
215 * string. The done markup string is needed so we can tell that end of
216 * output has been reached.
217 *
218 * @param cmd
219 * The original command
220 * @return formatted command string
221 */
222 private String formatShellCommand(String cmd) {
223 if (cmd == null || cmd.equals("")) { //$NON-NLS-1$
224 return cmd;
225 }
226 StringBuffer formattedCommand = new StringBuffer();
227 // Make a multi line command by using \ and \r. This is needed for matching
228 // the DONE_MARKUP_STRING in echoed command when having a long command
229 // (bigger than max SSH line)
230 formattedCommand.append(cmd).append("\\\r;"); //$NON-NLS-1$
231 formattedCommand.append(SHELL_ECHO_CMD).append(DONE_MARKUP_STRING);
232 formattedCommand.append(" $?"); //$NON-NLS-1$
233 formattedCommand.append(CMD_DELIMITER);
234 return formattedCommand.toString();
235 }
236
237 }
This page took 0.036418 seconds and 6 git commands to generate.