summaryrefslogtreecommitdiffstats
path: root/plugins/org.yocto.remote.utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.yocto.remote.utils/src')
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Activator.java62
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/CommonHelper.java46
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/DialogRunnable.java26
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Messages.java35
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RSEHelper.java344
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RemoteShellExec.java140
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/ShellSession.java332
-rw-r--r--plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/TerminalHandler.java132
8 files changed, 1117 insertions, 0 deletions
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Activator.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Activator.java
new file mode 100644
index 0000000..da66a3e
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Activator.java
@@ -0,0 +1,62 @@
1/*******************************************************************************
2 * Copyright (c) 2013 Intel Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel - initial API and implementation
10 *******************************************************************************/
11package org.yocto.remote.utils;
12
13import org.eclipse.ui.plugin.AbstractUIPlugin;
14import org.osgi.framework.BundleContext;
15
16/**
17 * The activator class controls the plug-in life cycle
18 */
19public class Activator extends AbstractUIPlugin {
20
21 // The plug-in ID
22 public static final String PLUGIN_ID = "org.yocto.remote.utils"; //$NON-NLS-1$
23
24 // The shared instance
25 private static Activator plugin;
26
27 /**
28 * The constructor
29 */
30 public Activator() {
31 }
32
33 /*
34 * (non-Javadoc)
35 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
36 */
37 @Override
38 public void start(BundleContext context) throws Exception {
39 super.start(context);
40 plugin = this;
41 }
42
43 /*
44 * (non-Javadoc)
45 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
46 */
47 @Override
48 public void stop(BundleContext context) throws Exception {
49 plugin = null;
50 super.stop(context);
51 }
52
53 /**
54 * Returns the shared instance
55 *
56 * @return the shared instance
57 */
58 public static Activator getDefault() {
59 return plugin;
60 }
61
62}
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/CommonHelper.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/CommonHelper.java
new file mode 100644
index 0000000..23afd38
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/CommonHelper.java
@@ -0,0 +1,46 @@
1/*******************************************************************************
2 * Copyright (c) 2013 Intel Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel - initial API and implementation
10 *******************************************************************************/
11package org.yocto.remote.utils;
12
13import org.eclipse.core.runtime.IStatus;
14import org.eclipse.core.runtime.Status;
15import org.eclipse.jface.dialogs.ErrorDialog;
16import org.eclipse.swt.widgets.Display;
17
18public class CommonHelper {
19
20 static public boolean isExecAvail(String exec) {
21 boolean ret = false;
22 try {
23 Process p = Runtime.getRuntime().exec(new String[] {"which", exec});
24 p.waitFor();
25 if(p.exitValue() == 0) {
26 ret = true;
27 }
28 } catch (Exception e) {
29 e.printStackTrace();
30 }
31 return ret;
32 }
33
34 public static void showErrorDialog(final String dialogTitle, final String errorMessage, final String reason) {
35 //needs to be run in the ui thread otherwise swt throws invalid thread access
36 Display.getDefault().syncExec(new Runnable() {
37 @Override
38 public void run() {
39 ErrorDialog.openError(null, dialogTitle, errorMessage,
40 new Status(IStatus.ERROR,Activator.PLUGIN_ID,reason));
41 }
42 });
43
44 }
45
46}
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/DialogRunnable.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/DialogRunnable.java
new file mode 100644
index 0000000..5fbab76
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/DialogRunnable.java
@@ -0,0 +1,26 @@
1package org.yocto.remote.utils;
2
3import org.eclipse.jface.dialogs.MessageDialog;
4
5public class DialogRunnable implements Runnable{
6 int type = 0;
7 boolean result;
8 public static final int QUESTION = 1;
9 public static final int ERROR = 2;
10 String title;
11 String message;
12
13 DialogRunnable(String title, String message, int type){
14 this.title = title;
15 this.message = message;
16 this.type = type;
17 }
18 @Override
19 public void run() {
20 if (type == QUESTION) {
21 result = MessageDialog.openQuestion(null, title, message);
22 } else if (type == ERROR) {
23 MessageDialog.openError(null, title, message);
24 }
25 }
26} \ No newline at end of file
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Messages.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Messages.java
new file mode 100644
index 0000000..fc696d6
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/Messages.java
@@ -0,0 +1,35 @@
1/*******************************************************************************
2 * Copyright (c) 2013 Intel Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel - initial API and implementation
10 *******************************************************************************/
11package org.yocto.remote.utils;
12
13import org.eclipse.osgi.util.NLS;
14
15public class Messages extends NLS {
16
17 private static final String BUNDLE_NAME = "org.yocto.remote.utils.messages"; //$NON-NLS-1$
18
19 public static String ErrorNoSubsystem;
20 public static String ErrorConnectSubsystem;
21
22 public static String InfoDownload;
23 public static String InfoUpload;
24
25 public static String RemoteShellExec_1;
26 public static String RemoteShellExec_2;
27
28 static {
29 // initialize resource bundle
30 NLS.initializeMessages(BUNDLE_NAME, Messages.class);
31 }
32
33 private Messages() {
34 }
35}
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RSEHelper.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RSEHelper.java
new file mode 100644
index 0000000..201c944
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RSEHelper.java
@@ -0,0 +1,344 @@
1/********************************************************************************
2 * Copyright (c) 2013 MontaVista Software, Inc and Others.
3 * This program and the accompanying materials are made available under the terms
4 * of the Eclipse Public License v1.0 which accompanies this distribution, and is
5 * available at http://www.eclipse.org/legal/epl-v10.html
6 *
7 * Contributors:
8 * Anna Dushistova (MontaVista) - initial API and implementation
9 * Lianhao Lu (Intel) - Modified to add other file operations.
10 * Ioana Grigoropol (Intel) - Separated remote functionality
11 ********************************************************************************/
12package org.yocto.remote.utils;
13
14import java.io.BufferedInputStream;
15import java.io.BufferedOutputStream;
16import java.io.File;
17import java.io.FileOutputStream;
18import java.io.InputStream;
19import java.util.ArrayList;
20import java.util.Arrays;
21import java.util.Iterator;
22
23import org.eclipse.core.runtime.CoreException;
24import org.eclipse.core.runtime.FileLocator;
25import org.eclipse.core.runtime.IProgressMonitor;
26import org.eclipse.core.runtime.IStatus;
27import org.eclipse.core.runtime.MultiStatus;
28import org.eclipse.core.runtime.OperationCanceledException;
29import org.eclipse.core.runtime.Path;
30import org.eclipse.core.runtime.Status;
31import org.eclipse.core.runtime.SubProgressMonitor;
32import org.eclipse.osgi.util.NLS;
33import org.eclipse.rse.core.IRSECoreStatusCodes;
34import org.eclipse.rse.core.IRSESystemType;
35import org.eclipse.rse.core.RSECorePlugin;
36import org.eclipse.rse.core.model.IHost;
37import org.eclipse.rse.core.model.ISubSystemConfigurationCategories;
38import org.eclipse.rse.core.model.ISystemRegistry;
39import org.eclipse.rse.core.subsystems.ISubSystem;
40import org.eclipse.rse.services.IService;
41import org.eclipse.rse.services.files.IFileService;
42import org.eclipse.rse.services.shells.HostShellProcessAdapter;
43import org.eclipse.rse.services.shells.IHostShell;
44import org.eclipse.rse.services.shells.IShellService;
45import org.eclipse.rse.subsystems.files.core.servicesubsystem.IFileServiceSubSystem;
46import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.IShellServiceSubSystem;
47import org.eclipse.rse.subsystems.terminals.core.ITerminalServiceSubSystem;
48
49public class RSEHelper {
50 private final static String EXIT_CMD = "exit"; //$NON-NLS-1$
51 private final static String CMD_DELIMITER = ";"; //$NON-NLS-1$
52
53 public static IHost getRemoteConnectionByName(String remoteConnection) {
54 if (remoteConnection == null)
55 return null;
56 IHost[] connections = RSECorePlugin.getTheSystemRegistry().getHosts();
57 for (int i = 0; i < connections.length; i++)
58 if (connections[i].getAliasName().equals(remoteConnection))
59 return connections[i];
60 return null; // TODO Connection is not found in the list--need to react
61 // somehow, throw the exception?
62
63 }
64
65 public static IService getConnectedRemoteFileService(
66 IHost currentConnection, IProgressMonitor monitor) throws Exception {
67 final ISubSystem subsystem = getFileSubsystem(currentConnection);
68
69 if (subsystem == null)
70 throw new Exception(Messages.ErrorNoSubsystem);
71
72 try {
73 subsystem.connect(monitor, false);
74 } catch (CoreException e) {
75 throw e;
76 } catch (OperationCanceledException e) {
77 throw new CoreException(Status.CANCEL_STATUS);
78 }
79
80 if (!subsystem.isConnected())
81 throw new Exception(Messages.ErrorConnectSubsystem);
82
83 return ((IFileServiceSubSystem) subsystem).getFileService();
84 }
85
86 public static ISubSystem getFileSubsystem(IHost host) {
87 if (host == null)
88 return null;
89 ISubSystem[] subSystems = host.getSubSystems();
90 for (int i = 0; i < subSystems.length; i++) {
91 if (subSystems[i] instanceof IFileServiceSubSystem)
92 return subSystems[i];
93 }
94 return null;
95 }
96
97 public static IService getConnectedShellService(
98 IHost currentConnection, IProgressMonitor monitor) throws Exception {
99 final ISubSystem subsystem = getShellSubsystem(currentConnection);
100
101 if (subsystem == null)
102 throw new Exception(Messages.ErrorNoSubsystem);
103
104 try {
105 subsystem.connect(monitor, false);
106 } catch (CoreException e) {
107 throw e;
108 } catch (OperationCanceledException e) {
109 throw new CoreException(Status.CANCEL_STATUS);
110 }
111
112 if (!subsystem.isConnected())
113 throw new Exception(Messages.ErrorConnectSubsystem);
114
115 return ((IShellServiceSubSystem) subsystem).getShellService();
116 }
117
118 public static ISubSystem getShellSubsystem(IHost host) {
119 if (host == null)
120 return null;
121 ISubSystem[] subSystems = host.getSubSystems();
122 for (int i = 0; i < subSystems.length; i++) {
123 if (subSystems[i] instanceof IShellServiceSubSystem)
124 return subSystems[i];
125 }
126 return null;
127 }
128
129 public static IHost[] getSuitableConnections() {
130
131 //we only get RSE connections with files&cmds subsystem
132 ArrayList <IHost> filConnections = new ArrayList <IHost>(Arrays.asList(RSECorePlugin.getTheSystemRegistry()
133 .getHostsBySubSystemConfigurationCategory(ISubSystemConfigurationCategories.SUBSYSTEM_CATEGORY_FILES))); //$NON-NLS-1$
134
135 ArrayList <IHost> terminalConnections = new ArrayList <IHost>(Arrays.asList(RSECorePlugin.getTheSystemRegistry()
136 .getHostsBySubSystemConfigurationCategory("terminal")));//$NON-NLS-1$
137
138 ArrayList <IHost> shellConnections = new ArrayList <IHost>(Arrays.asList(RSECorePlugin.getTheSystemRegistry()
139 .getHostsBySubSystemConfigurationCategory("shells"))); //$NON-NLS-1$
140
141 Iterator <IHost>iter = filConnections.iterator();
142 while(iter.hasNext()){
143 IHost fileConnection = iter.next();
144 if(!terminalConnections.contains(fileConnection) && !shellConnections.contains(fileConnection)){
145 iter.remove();
146 }
147 IRSESystemType sysType = fileConnection.getSystemType();
148 if (sysType == null || !sysType.isEnabled()) {
149 iter.remove();
150 }
151 }
152
153 return filConnections.toArray(new IHost[filConnections.size()]);
154 }
155
156 public static void putRemoteFileInPlugin(IHost connection, String locaPathInPlugin, String remoteExePath,
157 IProgressMonitor monitor) throws Exception {
158
159 assert(connection != null);
160 monitor.beginTask(Messages.InfoUpload, 100);
161
162 IFileService fileService;
163 try {
164 fileService = (IFileService) getConnectedRemoteFileService(
165 connection,
166 new SubProgressMonitor(monitor, 5));
167 InputStream inputStream = FileLocator.openStream(
168 Activator.getDefault().getBundle(), new Path(locaPathInPlugin), false);
169 Path remotePath = new Path(remoteExePath);
170
171 //TODO workaround for now
172 //in case the underlying scp file service doesn't support inputStream upload
173 BufferedInputStream bis = new BufferedInputStream(inputStream);
174 File tempFile = File.createTempFile("scp", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
175 FileOutputStream os = new FileOutputStream(tempFile);
176 BufferedOutputStream bos = new BufferedOutputStream(os);
177 byte[] buffer = new byte[1024];
178 int readCount;
179 while( (readCount = bis.read(buffer)) > 0)
180 {
181 bos.write(buffer, 0, readCount);
182 }
183 bos.close();
184 fileService.upload(tempFile, remotePath.removeLastSegments(1)
185 .toString(), remotePath.lastSegment(), true, null, null,
186 new SubProgressMonitor(monitor, 80));
187 // Need to change the permissions to match the original file
188 // permissions because of a bug in upload
189 remoteShellExec(
190 connection,
191 "", "chmod", "+x " + spaceEscapify(remotePath.toString()), new SubProgressMonitor(monitor, 5)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
192
193 } finally {
194 monitor.done();
195 }
196 return;
197 }
198
199 public static void getRemoteFile(IHost connection, String localExePath, String remoteExePath,
200 IProgressMonitor monitor) throws Exception {
201
202 assert(connection!=null);
203 monitor.beginTask(Messages.InfoDownload, 100);
204
205 IFileService fileService;
206 try {
207 fileService = (IFileService) getConnectedRemoteFileService(
208 connection,
209 new SubProgressMonitor(monitor, 10));
210 File file = new File(localExePath);
211 file.deleteOnExit();
212 monitor.worked(5);
213 Path remotePath = new Path(remoteExePath);
214 fileService.download(remotePath.removeLastSegments(1).toString(),
215 remotePath.lastSegment(),file,true, null,
216 new SubProgressMonitor(monitor, 85));
217 // Need to change the permissions to match the original file
218 // permissions because of a bug in upload
219 //RemoteApplication p = remoteShellExec(
220 // config,
221 // "", "chmod", "+x " + spaceEscapify(remotePath.toString()), new SubProgressMonitor(monitor, 5)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
222 //Thread.sleep(500);
223 //p.destroy();
224
225 } finally {
226 monitor.done();
227 }
228 return;
229 }
230
231 public static ITerminalServiceSubSystem getTerminalSubSystem(
232 IHost connection) {
233 ISystemRegistry systemRegistry = RSECorePlugin.getTheSystemRegistry();
234 ISubSystem[] subsystems = systemRegistry.getSubSystems(connection);
235 for (int i = 0; i < subsystems.length; i++) {
236 if (subsystems[i] instanceof ITerminalServiceSubSystem) {
237 ITerminalServiceSubSystem subSystem = (ITerminalServiceSubSystem) subsystems[i];
238 return subSystem;
239 }
240 }
241 return null;
242 }
243
244 public static String spaceEscapify(String inputString) {
245 if (inputString == null)
246 return null;
247
248 return inputString.replaceAll(" ", "\\\\ "); //$NON-NLS-1$ //$NON-NLS-2$
249 }
250
251 public static Process remoteShellExec(IHost connection,
252 String prelaunchCmd, String remoteCommandPath, String arguments,
253 IProgressMonitor monitor) throws CoreException {
254
255 monitor.beginTask(NLS.bind(Messages.RemoteShellExec_1,
256 remoteCommandPath, arguments), 10);
257 String realRemoteCommand = arguments == null ? spaceEscapify(remoteCommandPath)
258 : spaceEscapify(remoteCommandPath) + " " + arguments; //$NON-NLS-1$
259
260 String remoteCommand = realRemoteCommand + CMD_DELIMITER + EXIT_CMD;
261
262 if(prelaunchCmd != null) {
263 if (!prelaunchCmd.trim().equals("")) //$NON-NLS-1$
264 remoteCommand = prelaunchCmd + CMD_DELIMITER + remoteCommand;
265 }
266
267 IShellService shellService;
268 Process p = null;
269 try {
270 shellService = (IShellService) getConnectedShellService(
271 connection,
272 new SubProgressMonitor(monitor, 7));
273
274 // This is necessary because runCommand does not actually run the
275 // command right now.
276 String env[] = new String[0];
277 try {
278 IHostShell hostShell = shellService.launchShell(
279 "", env, new SubProgressMonitor(monitor, 3)); //$NON-NLS-1$
280 hostShell.writeToShell(remoteCommand);
281 p = new HostShellProcessAdapter(hostShell);
282 } catch (Exception e) {
283 if (p != null) {
284 p.destroy();
285 }
286 abort(Messages.RemoteShellExec_2, e,
287 IRSECoreStatusCodes.EXCEPTION_OCCURRED);
288 }
289 } catch (Exception e1) {
290 abort(e1.getMessage(), e1,
291 IRSECoreStatusCodes.EXCEPTION_OCCURRED);
292 }
293
294 monitor.done();
295 return p;
296 }
297
298 /**
299 * Throws a core exception with an error status object built from the given
300 * message, lower level exception, and error code.
301 *
302 * @param message
303 * the status message
304 * @param exception
305 * lower level exception associated with the error, or
306 * <code>null</code> if none
307 * @param code
308 * error code
309 */
310 public static void abort(String message, Throwable exception, int code) throws CoreException {
311 IStatus status;
312 if (exception != null) {
313 MultiStatus multiStatus = new MultiStatus(Activator.PLUGIN_ID, code, message, exception);
314 multiStatus.add(new Status(IStatus.ERROR, Activator.PLUGIN_ID, code, exception.getLocalizedMessage(), exception));
315 status = multiStatus;
316 } else {
317 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, code, message, null);
318 }
319 throw new CoreException(status);
320 }
321 /**
322 * Checks whether a IHost associated system's is enabled and not a local one
323 * @param host
324 * @return
325 */
326 public static boolean isHostViable(IHost host) {
327 IRSESystemType sysType = host.getSystemType();
328 if (sysType != null && sysType.isEnabled() && !sysType.isLocal())
329 return true;
330 return false;
331 }
332
333 /**
334 * Ensures that RSECorePlugin is initialized before performing any actions
335 */
336 public static void waitForRSEInitCompletition() {
337 if (!RSECorePlugin.isInitComplete(RSECorePlugin.INIT_MODEL))
338 try {
339 RSECorePlugin.waitForInitCompletion(RSECorePlugin.INIT_MODEL);
340 } catch (InterruptedException e) {
341 return;
342 }
343 }
344}
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RemoteShellExec.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RemoteShellExec.java
new file mode 100644
index 0000000..a7fe221
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/RemoteShellExec.java
@@ -0,0 +1,140 @@
1/*******************************************************************************
2 * Copyright (c) 2013 Intel Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel - initial API and implementation
10 *******************************************************************************/
11package org.yocto.remote.utils;
12
13import java.io.BufferedReader;
14import java.io.IOException;
15import java.io.InputStream;
16import java.io.InputStreamReader;
17import java.io.OutputStream;
18
19import org.eclipse.core.runtime.IProgressMonitor;
20import org.eclipse.rse.core.model.IHost;
21
22public class RemoteShellExec {
23
24 public static final int
25 STATE_NULL = 0,
26 STATE_RUNNING = 1,
27 STATE_EXITED = 2;
28
29 private final String command;
30 private final IHost host;
31
32 private InputStream fInStream;
33 private OutputStream fOutStream;
34 private InputStream fErrStream;
35 private Process remoteShellProcess;
36
37 private int exitCode = 0;
38 private int status = STATE_NULL;
39
40 private final String RETURN_VALUE_TAG = "org.yocto.sdk.remotetools.RVTAG";
41 private final String RETURN_VALUE_CMD = ";echo \"" + RETURN_VALUE_TAG + "$?\"";
42
43 public RemoteShellExec(IHost host, String command) {
44 assert(host != null);
45 this.host = host;
46 this.command = command;
47 }
48
49 public int getStatus() {
50 return status;
51 }
52
53 public int getExitCode() {
54 return exitCode;
55 }
56
57 private void reset() {
58 fInStream = null;
59 fOutStream = null;
60 fErrStream = null;
61
62 remoteShellProcess = null;
63 exitCode = 0;
64 status = STATE_NULL;
65 }
66
67 public InputStream getInputStream() {
68 return fInStream;
69 }
70
71 public OutputStream getOutputStream() {
72 return fOutStream;
73 }
74
75 public InputStream getErrStream() {
76 return fErrStream;
77 }
78
79 public synchronized void start(String prelaunchCmd, String argument, IProgressMonitor monitor) throws Exception {
80 if(status == STATE_RUNNING)
81 return;
82
83 reset();
84 argument = (argument == null ? RETURN_VALUE_CMD : argument + RETURN_VALUE_CMD);
85 remoteShellProcess = RSEHelper.remoteShellExec(this.host, prelaunchCmd, this.command, argument, monitor);
86 fInStream = remoteShellProcess.getInputStream();
87 fOutStream = remoteShellProcess.getOutputStream();
88 fErrStream = remoteShellProcess.getErrorStream();
89 status = STATE_RUNNING;
90 }
91
92 public synchronized void terminate() throws Exception {
93 if(status != STATE_RUNNING || remoteShellProcess != null)
94 return;
95
96 remoteShellProcess.destroy();
97 reset();
98 }
99
100 public int waitFor(IProgressMonitor monitor) throws InterruptedException {
101 while(status == STATE_RUNNING) {
102 if(monitor != null) {
103 if(monitor.isCanceled()) {
104 throw new InterruptedException("User Cancelled");
105 }
106 }
107
108 try {
109 remoteShellProcess.waitFor();
110 }catch(InterruptedException e){
111 //get the return value
112 try {
113 if(fInStream.available() != 0) {
114 BufferedReader in = new BufferedReader(new InputStreamReader(fInStream));
115 String thisline;
116 int idx;
117 while((thisline = in.readLine()) != null) {
118 if(thisline.indexOf(RETURN_VALUE_CMD) == -1) {
119 idx = thisline.indexOf(RETURN_VALUE_TAG);
120 if(idx != -1) {
121 try {
122 exitCode=(new Integer(thisline.substring(idx+RETURN_VALUE_TAG.length()))).intValue();
123 }catch(NumberFormatException e2) {
124 }
125 break;
126 }
127 }
128 }
129 }
130 }catch(IOException e1) {
131 //do nothing
132 }
133 }finally {
134 status=STATE_EXITED;
135 }
136 }
137 return exitCode;
138 }
139}
140
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/ShellSession.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/ShellSession.java
new file mode 100644
index 0000000..0922824
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/ShellSession.java
@@ -0,0 +1,332 @@
1/*****************************************************************************
2 * Copyright (c) 2013 Ken Gilmer
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Ken Gilmer - initial API and implementation
10 * Jessica Zhang - Adopt for Yocto Tools plugin
11 *******************************************************************************/
12package org.yocto.remote.utils;
13
14import java.io.BufferedReader;
15import java.io.File;
16import java.io.IOException;
17import java.io.InputStream;
18import java.io.InputStreamReader;
19import java.io.OutputStream;
20import java.io.OutputStreamWriter;
21import java.lang.reflect.InvocationTargetException;
22import java.util.regex.Matcher;
23import java.util.regex.Pattern;
24
25import org.eclipse.swt.widgets.Display;
26
27public class ShellSession {
28 /**
29 * Bash shell
30 */
31 public static final int SHELL_TYPE_BASH = 1;
32 /**
33 * sh shell
34 */
35 public static final int SHELL_TYPE_SH = 2;
36 private volatile boolean interrupt = false;
37 /**
38 * String used to isolate command execution
39 */
40 public static final String TERMINATOR = "build$";
41 public static final String LT = System.getProperty("line.separator");
42 private Process process;
43
44 private OutputStream pos = null;
45
46 private String shellPath = null;
47 private final String initCmd;
48 private final File root;
49 private final File builddir;
50
51 private OutputStreamWriter out;
52
53 public static String getFilePath(String file) throws IOException {
54 File f = new File(file);
55
56 if (!f.exists() || f.isDirectory()) {
57 throw new IOException("Path passed is not a file: " + file);
58 }
59
60 StringBuffer sb = new StringBuffer();
61
62 String elems[] = file.split(File.separator);
63
64 for (int i = 0; i < elems.length - 1; ++i) {
65 sb.append(elems[i]);
66 sb.append(File.separator);
67 }
68
69 return sb.toString();
70 }
71
72 public ShellSession(int shellType, File root, File builddir, String initCmd, OutputStream out) throws IOException {
73 this.root = root;
74 this.builddir = builddir;
75 this.initCmd = initCmd;
76 if (out == null) {
77 this.out = new OutputStreamWriter(null);
78 } else {
79 this.out = new OutputStreamWriter(out);
80 }
81 if (shellType == SHELL_TYPE_SH) {
82 shellPath = "/bin/sh";
83 }
84 shellPath = "/bin/bash";
85
86 initializeShell();
87 }
88
89 private void initializeShell() throws IOException {
90 process = Runtime.getRuntime().exec(shellPath);
91 pos = process.getOutputStream();
92
93 if (root != null) {
94 execute("cd " + root.getAbsolutePath());
95 }
96
97 if (initCmd != null) {
98 execute("source " + initCmd + " " + builddir.getAbsolutePath());
99 }
100 }
101
102 synchronized
103 public String execute(String command, int[] retCode) throws IOException {
104 String errorMessage = null;
105
106 interrupt = false;
107 out.write(command);
108 out.write(LT);
109
110 sendToProcessAndTerminate(command);
111
112 if (process.getErrorStream().available() > 0) {
113 byte[] msg = new byte[process.getErrorStream().available()];
114
115 process.getErrorStream().read(msg, 0, msg.length);
116 String msg_str = new String(msg);
117 out.write(msg_str);
118 out.write(LT);
119 if (!msg_str.contains("WARNING"))
120 errorMessage = "Error while executing: " + command + LT + new String(msg);
121 }
122
123 BufferedReader br = new BufferedReader(new InputStreamReader(process
124 .getInputStream()));
125
126 StringBuffer sb = new StringBuffer();
127 String line = null;
128
129 while (true) {
130 line = br.readLine();
131 if (line != null) {
132 sb.append(line);
133 sb.append(LT);
134 out.write(line);
135 out.write(LT);
136 }
137 if (line.endsWith(TERMINATOR))
138 break;
139 }
140 if (interrupt) {
141 process.destroy();
142 initializeShell();
143 interrupt = false;
144 }else if (line != null && retCode != null) {
145 try {
146 retCode[0]=Integer.parseInt(line.substring(0,line.lastIndexOf(TERMINATOR)));
147 }catch (NumberFormatException e) {
148 throw new IOException("Can NOT get return code" + command + LT + line);
149 }
150 }
151 out.flush();
152 if (errorMessage != null) {
153 throw new IOException(errorMessage);
154 }
155 return sb.toString();
156 }
157
158 synchronized
159 public void execute(String command) throws IOException {
160 interrupt = false;
161 String errorMessage = null;
162
163 sendToProcessAndTerminate(command);
164 boolean cancel = false;
165 try {
166 InputStream is = process.getInputStream();
167 InputStream es = process.getErrorStream();
168 String info;
169 while (!cancel) {
170 info = null;
171 StringBuffer buffer = new StringBuffer();
172 int c;
173 while (is.available() > 0) {
174 c = is.read();
175 char ch = (char) c;
176 buffer.append(ch);
177 if (ch == '\n') {
178 info = buffer.toString();
179 if (!info.trim().endsWith(TERMINATOR)) {
180 out.write(info);
181 out.write(LT);
182 buffer.delete(0, buffer.length());
183 } else {
184 cancel = true;
185 break;
186 }
187 }
188 }
189 while (es.available() > 0) {
190 c = es.read();
191 char ch = (char) c;
192 buffer.append(ch);
193 if (ch == '\n') {
194 info = buffer.toString();
195 if (!info.contains("WARNING"))
196 errorMessage += info;
197 out.write(info);
198 out.write(LT);
199 buffer.delete(0, buffer.length());
200 }
201 }
202 }
203 } catch (IOException e) {
204 try {
205 throw new InvocationTargetException(e);
206 } catch (InvocationTargetException e1) {
207 e1.printStackTrace();
208 }
209 }
210 out.flush();
211 if (errorMessage != null) {
212 throw new IOException(errorMessage);
213 }
214 if (interrupt) {
215 process.destroy();
216 initializeShell();
217 interrupt = false;
218 }
219 }
220 synchronized
221 public boolean ensureKnownHostKey(String user, String host) throws IOException {
222
223 boolean loadKeysMatch = false;
224 boolean accepted = false;
225 Process proc = Runtime.getRuntime().exec("ssh -o LogLevel=DEBUG3 " + user + "@" + host);
226 Pattern patternLoad = Pattern.compile("^debug3: load_hostkeys: loaded (\\d+) keys");
227 Pattern patternAuthSucceeded = Pattern.compile("^debug1: Authentication succeeded.*");
228
229 try {
230 InputStream es = proc.getErrorStream();
231 String info;
232 while (!loadKeysMatch) {
233 info = null;
234 StringBuffer buffer = new StringBuffer();
235 int c;
236 while (es.available() > 0) {
237 c = es.read();
238 char ch = (char) c;
239 buffer.append(ch);
240 if (ch == '\r') {
241 info = buffer.toString().trim();
242 Matcher m = patternLoad.matcher(info);
243 if(m.matches()) {
244 int keys = new Integer(m.group(1));
245 if (keys == 0) {
246 proc.destroy();
247 DialogRunnable runnable = new DialogRunnable("Host authenticity", "The authenticity of host '" + host + "(" + host + ")' can't be established.\nAre you sure you want to continue connecting ?", DialogRunnable.QUESTION);
248 Display.getDefault().syncExec(runnable);
249 accepted = runnable.result;
250 if (accepted){
251 proc = Runtime.getRuntime().exec("ssh -o StrictHostKeyChecking=no " + user + "@" + host);//add host key to known_hosts
252 try {
253 Thread.sleep(2000); //wait for process to finish
254 } catch (InterruptedException e) {
255 e.printStackTrace();
256 }
257 proc.destroy();
258 } else {
259 Display.getDefault().syncExec( new DialogRunnable("Host authenticity", "Host key verification failed.", DialogRunnable.ERROR));
260 }
261 } else {
262 String errorMsg = "";
263 // wait to check if key is the same and authentication succeeds
264 while (es.available() > 0) {
265 c = es.read();
266 ch = (char) c;
267 buffer.append(ch);
268 if (ch == '\r') {
269 info = buffer.toString().trim();
270 Matcher mAuthS = patternAuthSucceeded.matcher(info);
271 if(mAuthS.matches()) {
272 accepted = true;
273 break;
274 } else {
275 if (!info.startsWith("debug"))
276 errorMsg += info + "\n";
277 }
278 try {
279 Thread.sleep(100);
280 } catch (InterruptedException e) {
281 // TODO Auto-generated catch block
282 e.printStackTrace();
283 }
284 buffer.delete(0, buffer.length());
285 }
286 }
287 if (!accepted && !errorMsg.isEmpty()) {
288 Display.getDefault().syncExec( new DialogRunnable("Host authenticity", errorMsg, DialogRunnable.ERROR));
289 }
290 }
291 loadKeysMatch = true;
292 break;
293 }
294 buffer.delete(0, buffer.length());
295 }
296 }
297 }
298 es.close();
299 } catch (IOException e) {
300 try {
301 throw new InvocationTargetException(e);
302 } catch (InvocationTargetException e1) {
303 e1.printStackTrace();
304 }
305 }
306 return accepted;
307 }
308
309 /**
310 * Send command string to shell process and add special terminator string so
311 * reader knows when output is complete.
312 *
313 * @param command
314 * @throws IOException
315 */
316 private void sendToProcessAndTerminate(String command) throws IOException {
317 pos.write(command.getBytes());
318 pos.write(LT.getBytes());
319 pos.flush();
320 pos.write("echo $?".getBytes());
321 pos.write(TERMINATOR.getBytes());
322 pos.write(LT.getBytes());
323 pos.flush();
324 }
325
326 /**
327 * Interrupt any running processes.
328 */
329 public void interrupt() {
330 interrupt = true;
331 }
332}
diff --git a/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/TerminalHandler.java b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/TerminalHandler.java
new file mode 100644
index 0000000..d4798c2
--- /dev/null
+++ b/plugins/org.yocto.remote.utils/src/org/yocto/remote/utils/TerminalHandler.java
@@ -0,0 +1,132 @@
1/*******************************************************************************
2 * Copyright (c) 2013 Intel Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel - initial API and implementation
10 *******************************************************************************/
11package org.yocto.remote.utils;
12
13import org.eclipse.core.commands.AbstractHandler;
14import org.eclipse.core.commands.ExecutionException;
15import org.eclipse.core.runtime.IProgressMonitor;
16import org.eclipse.core.runtime.NullProgressMonitor;
17import org.eclipse.core.runtime.OperationCanceledException;
18import org.eclipse.jface.dialogs.ProgressMonitorDialog;
19import org.eclipse.jface.operation.IRunnableWithProgress;
20import org.eclipse.rse.core.model.IHost;
21import org.eclipse.rse.internal.terminals.ui.TerminalServiceHelper;
22import org.eclipse.rse.internal.terminals.ui.views.RSETerminalConnector;
23import org.eclipse.rse.internal.terminals.ui.views.TerminalViewTab;
24import org.eclipse.rse.internal.terminals.ui.views.TerminalViewer;
25import org.eclipse.rse.internal.terminals.ui.views.TerminalsUI;
26import org.eclipse.rse.services.terminals.ITerminalShell;
27import org.eclipse.rse.subsystems.terminals.core.ITerminalServiceSubSystem;
28import org.eclipse.rse.subsystems.terminals.core.elements.TerminalElement;
29import org.eclipse.rse.ui.SystemBasePlugin;
30import org.eclipse.swt.custom.CTabItem;
31import org.eclipse.swt.events.DisposeEvent;
32import org.eclipse.swt.events.DisposeListener;
33import org.eclipse.swt.widgets.Shell;
34import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
35import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
36
37abstract public class TerminalHandler extends AbstractHandler {
38
39
40 protected Shell shell;
41
42 protected String changeTerm = "export TERM=vt100;";
43
44 abstract protected String getInitCmd();
45 abstract protected String getConnnectionName();
46 abstract protected String getDialogTitle();
47
48 protected String changeTerm() {
49 return changeTerm;
50 }
51
52 protected ITerminalShell getTerminalShellFromTab(CTabItem item) {
53 ITerminalShell terminalShell = null;
54 ITerminalViewControl terminalViewControl = (ITerminalViewControl) item
55 .getData(TerminalViewTab.DATA_KEY_CONTROL);
56 ITerminalConnector terminalConnector = terminalViewControl
57 .getTerminalConnector();
58 if (terminalConnector instanceof RSETerminalConnector) {
59 RSETerminalConnector rseTerminalConnector = (RSETerminalConnector) terminalConnector;
60 terminalShell = rseTerminalConnector.getTerminalHostShell();
61 }
62 return terminalShell;
63 }
64
65 protected boolean preProcess(final ITerminalServiceSubSystem terminalSubSystem) {
66 if (!terminalSubSystem.isConnected()) {
67 try {
68 ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
69 dialog.run(true, true, new IRunnableWithProgress(){
70 @Override
71 public void run(IProgressMonitor monitor) {
72 monitor.beginTask("Connecting to remote target ...", 100);
73 try {
74 terminalSubSystem.connect(new NullProgressMonitor(), false);
75 monitor.done();
76 } catch (Exception e) {
77 CommonHelper.showErrorDialog("Connection failure", null, e.getMessage());
78 monitor.done();
79
80 }
81 }
82 });
83 } catch (OperationCanceledException e) {
84 // user canceled, return silently
85 return false;
86 } catch (Exception e) {
87 SystemBasePlugin.logError(e.getLocalizedMessage(), e);
88 return false;
89 }
90 } else
91 return true;
92 return false;
93 }
94
95 public void execute(IHost host) throws ExecutionException {
96
97 final ITerminalServiceSubSystem terminalSubSystem = RSEHelper.getTerminalSubSystem(host);
98
99 if (terminalSubSystem != null) {
100 TerminalsUI terminalsUI = TerminalsUI.getInstance();
101 TerminalViewer viewer = terminalsUI.activateTerminalsView();
102 if (preProcess(terminalSubSystem)) {
103 CTabItem tab = viewer.getTabFolder().createTabItem(
104 terminalSubSystem.getHost(), changeTerm() + getInitCmd());
105 //since RSETerminalConnector not exit the shell during the diconnection,
106 //we have manually exit it here
107 try {
108 tab.addDisposeListener(new DisposeListener() {
109 @Override
110 public void widgetDisposed(DisposeEvent e) {
111 Object source = e.getSource();
112 if (source instanceof CTabItem) {
113 CTabItem currentItem = (CTabItem) source;
114 ITerminalShell shell=getTerminalShellFromTab(currentItem);
115 if(shell!=null) {
116 shell.exit();
117 }
118 }
119 }
120 });
121 }catch(Exception e) {
122 e.printStackTrace();
123 }
124 TerminalElement element = TerminalServiceHelper
125 .createTerminalElement(tab, terminalSubSystem);
126 terminalSubSystem.addChild(element);
127
128 }
129 }
130 }
131
132}