/*******************************************************************************
* Copyright (c) 2006, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial Contributors:
* The following IBM employees contributed to the Remote System Explorer
* component that contains this file: David McKnight, Kushal Munir,
* Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
* Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
*
* Contributors:
* Martin Oberhuber (Wind River) - Adapted from LocalServiceCommandShell
* Martin Oberhuber (Wind River) - [225510][api] Fix OutputRefreshJob API leakage
* Anna Dushistova (MontaVista) - [259414][api] refactor the "SSH Shell" to use the generic Terminal->IHostShell converter
* Anna Dushistova (MontaVista) - [261478] Remove SshShellService, SshHostShell (or deprecate and schedule for removal in 3.2)
* David McKnight (IBM) - [272032][ssh][telnet][local] shell output not setting line numbers when available
* Liping Ke (Intel Corp.)- Adapted from org.eclipse.rse.internal.subsystems.shells.ssh.SshServiceCommandShell
* Liping Ke (Intel Corp.)- [246987] Implement TCF Shell/terminal services
*******************************************************************************/
package org.eclipse.tcf.internal.rse.shells;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.rse.core.subsystems.ISubSystem;
import org.eclipse.rse.internal.services.shells.TerminalServiceHostShell;
import org.eclipse.rse.services.shells.IHostOutput;
import org.eclipse.rse.services.shells.IHostShell;
import org.eclipse.rse.services.shells.IHostShellChangeEvent;
import org.eclipse.rse.services.shells.ParsedOutput;
import org.eclipse.rse.services.shells.Patterns;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
import org.eclipse.rse.subsystems.shells.core.model.ISystemOutputRemoteTypes;
import org.eclipse.rse.subsystems.shells.core.model.RemoteError;
import org.eclipse.rse.subsystems.shells.core.model.RemoteOutput;
import org.eclipse.rse.subsystems.shells.core.subsystems.IRemoteCmdSubSystem;
import org.eclipse.rse.subsystems.shells.core.subsystems.IRemoteOutput;
import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.ServiceCommandShell;
@SuppressWarnings("restriction")
public class TCFServiceCommandShell extends ServiceCommandShell {
private Patterns _patterns;
private String _workingDir;
private String _curCommand;
private IRemoteFileSubSystem _fs;
public TCFServiceCommandShell(IRemoteCmdSubSystem cmdSS,
IHostShell hostShell) {
super(cmdSS, hostShell);
_patterns = new Patterns();
_patterns.update("cmd"); //$NON-NLS-1$
ISubSystem[] sses = cmdSS.getHost().getSubSystems();
for (int i = 0; i < sses.length; i++)
{
if (sses[i] instanceof IRemoteFileSubSystem)
{
_fs = (IRemoteFileSubSystem)sses[i];
break;
}
}
}
public Object getContext()
{
String workingDir = _workingDir;
if (workingDir != null && workingDir.length() > 0)
{
try {
return _fs.getRemoteFileObject(workingDir, new NullProgressMonitor());
}
catch (Exception e)
{
e.printStackTrace();
}
}
return null;
}
public String getContextString()
{
return _workingDir;
}
public void shellOutputChanged(IHostShellChangeEvent event)
{
IHostOutput[] lines = event.getLines();
boolean gotCommand = false;
ArrayList<RemoteOutput> outputs = new ArrayList<RemoteOutput>(lines.length);
for (int i = 0; i < lines.length; i++)
{
String line = lines[i].getString();
if (line.endsWith(getPromptCommand())) {
continue; //ignore our synthetic prompt command
}
ParsedOutput parsedMsg = null;
if (!gotCommand && line.equals(_curCommand)) {
gotCommand = true;
continue; //ignore remote command echo
} else
{
try
{
// Bug 160202: Remote shell dies.
if ((_curCommand == null) || (!_curCommand.trim().equals("ls"))) { //$NON-NLS-1$
parsedMsg = _patterns.matchLine(line);
// Bug 160202: Remote shell dies.
if (_curCommand != null) {
String temp = _curCommand.trim();
StringTokenizer tokenizer = new StringTokenizer(temp);
if (tokenizer.countTokens() == 2) {
String token1 = tokenizer.nextToken();
String token2 = tokenizer.nextToken();
if ((token1.equals("ls")) && (token2.indexOf('-') == 0) && (token2.indexOf('l') > 0)) { //$NON-NLS-1$
if (line.startsWith("total")) { //$NON-NLS-1$
parsedMsg = null;
}
}
}
}
}
}
catch (Throwable e) {
e.printStackTrace();
}
}
RemoteOutput output = null;
String type = "stdout"; //$NON-NLS-1$
if (parsedMsg != null) {
type = parsedMsg.type;
}
if (event.isError()) {
output = new RemoteError(this, type);
}
else {
output = new RemoteOutput(this, type);
}
output.setText(line);
if (parsedMsg != null)
{
String file = parsedMsg.file;
if (type.equals(ISystemOutputRemoteTypes.TYPE_PROMPT))
{
_workingDir = file;
output.setAbsolutePath(_workingDir);
}
else if(_workingDir!=null)
{
IPath p = new Path(_workingDir).append(file);
output.setAbsolutePath(p.toString());
}
else
{
output.setAbsolutePath(file);
}
if (parsedMsg.line > 0){
output.setLine(parsedMsg.line);
}
}
addOutput(output);
outputs.add(output);
}
IRemoteOutput[] remoteOutputs = outputs.toArray(new IRemoteOutput[outputs.size()]);
notifyOutputChanged(remoteOutputs, false);
}
/**
* Return the prompt command, such that lines ending with the
* prompt command can be removed from output.
* Should be overridden in case the IHostShell used for this
* service is not an SshHostShell.
* @return String promptCommand
*/
protected String getPromptCommand() {
IHostShell shell = getHostShell();
if (shell instanceof TerminalServiceHostShell) {
return ((TerminalServiceHostShell)shell).getPromptCommand();
}
//return something impossible such that nothing is ever matched
return "\uffff"; //$NON-NLS-1$
}
public void writeToShell(String cmd)
{
_curCommand = cmd;
_patterns.update(cmd);
super.writeToShell(cmd);
}
}