Update internal packages export in LTTng 2.0 control + update java doc
[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 public final static String SHELL_ECHO_CMD = " echo "; //$NON-NLS-1$
56
57 private final static int DEFAULT_TIMEOUT_VALUE = 15000; // in milliseconds
58
59 // ------------------------------------------------------------------------
60 // Attributes
61 // ------------------------------------------------------------------------
62 private IRemoteSystemProxy fProxy = null;
63 private IHostShell fHostShell = null;
64 private BufferedReader fBufferReader = null;
65 private ExecutorService fExecutor = Executors.newFixedThreadPool(1);
66 private boolean fIsConnected = false;
67
68 // ------------------------------------------------------------------------
69 // Constructors
70 // ------------------------------------------------------------------------
71 public CommandShell(IRemoteSystemProxy proxy) {
72 fProxy = proxy;
73 }
74
75 // ------------------------------------------------------------------------
76 // Operations
77 // ------------------------------------------------------------------------
78 /*
79 * (non-Javadoc)
80 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#connect()
81 */
82 @Override
83 public void connect() throws ExecutionException {
84 IShellService shellService = fProxy.getShellService();
85 Process p = null;
86 try {
87 fHostShell = shellService.launchShell("", new String[0], new NullProgressMonitor()); //$NON-NLS-1$
88 p = new HostShellProcessAdapter(fHostShell);
89 } catch (Exception e) {
90 throw new ExecutionException(Messages.TraceControl_CommandShellError, e);
91 }
92 fBufferReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
93 fIsConnected = true;
94
95 // Flush Login messages
96 executeCommand(" ", new NullProgressMonitor(), false); //$NON-NLS-1$
97 }
98
99 /*
100 * (non-Javadoc)
101 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#disconnect()
102 */
103 @Override
104 public void disconnect() {
105 fIsConnected = false;
106 try {
107 fBufferReader.close();
108 } catch (IOException e) {
109 // ignore
110 }
111 }
112
113 /*
114 * (non-Javadoc)
115 * @see org.eclipse.linuxtools.internal.lttng2.ui.views.control.service.ICommandShell#executeCommand(java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
116 */
117 @Override
118 public ICommandResult executeCommand(String command, IProgressMonitor monitor) throws ExecutionException {
119 return executeCommand(command, monitor, true);
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, boolean)
125 */
126 @Override
127 public ICommandResult executeCommand(final String command, final IProgressMonitor monitor, final boolean checkReturnValue) throws ExecutionException {
128 if (fIsConnected) {
129 FutureTask<CommandResult> future = new FutureTask<CommandResult>(new Callable<CommandResult>() {
130 @Override
131 public CommandResult call() throws IOException, CancellationException {
132 final ArrayList<String> result = new ArrayList<String>();
133 int returnValue = 0;
134
135 synchronized (fHostShell) {
136 fHostShell.writeToShell(formatShellCommand(command));
137 String nextLine;
138 while ((nextLine = fBufferReader.readLine()) != null) {
139
140 if (monitor.isCanceled()) {
141 flushInput();
142 throw new CancellationException();
143 }
144
145 if (nextLine.contains(DONE_MARKUP_STRING) && nextLine.contains(SHELL_ECHO_CMD)) {
146 break;
147 }
148 }
149
150 while ((nextLine = fBufferReader.readLine()) != null) {
151 // check if job was cancelled
152 if (monitor.isCanceled()) {
153 flushInput();
154 throw new CancellationException();
155 }
156
157 if (!nextLine.contains(DONE_MARKUP_STRING)) {
158 result.add(nextLine);
159 } else {
160 if (checkReturnValue) {
161 returnValue = Integer.valueOf(nextLine.substring(DONE_MARKUP_STRING.length()+1));
162 }
163 break;
164 }
165 }
166
167 flushInput();
168 }
169 return new CommandResult(returnValue, result.toArray(new String[result.size()]));
170 }
171 });
172
173 fExecutor.execute(future);
174
175 try {
176 return future.get(DEFAULT_TIMEOUT_VALUE, TimeUnit.MILLISECONDS);
177 } catch (java.util.concurrent.ExecutionException ex) {
178 throw new ExecutionException(Messages.TraceControl_ExecutionFailure, ex);
179 } catch (InterruptedException ex) {
180 throw new ExecutionException(Messages.TraceControl_ExecutionCancelled, ex);
181 } catch (TimeoutException ex) {
182 throw new ExecutionException(Messages.TraceControl_ExecutionTimeout, ex);
183 }
184 }
185 throw new ExecutionException(Messages.TraceControl_ShellNotConnected, null);
186 }
187
188 // ------------------------------------------------------------------------
189 // Helper methods
190 // ------------------------------------------------------------------------
191 /**
192 * Flushes the buffer reader
193 * @throws IOException
194 */
195 private void flushInput() throws IOException {
196 char[] cbuf = new char[1];
197 while (fBufferReader.ready()) {
198 if (fBufferReader.read(cbuf, 0, 1) == -1) {
199 break;
200 }
201 }
202 }
203
204 /**
205 * format the command to be sent into the shell command with the done markup string.
206 * The done markup string is needed so we can tell that end of output has been reached.
207 *
208 * @param cmd
209 * @return formatted command string
210 */
211 private String formatShellCommand(String cmd) {
212 if (cmd == null || cmd.equals("")) //$NON-NLS-1$
213 return cmd;
214 StringBuffer formattedCommand = new StringBuffer();
215 // Make a multi line command by using \ and \r. This is needed for matching
216 // the DONE_MARKUP_STRING in echoed command when having a long command
217 // (bigger than max SSH line)
218 formattedCommand.append(cmd).append("\\\r;"); //$NON-NLS-1$
219 formattedCommand.append(SHELL_ECHO_CMD).append(DONE_MARKUP_STRING);
220 formattedCommand.append(" $?"); //$NON-NLS-1$
221 formattedCommand.append(CMD_DELIMITER);
222 return formattedCommand.toString();
223 }
224
225 }
This page took 0.055704 seconds and 6 git commands to generate.