diff options
Diffstat (limited to 'plugins/org.yocto.remote.utils/src')
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 | *******************************************************************************/ | ||
| 11 | package org.yocto.remote.utils; | ||
| 12 | |||
| 13 | import org.eclipse.ui.plugin.AbstractUIPlugin; | ||
| 14 | import org.osgi.framework.BundleContext; | ||
| 15 | |||
| 16 | /** | ||
| 17 | * The activator class controls the plug-in life cycle | ||
| 18 | */ | ||
| 19 | public 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 | *******************************************************************************/ | ||
| 11 | package org.yocto.remote.utils; | ||
| 12 | |||
| 13 | import org.eclipse.core.runtime.IStatus; | ||
| 14 | import org.eclipse.core.runtime.Status; | ||
| 15 | import org.eclipse.jface.dialogs.ErrorDialog; | ||
| 16 | import org.eclipse.swt.widgets.Display; | ||
| 17 | |||
| 18 | public 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 @@ | |||
| 1 | package org.yocto.remote.utils; | ||
| 2 | |||
| 3 | import org.eclipse.jface.dialogs.MessageDialog; | ||
| 4 | |||
| 5 | public 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 | *******************************************************************************/ | ||
| 11 | package org.yocto.remote.utils; | ||
| 12 | |||
| 13 | import org.eclipse.osgi.util.NLS; | ||
| 14 | |||
| 15 | public 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 | ********************************************************************************/ | ||
| 12 | package org.yocto.remote.utils; | ||
| 13 | |||
| 14 | import java.io.BufferedInputStream; | ||
| 15 | import java.io.BufferedOutputStream; | ||
| 16 | import java.io.File; | ||
| 17 | import java.io.FileOutputStream; | ||
| 18 | import java.io.InputStream; | ||
| 19 | import java.util.ArrayList; | ||
| 20 | import java.util.Arrays; | ||
| 21 | import java.util.Iterator; | ||
| 22 | |||
| 23 | import org.eclipse.core.runtime.CoreException; | ||
| 24 | import org.eclipse.core.runtime.FileLocator; | ||
| 25 | import org.eclipse.core.runtime.IProgressMonitor; | ||
| 26 | import org.eclipse.core.runtime.IStatus; | ||
| 27 | import org.eclipse.core.runtime.MultiStatus; | ||
| 28 | import org.eclipse.core.runtime.OperationCanceledException; | ||
| 29 | import org.eclipse.core.runtime.Path; | ||
| 30 | import org.eclipse.core.runtime.Status; | ||
| 31 | import org.eclipse.core.runtime.SubProgressMonitor; | ||
| 32 | import org.eclipse.osgi.util.NLS; | ||
| 33 | import org.eclipse.rse.core.IRSECoreStatusCodes; | ||
| 34 | import org.eclipse.rse.core.IRSESystemType; | ||
| 35 | import org.eclipse.rse.core.RSECorePlugin; | ||
| 36 | import org.eclipse.rse.core.model.IHost; | ||
| 37 | import org.eclipse.rse.core.model.ISubSystemConfigurationCategories; | ||
| 38 | import org.eclipse.rse.core.model.ISystemRegistry; | ||
| 39 | import org.eclipse.rse.core.subsystems.ISubSystem; | ||
| 40 | import org.eclipse.rse.services.IService; | ||
| 41 | import org.eclipse.rse.services.files.IFileService; | ||
| 42 | import org.eclipse.rse.services.shells.HostShellProcessAdapter; | ||
| 43 | import org.eclipse.rse.services.shells.IHostShell; | ||
| 44 | import org.eclipse.rse.services.shells.IShellService; | ||
| 45 | import org.eclipse.rse.subsystems.files.core.servicesubsystem.IFileServiceSubSystem; | ||
| 46 | import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.IShellServiceSubSystem; | ||
| 47 | import org.eclipse.rse.subsystems.terminals.core.ITerminalServiceSubSystem; | ||
| 48 | |||
| 49 | public 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 | *******************************************************************************/ | ||
| 11 | package org.yocto.remote.utils; | ||
| 12 | |||
| 13 | import java.io.BufferedReader; | ||
| 14 | import java.io.IOException; | ||
| 15 | import java.io.InputStream; | ||
| 16 | import java.io.InputStreamReader; | ||
| 17 | import java.io.OutputStream; | ||
| 18 | |||
| 19 | import org.eclipse.core.runtime.IProgressMonitor; | ||
| 20 | import org.eclipse.rse.core.model.IHost; | ||
| 21 | |||
| 22 | public 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 | *******************************************************************************/ | ||
| 12 | package org.yocto.remote.utils; | ||
| 13 | |||
| 14 | import java.io.BufferedReader; | ||
| 15 | import java.io.File; | ||
| 16 | import java.io.IOException; | ||
| 17 | import java.io.InputStream; | ||
| 18 | import java.io.InputStreamReader; | ||
| 19 | import java.io.OutputStream; | ||
| 20 | import java.io.OutputStreamWriter; | ||
| 21 | import java.lang.reflect.InvocationTargetException; | ||
| 22 | import java.util.regex.Matcher; | ||
| 23 | import java.util.regex.Pattern; | ||
| 24 | |||
| 25 | import org.eclipse.swt.widgets.Display; | ||
| 26 | |||
| 27 | public 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 | *******************************************************************************/ | ||
| 11 | package org.yocto.remote.utils; | ||
| 12 | |||
| 13 | import org.eclipse.core.commands.AbstractHandler; | ||
| 14 | import org.eclipse.core.commands.ExecutionException; | ||
| 15 | import org.eclipse.core.runtime.IProgressMonitor; | ||
| 16 | import org.eclipse.core.runtime.NullProgressMonitor; | ||
| 17 | import org.eclipse.core.runtime.OperationCanceledException; | ||
| 18 | import org.eclipse.jface.dialogs.ProgressMonitorDialog; | ||
| 19 | import org.eclipse.jface.operation.IRunnableWithProgress; | ||
| 20 | import org.eclipse.rse.core.model.IHost; | ||
| 21 | import org.eclipse.rse.internal.terminals.ui.TerminalServiceHelper; | ||
| 22 | import org.eclipse.rse.internal.terminals.ui.views.RSETerminalConnector; | ||
| 23 | import org.eclipse.rse.internal.terminals.ui.views.TerminalViewTab; | ||
| 24 | import org.eclipse.rse.internal.terminals.ui.views.TerminalViewer; | ||
| 25 | import org.eclipse.rse.internal.terminals.ui.views.TerminalsUI; | ||
| 26 | import org.eclipse.rse.services.terminals.ITerminalShell; | ||
| 27 | import org.eclipse.rse.subsystems.terminals.core.ITerminalServiceSubSystem; | ||
| 28 | import org.eclipse.rse.subsystems.terminals.core.elements.TerminalElement; | ||
| 29 | import org.eclipse.rse.ui.SystemBasePlugin; | ||
| 30 | import org.eclipse.swt.custom.CTabItem; | ||
| 31 | import org.eclipse.swt.events.DisposeEvent; | ||
| 32 | import org.eclipse.swt.events.DisposeListener; | ||
| 33 | import org.eclipse.swt.widgets.Shell; | ||
| 34 | import org.eclipse.tm.internal.terminal.control.ITerminalViewControl; | ||
| 35 | import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector; | ||
| 36 | |||
| 37 | abstract 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 | } | ||
