From b5e8fe024dd87c0fd05bc0a168e938a457f2a55f Mon Sep 17 00:00:00 2001
From: Martin Oberhuber < martin.oberhuber@windriver.com>
Date: Tue, 8 Aug 2006 16:57:55 +0000
Subject: [PATCH] Support shell output parsing in ssh connections
---
.../build.properties | 1 +
.../org.eclipse.rse.services.ssh/patterns.dat | 283 ++++++++++++++++++
.../eclipse/rse/services/ssh/Activator.java | 18 +-
.../rse/services/ssh/SshServiceResources.java | 2 +
.../ssh/SshServiceResources.properties | 2 +
.../services/ssh/shell/CommandPattern.java | 60 ++++
.../rse/services/ssh/shell/OutputPattern.java | 98 ++++++
.../rse/services/ssh/shell/ParsedOutput.java | 38 +++
.../rse/services/ssh/shell/Patterns.java | 121 ++++++++
.../rse/services/ssh/shell/SshHostShell.java | 6 +-
.../ssh/shell/SshShellOutputReader.java | 6 +-
.../META-INF/MANIFEST.MF | 1 +
.../shells/ssh/SshServiceCommandShell.java | 161 ++++++++++
.../ssh/SshShellSubSystemConfiguration.java | 8 +
14 files changed, 798 insertions(+), 7 deletions(-)
create mode 100644 rse/plugins/org.eclipse.rse.services.ssh/patterns.dat
create mode 100644 rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/CommandPattern.java
create mode 100644 rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/OutputPattern.java
create mode 100644 rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/ParsedOutput.java
create mode 100644 rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/Patterns.java
create mode 100644 rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshServiceCommandShell.java
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/build.properties b/rse/plugins/org.eclipse.rse.services.ssh/build.properties
index af039aff2e1..1d891040fed 100644
--- a/rse/plugins/org.eclipse.rse.services.ssh/build.properties
+++ b/rse/plugins/org.eclipse.rse.services.ssh/build.properties
@@ -4,6 +4,7 @@ bin.includes = META-INF/,\
about.ini,\
about.mappings,\
about.properties,\
+ patterns.dat,\
plugin.properties,\
readme.txt,\
eclipse32.png
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/patterns.dat b/rse/plugins/org.eclipse.rse.services.ssh/patterns.dat
new file mode 100644
index 00000000000..d469576fc9b
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/patterns.dat
@@ -0,0 +1,283 @@
+################################################################################
+# Copyright (c) 2006 IBM Corporation. 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 RSE services.local/patterns.dat
+################################################################################
+#
+# parse command line output.
+#
+# CLICK THIS LINE TO EDIT THIS FILE (PATTERNS.DAT). (When viewing from the Output view)
+
+command: grep -n.*
+ grep file line pattern =([\w,.,/,(,),\\,\-,\+,\d]*):(\d*):.*
+
+command: grep -.*n.*
+ grep file line pattern =([\w,.,/,(,),\\,\-,\+,\d]*):(\d*):.*
+
+command: grep .*
+ grep file pattern =([\w,.,/,(,)\\,\-,\+,\d]*):.*
+
+
+command: pwd
+ directory file pattern=([\w,.,/,(,),\\,\-,\+,\d,:]*)
+
+command: nmake.*
+ error pattern=NMAKE : .*
+ error file line pattern =([\w,.,\-,\+,(,),\\,:]*)\((\d*):(\d*)\) : error EDC.*
+ error file pattern =[\w,.,\-,\+,(,),\\,:]*\(([\w,.,/,\\]*)\) : error LNK.*
+ error file line pattern=([\w,.,/,\-,\+,(,),\\]*):(\d*):\d*\) : error .*
+ warning file line pattern=([\w,.,/,\-,\+,(,),\\]*)\((\d*):\d*\) : warning .*
+ informational file line pattern=([\w,.,/,\-,\+,(,),\\]*)\((\d*):\d*\) : informational .*
+
+command: make.*
+ error file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(S\).*
+ error file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\",, line (\d*)\.\d*: \d*-\d* \(E\).*
+ warning file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(W\).*
+ informational file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(I\).*
+ warning file line pattern =([\w,.,/,(,),\-,\+,\\]*):(\d*): warning: .*
+ warning file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):\d*: warning: .*
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):.*
+ informational file pattern =([\w,.,/,\\,\-,\+,(,)]*):.*
+ informational file line pattern =In file included from ([\w,.,/,\\,\-,\+,(,)]*):(\d*):
+ #iseries c compiler
+ error file line pattern=[\w,.,/,\\]* Line \d* \"([\w,.,/,\\]*)\", line (\d*)\.\d*: .*
+ error file line pattern=([\w,.,/,\\]*) Line (\d*)\s.*
+ #makefile errors
+ error file line pattern=\"([\w,\.,/,(,),\-,\+,\\]*)\", line (\d*): make:.*
+ #xlc Options warnings
+ warning pattern=\(W\) Option .*
+ #c89 errors
+ error file line pattern=ERROR CBC\d* ([\w,.,/,\\,\-,\+,(,)]*):(\d*) .*
+ warning file line pattern=WARNING CBC\d* ([\w,.,/,\\,\-,\+,(,)]*):(\d*) .*
+ informational pattern=CBC\d*\(I\) .*
+
+command: gmake.*
+ error file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(S\).*
+ warning file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(W\).*
+ informational file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(I\).*
+ warning file line pattern =([\w,.,/,(,),\-,\+,\\]*):(\d*): warning: .*
+ warning file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):\d*: warning: .*
+ informational file line pattern =In file included from ([\w,.,/,\\,\-,\+,(,)]*):(\d*):
+ # ixlc compiler
+ error file line pattern=[\w,.,/,\\]* Line \d* \"([\w,.,/,\\]*)\", line (\d*)\.\d*: .*
+ error file line pattern=([\w,.,/,\\]*) Line (\d*)\s.*
+ # icc compiler
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*),\s(\d*)\.\d*:\s.*
+ error file line pattern =\"([\w,.,/,\\,\-,\+,(,)]*)\",\sline\s(\d*)\.\d*:\s.*
+ #generic
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):.*
+
+command: gcc\s.*
+ error file line pattern=\"([\w,.,/,\\,\-,\+,(,)]*)\", line (\d*)\.\d*: \d*-\d* \(S\).*
+ warning file line pattern=\"([\w,.,/,\\,\-,\+,(,)]*)\", line (\d*)\.\d*: \d*-\d* \(W\).*
+ informational file line pattern=\"([\w,.,/,\\,\-,\+,(,)]*)\", line (\d*)\.\d*: \d*-\d* \(I\).*
+ warning file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*): warning: .*
+ warning file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):\d*: warning: .*
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):.*
+ informational file pattern =([\w,.,/,\\,\-,\+,(,)]*):.*
+ informational file line pattern =In file included from ([\w,.,/,\\,\-,\+,(,)]*):(\d*):
+
+command: cc\s.*
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):.*
+
+command: CC\s.*
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*):(\d*):.*
+
+command: c89.*
+ error file line pattern=ERROR CBC\d* ([\w,.,/,\\,\-,\+,(,)]*):(\d*) .*
+ warning file line pattern=WARNING CBC\d* ([\w,.,/,\\,\-,\+,(,)]*):(\d*) .*
+ informational pattern=CBC\d*\(I\) .*
+
+command: icc.*
+ error file line pattern =([\w,.,/,\\,\-,\+,(,)]*),\s(\d*)\.\d*:\s.*
+ error file line pattern =\"([\w,.,/,\\,\-,\+,(,)]*)\",\sline\s(\d*)\.\d*:\s.*
+
+command: javac.*
+ warning file line pattern=([\w,.,/,\\,\-,\+,(,),:]*):(\d*): warning.*
+ error file line pattern=([\w,.,/,\\,\-,\+,(,),:]*):(\d*):.*
+
+command: .*bat\s.*
+ error file line pattern=\[javac\]\s([\w,.,/,\\,:]*):(\d*):.*
+ error file line pattern=file:([\w,.,/,\\,:]*):(\d*):.*
+
+command: dir.*
+ directory file pattern=\d{2}/\d{2}/\d*\s*\d{2}:\d{2}\s[a,p,AM,PM]+\s*
\s*([\w,.,/,\\,\s,\-,\+,\d]*).*
+ directory file pattern=.*\s*([\w,.,/,\\,\s,\-,\+,\d]*).*
+ file file pattern=\d{2}/\d{2}/\d*\s*\d{2}:\d{2}\s[a,p,AM,PM]+\s*[\d,,]*\s*([\w,.,/,\\,\s,\-,\+,\d]*).*
+ directory file pattern=[\d,/,\\,.,-]+.\s*\d{2}[:,.]\d{2}.\s*\s*([\w,.,/,\\,\s,\-,\+,\d]*)
+ file file pattern=[\d,/,\\,.,-]+.\s*\d{2}[:,.]\d{2}.\s*[\d,,,.]*\s*([\w,.,/,\\,\s,\-,\+,\d]*)
+
+command: ls -l.*
+ file file pattern=-[-,r,w,x]+\s.*\s[\d{4},\d{2}:\d{2}]+,\s([\w,.,/,(,),\\,\-,\+\s,\d]*)
+ file file pattern=l[-,r,w,x]+\s.*\s[\d{4},\d{2}:\d{2}]+,\s([\w,.,/,(,),\\,\-,\+\s,\d]*)\s->\s[\w,.,/,(,),\\,\-,\+\s,\d]*
+ file file pattern=-.*\d{2}:\d{2} ([\w,.,/,(,),\\,\-,\+,\s,\d]*)
+ file file pattern=-.* \d{4} ([\w,.,/,(,),\\,\-,\+,\s,\d]*)
+ file file pattern=l.*\d{2}:\d{2} ([\w,.,/,(,),\\,\-,\+,\s,\d]*)\s->\s[\w,.,/,(,),\\,\-,\+\s,\d]*
+ file file pattern=l.* \d{4} ([\w,.,/,(,),\\,\-,\+,\s,\d]*)\s->\s[\w,.,/,(,),\\,\-,\+\s,\d]*
+ directory file pattern=d.*\d{2}:\d{2} ([\w,.,/,(,),\\,\-,\+\s,\d]*)
+ directory file pattern=d.*\d{4} ([\w,.,/,(,),\\,\-,\+,\s,\d]*)
+
+command: ls -a.*
+ file file pattern=-.*\d{2}:\d{2} ([\w,.,/,(,),\\,\-,\+\s,\d]*)
+ file file pattern=-.* \d{4} ([\w,.,/,(,),\\,\-,\+\s,\d]*)
+ directory file pattern=d.*\d{2}:\d{2} ([\w,.,/,(,),\\,\-,\+\s,\d]*)
+ directory file pattern=d.*\d{4} ([\w,.,/,(,),\\,\-,\+\s,\d]*)
+
+command: ls
+ file file pattern=([\w,\d,.,(,),\-,\+\s]+)
+
+command: ls\s.*
+ file file pattern=([\w,\d,.,(,),\-,\+\s]+)
+
+command: .*
+ prompt file pattern=([\w,.,/,(,),\\,\-,\+,\d,:,\s]*)>.*
+
+command: find .*
+ file file pattern=([\w,.,/,\\,(,),\-]+)
+
+command: env
+ pathenvvar file pattern=PATH\=(.*)
+ libpathenvvar file pattern=LIBPATH\=(.*)
+ libpathenvvar file pattern=LIB\=(.*)
+ envvar pattern=[\w\d]+\=.*
+
+command: ps
+ process pattern=[\s]*[\d]+\s.*
+
+command: ps .*
+ process pattern=[\s]*[\d]+\s.*
+
+command: xl[C,c].*
+ error file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\",, line (\d*)\.\d*: \d*-\d* \(S\).*
+ error file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(E\).*
+ warning file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(W\).*
+ informational file line pattern=\"([\w,.,/,(,),\-,\+,\\]*)\", line (\d*)\.\d*: \d*-\d* \(I\).*
+
+command: ixlc.*
+ error file line pattern=([\w,.,/,\\]*) Line (\d*)\s.*
+ error file line pattern=[\w,.,/,\\]* Line \d* \"([\w,.,/,\\]*)\", line (\d*)\.\d*: .*
+
+command: cat.*patterns.*
+ warning file pattern=# .*(PATTERNS.DAT).*
+ Output pattern=command: .*
+ #statement pattern=#.*
+ statement pattern=.* pattern.*=.*
+
+# special for autoconf
+command: ./bootstrap.sc.*
+ error file line pattern=aclocal: ([\w,.,/,\\]*): (\d*):.*
+ warning file line pattern=([\w,.,/,\\]*):(\d*):.*
+
+command: ./configure.*
+ error file line pattern=./(configure): line (\d*): .*
+
+# How Patterns Work
+# -----------------
+#
+# Patterns are used by the Output View to allow lines that contain file names and
+# perhaps line numbers to be clicked to cause the file location to be opened in an Editor.
+# A line in this file can be 1 of 3 things:
+# 1. An empty line or a comment line (denoted by a # in column 1)
+# 2. The start of a command description (denoted by a 'command:' at the beginning of the line)
+# 3. A pattern description.
+# A formal description of the syntax of this file is included at the bottom of this file.
+#
+#
+# Command Descriptions
+# --------------------
+#
+# A Command Description consists of 2 things: A regular expression that describes the
+# command invocation, and a list of Pattern Descriptions. The regular expression
+# is used to determine what set of Pattern Descriptons to use when parsing command output.
+# For example, if you type the command 'gmake clean', the Command Descriptions are checked and
+# .*make.* would match that command. Therefore the Pattern Descriptions for .*make.* would
+# be used to parse the output of the 'gmake clean'.
+# Note: The first Command Description that is found to match the command is used, so make
+# sure you put the most specific patterns first. For example, if the nmake.* Command
+# Description appeared after .*make.*, then 'nmake install' would be matched by the .*make.*
+# Command Descripton, which is probably not what was intended.
+#
+#
+# Pattern Descriptions
+# --------------------
+#
+# A Pattern Description has the following form:
+# "pattern="
+#
+# where:
+# : The type of object that will be created in the Output View if
+# a line of output matches this pattern.
+#
+# : This is some combination of the words "file" and "line" or nothing
+# at all. This is used to define how the backreferences in the
+# regular expression are to be interpreted. So "file line" means
+# that the first back-reference is a file, and the second is a
+# line number. This may seem unnecessary, but we added this capability
+# in the event that future releases support other types of information
+# that may be useful, such as column info (once we support it).
+#
+# : A regular expression that describes a line of output. Backreferences
+# are used to store (instead of just match) the filename and line
+# number. To store a filename use the backreference ([\w,.,/,\\]*), and
+# to store a line number, use (\d*)
+#
+#
+# Note: The patterns are checked against command output and only exact matches are dealt with
+# So as an example, if you forget the .* (match everything) at the end of a pattern,
+# the match will fail if there are trailing characters in the output not accounted for by
+# the pattern
+#
+#
+# Pattern File Syntax
+# -------------------
+#
+# The pattern file syntax should be easy to grasp by looking at the ones
+# above, but for those of you who like formal grammars, here it is:
+#
+# patterns-file:
+# commands
+#
+# commands:
+# command
+# commands new-line command
+#
+# command:
+# "command:" reg-ex new-line patterns
+#
+# patterns:
+# pattern
+# patterns new-line pattern
+#
+# pattern:
+# command-name match-list "pattern=" reg-ex
+#
+# command-name:
+# String that denotes what type of object will be created if some output matches this pattern
+#
+# match-list:
+# file-or-line
+# match-list space file-or-line
+#
+# file-or-line:
+# "file" | "line"
+#
+# reg-ex:
+# A regular expression
+#
+# new-line:
+# The new-line character \n
+#
+# space:
+# The space character
+
+
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java
index 4b470373e00..77c004b0123 100644
--- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/Activator.java
@@ -15,8 +15,12 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
@@ -61,7 +65,19 @@ public class Activator extends Plugin {
public static Activator getDefault() {
return plugin;
}
-
+
+ /**
+ * Logs an throwable to the log for this plugin.
+ * @param t the Throwable to be logged.
+ */
+ public void logException(Throwable t) {
+ ILog log = getLog();
+ String id = getBundle().getSymbolicName();
+ String message = NLS.bind(SshServiceResources.SshPlugin_Unexpected_Exception, t.getClass().getName(), t.getLocalizedMessage());
+ IStatus status = new Status(IStatus.ERROR, id, 0, message, t);
+ log.log(status);
+ }
+
//----------------------------------------------------
private static Boolean fTracingOn = null;
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.java
index 13e3152d956..3947737b221 100644
--- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.java
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.java
@@ -16,6 +16,8 @@ import org.eclipse.osgi.util.NLS;
public class SshServiceResources extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.rse.services.ssh.SshServiceResources"; //$NON-NLS-1$
+ public static String SshPlugin_Unexpected_Exception;
+
public static String SftpFileService_Description;
public static String SftpFileService_Error_JschSessionLost;
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.properties b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.properties
index d9efcf5d040..88d9556a7f3 100644
--- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.properties
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/SshServiceResources.properties
@@ -9,6 +9,8 @@
# Martin Oberhuber (Wind River) - initial API and implementation
################################################################################
+SshPlugin_Unexpected_Exception=Unexpected {0}: {1}
+
SftpFileService_Name=Ssh / Sftp File Service
SftpFileService_Description=Access a remote file system via Ssh / Sftp protocol
SftpFileService_Error_JschSessionLost=jsch session lost
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/CommandPattern.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/CommandPattern.java
new file mode 100644
index 00000000000..73dafd03404
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/CommandPattern.java
@@ -0,0 +1,60 @@
+/********************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and International Business Machines Corporation. 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 (WindRiver) - adapted from services.local
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.shell;
+
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+public class CommandPattern
+{
+
+
+ private Pattern _pattern;
+ private ArrayList _outputPatterns;
+
+ public CommandPattern(Pattern theCommandPattern)
+ {
+ _pattern = theCommandPattern;
+ _outputPatterns = new ArrayList();
+ }
+
+ public void addOutputPattern(OutputPattern op)
+ {
+ _outputPatterns.add(op);
+ }
+
+ public boolean matchCommand(String theLine)
+ {
+ return _pattern.matcher(theLine).matches();
+ }
+
+ public ParsedOutput matchLine(String theLine)
+ {
+ int patterns = _outputPatterns.size();
+ ParsedOutput matchedOutput;
+ OutputPattern curPattern;
+ for (int i = 0; i < patterns; i++)
+ {
+ curPattern = (OutputPattern) _outputPatterns.get(i);
+ matchedOutput = curPattern.matchLine(theLine);
+ if (matchedOutput != null)
+ return matchedOutput;
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/OutputPattern.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/OutputPattern.java
new file mode 100644
index 00000000000..bb86d09fa76
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/OutputPattern.java
@@ -0,0 +1,98 @@
+/********************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and International Business Machines Corporation. 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 (WindRiver) - adapted from services.local
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.shell;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class OutputPattern
+{
+
+
+ private Pattern _pattern;
+ private String _objType;
+ private ArrayList _matchOrder;
+
+ public OutputPattern(String objType, String matchOrder, Pattern thePattern)
+ {
+ _objType = objType;
+ _pattern = thePattern;
+
+ _matchOrder = new ArrayList();
+ //Here we add a dummy first element to the ArrayList, to mimick how the PatternMatcher stores it's
+ //matches (starting with group 1).
+ _matchOrder.add(null);
+
+ int index = 0;
+ int nextSpace = 0;
+ //Walk the matchOrder string parsing out words and adding them to _matchOrder...Could use StringTokenizer
+ //but this seem much simpler.
+ while ((nextSpace = matchOrder.indexOf(" ", index)) > 0) //$NON-NLS-1$
+ {
+ _matchOrder.add(matchOrder.substring(index, nextSpace).toLowerCase());
+ index = nextSpace;
+ while ((index < matchOrder.length()) && (matchOrder.charAt(index) == ' '))
+ index++;
+ }
+ _matchOrder.add(matchOrder.substring(index, matchOrder.length()).toLowerCase());
+
+ }
+
+ public ParsedOutput matchLine(String theLine)
+ {
+ Matcher matcher = null;
+ try
+ {
+ matcher = _pattern.matcher(theLine);
+ if (!matcher.matches())
+ return null;
+ }
+ catch (StringIndexOutOfBoundsException e)
+ {
+ //Getting an exception here, when theLine is an empty line for some patterns..should probably investigate,
+ //but for now we'll just handle it...
+ return null;
+ }
+
+ String fileString = ""; //$NON-NLS-1$
+ String lineString = ""; //$NON-NLS-1$
+ //Groups start at 1 (group 0 is the entire match).
+ for (int i = 1; i < _matchOrder.size(); i++)
+ {
+ String mStr = (String)_matchOrder.get(i);
+ if (mStr.equals("file")) //$NON-NLS-1$
+ fileString = matcher.group(i);
+ else if (mStr.equals("line")) //$NON-NLS-1$
+ lineString = matcher.group(i);
+ }
+ int line = 1;
+ if (lineString.length() > 0)
+ {
+ try
+ {
+ line = Integer.parseInt(lineString);
+ }
+ catch (NumberFormatException e)
+ {
+ }
+ }
+
+ return new ParsedOutput(_objType, theLine, fileString, line, 1);
+ }
+
+}
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/ParsedOutput.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/ParsedOutput.java
new file mode 100644
index 00000000000..5ec2ccb706a
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/ParsedOutput.java
@@ -0,0 +1,38 @@
+/********************************************************************************
+ * Copyright (c) 2002, 2006 IBM Corporation. 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 (WindRiver) - adapted from services.local
+ ********************************************************************************/
+
+package org.eclipse.rse.services.ssh.shell;
+
+//This is just a convenience object for storing information parsed out of a line of output.
+public class ParsedOutput
+{
+
+
+ public String type;
+ public String text;
+ public String file;
+ public int line;
+ public int col;
+
+ public ParsedOutput (String theType, String theText, String theFile, int theLine, int theColumn)
+ {
+ type = theType;
+ text = theText;
+ file = theFile;
+ line = theLine;
+ col = theColumn;
+ }
+}
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/Patterns.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/Patterns.java
new file mode 100644
index 00000000000..d8ff2dfa19e
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/Patterns.java
@@ -0,0 +1,121 @@
+/********************************************************************************
+ * Copyright (c) 2002, 2006 IBM Corporation. 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 (WindRiver) - adapted from services.local
+ ********************************************************************************/
+package org.eclipse.rse.services.ssh.shell;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Bundle;
+
+import org.eclipse.rse.services.ssh.Activator;
+
+public class Patterns {
+ private ArrayList _theCommands;
+ private String _currentCommand;
+
+ public Patterns() {
+ _theCommands = new ArrayList();
+ parsePatterns();
+ }
+
+ private void parsePatterns() {
+ Bundle bundle = Activator.getDefault().getBundle();
+ URL patterns = bundle.getEntry("/patterns.dat"); //$NON-NLS-1$
+ if (patterns != null) {
+ try {
+ InputStream in = patterns.openStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ _theCommands.clear();
+ String curLine;
+ CommandPattern curCommand = null;
+ while ((curLine = reader.readLine()) != null) {
+ curLine = curLine.trim();
+ // Skip the current line if it is empty or starts with a #
+ if ((curLine.length() == 0) || (curLine.charAt(0) == '#')) {
+ continue;
+ }
+ // Check if this line is the start of a new command section
+ if (curLine.startsWith("command")) { //$NON-NLS-1$
+ int colon = curLine.indexOf(":"); //$NON-NLS-1$
+ // Check that there is something after the colon
+ if (colon == (curLine.length() - 1)) {
+ continue;
+ }
+ Pattern thePattern = Pattern.compile(curLine.substring(colon + 1, curLine.length()).trim());
+ curCommand = new CommandPattern(thePattern);
+ _theCommands.add(curCommand);
+ }
+ // If we get here, the line must be an output pattern
+ else {
+ int firstSpace = curLine.indexOf(" "); //$NON-NLS-1$
+ int patternWord = curLine.indexOf("pattern"); //$NON-NLS-1$
+ int firstEquals = curLine.indexOf("="); //$NON-NLS-1$
+ if ((firstEquals == -1) || (firstEquals == (curLine.length() - 1))) {
+ continue;
+ }
+ String objType = curLine.substring(0, firstSpace);
+ String matchOrder = curLine.substring(firstSpace + 1, patternWord).trim();
+ String patternString = curLine.substring(firstEquals + 1, curLine.length());
+ Pattern thePattern = Pattern.compile(patternString.trim());
+ if (curCommand != null) {
+ curCommand.addOutputPattern(new OutputPattern(objType, matchOrder, thePattern));
+ }
+ }
+ }
+ in.close();
+ } catch (IOException e) {
+ Activator.getDefault().logException(e);
+ }
+ }
+ }
+
+ public void refresh(String theCommand) {
+ _currentCommand = theCommand;
+ parsePatterns();
+ }
+
+ public void update(String theCommand) {
+ _currentCommand = theCommand;
+ }
+
+ public ParsedOutput matchLine(String theLine) {
+ CommandPattern curCommand;
+ ParsedOutput matchedOutput = null;
+ int commands = _theCommands.size();
+ if (_currentCommand != null)
+ {
+
+ for (int i = 0; i < commands; i++)
+ {
+ curCommand = (CommandPattern) _theCommands.get(i);
+ if (curCommand.matchCommand(_currentCommand))
+ {
+ matchedOutput = curCommand.matchLine(theLine);
+ }
+ if (matchedOutput != null)
+ {
+ return matchedOutput;
+ }
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java
index 8c6c9f14768..714b908057d 100644
--- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshHostShell.java
@@ -20,6 +20,7 @@ import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -66,7 +67,10 @@ public class SshHostShell extends AbstractHostShell implements IHostShell {
PrintWriter outputWriter = new PrintWriter(outputStream);
fShellWriter = new SshShellWriterThread(outputWriter);
fChannel.connect();
- if (initialWorkingDirectory!=null && initialWorkingDirectory.length()>0 && !initialWorkingDirectory.equals(".")) { //$NON-NLS-1$
+ if (initialWorkingDirectory!=null && initialWorkingDirectory.length()>0
+ && !initialWorkingDirectory.equals(".") //$NON-NLS-1$
+ && !initialWorkingDirectory.equals("Command Shell") //$NON-NLS-1$ //FIXME workaround for bug 153047
+ ) {
writeToShell("cd "+initialWorkingDirectory); //$NON-NLS-1$
}
} catch(Exception e) {
diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java
index 0632a25cbbf..9ae4b5154c5 100644
--- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java
+++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/services/ssh/shell/SshShellOutputReader.java
@@ -20,9 +20,6 @@ package org.eclipse.rse.services.ssh.shell;
import java.io.BufferedReader;
import java.io.IOException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-
import org.eclipse.rse.services.shells.AbstractHostShellOutputReader;
import org.eclipse.rse.services.shells.IHostShell;
import org.eclipse.rse.services.shells.IHostShellOutputReader;
@@ -142,8 +139,7 @@ public class SshShellOutputReader extends AbstractHostShellOutputReader
//FIXME it's dangerous to return null here since this will end
//our reader thread completely... the exception could just be
//temporary, and we should keep running!
- Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.getDefault().getBundle().getSymbolicName(), 0, "IOException in SshShellOutputReader", e));
- //e.printStackTrace();
+ Activator.getDefault().logException(e);
return null;
}
}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF
index 40bfa66192e..90ac008d6a9 100644
--- a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/META-INF/MANIFEST.MF
@@ -12,6 +12,7 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.rse.connectorservice.ssh,
org.eclipse.rse.services.ssh,
org.eclipse.rse.subsystems.shells.core,
+ org.eclipse.rse.subsystems.files.core,
org.eclipse.rse.shells.ui,
org.eclipse.rse.ui
Eclipse-LazyStart: true
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshServiceCommandShell.java b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshServiceCommandShell.java
new file mode 100644
index 00000000000..44b798b2a17
--- /dev/null
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshServiceCommandShell.java
@@ -0,0 +1,161 @@
+/********************************************************************************
+ * Copyright (c) 2006 IBM Corporation. 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
+ ********************************************************************************/
+
+package org.eclipse.rse.subsystems.shells.ssh;
+
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+import org.eclipse.rse.core.subsystems.ISubSystem;
+import org.eclipse.rse.internal.subsystems.shells.servicesubsystem.OutputRefreshJob;
+import org.eclipse.rse.internal.subsystems.shells.subsystems.RemoteError;
+import org.eclipse.rse.internal.subsystems.shells.subsystems.RemoteOutput;
+import org.eclipse.rse.services.shells.IHostShell;
+import org.eclipse.rse.services.shells.IHostShellChangeEvent;
+import org.eclipse.rse.services.ssh.shell.ParsedOutput;
+import org.eclipse.rse.services.ssh.shell.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.subsystems.IRemoteCmdSubSystem;
+import org.eclipse.rse.subsystems.shells.core.subsystems.IRemoteOutput;
+import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.ServiceCommandShell;
+
+public class SshServiceCommandShell extends ServiceCommandShell implements ISystemOutputRemoteTypes
+{
+ private Patterns _patterns;
+ private String _curCommand;
+ private String _workingDir;
+ private IRemoteFileSubSystem _fs;
+
+ public SshServiceCommandShell(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];
+ }
+ }
+ }
+
+ public Object getContext()
+ {
+ String workingDir = _workingDir;
+ if (workingDir != null && workingDir.length() > 0)
+ {
+ try
+ {
+ return _fs.getRemoteFileObject(workingDir);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ return null;
+
+ }
+
+ public void shellOutputChanged(IHostShellChangeEvent event)
+ {
+ Object[] lines = event.getLines();
+ boolean gotCommand = false;
+ ArrayList outputs = new ArrayList(lines.length);
+ for (int i = 0; i < lines.length; i++)
+ {
+ String line = (String)lines[i];
+ if (line.endsWith(getPromptCommand())) {
+ continue; //ignore our synthetic prompt command
+ }
+
+ ParsedOutput parsedMsg = null;
+ if (!gotCommand && line.equals(_curCommand)) {
+ gotCommand = true;
+ } else {
+ try {
+ parsedMsg = _patterns.matchLine(line);
+ }
+ 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("prompt")) //$NON-NLS-1$
+ {
+ _workingDir = file;
+ output.setAbsolutePath(_workingDir);
+ }
+ else if(_workingDir!=null)
+ {
+ IPath p = new Path(_workingDir).append(file);
+ output.setAbsolutePath(p.toString());
+ }
+ else
+ {
+ output.setAbsolutePath(file);
+ }
+ }
+
+ addOutput(output);
+ outputs.add(output);
+ }
+ if (_lastRefreshJob == null || _lastRefreshJob.isComplete())
+ {
+ IRemoteOutput[] remoteOutputs = (IRemoteOutput[])outputs.toArray(new IRemoteOutput[outputs.size()]);
+ _lastRefreshJob = new OutputRefreshJob(this, remoteOutputs, false);
+ _lastRefreshJob.schedule();
+ }
+ }
+
+ private static final Pattern cdCommands = Pattern.compile("\\A\\s*(cd|chdir|ls)\\b"); //$NON-NLS-1$
+
+ protected String getPromptCommand() {
+ return "echo $PWD'>'"; //$NON-NLS-1$
+ }
+
+ public void writeToShell(String cmd)
+ {
+ _curCommand = cmd;
+ _patterns.update(cmd);
+ if (cdCommands.matcher(cmd).find()) {
+ cmd += "\r\n" + getPromptCommand(); //$NON-NLS-1$
+ }
+ super.writeToShell(cmd);
+
+ }
+
+}
diff --git a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java
index 26e84d01336..ac009632787 100644
--- a/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java
+++ b/rse/plugins/org.eclipse.rse.subsystems.shells.ssh/src/org/eclipse/rse/subsystems/shells/ssh/SshShellSubSystemConfiguration.java
@@ -21,9 +21,12 @@ import org.eclipse.rse.connectorservice.ssh.SshConnectorServiceManager;
import org.eclipse.rse.core.subsystems.IConnectorService;
import org.eclipse.rse.core.subsystems.ISubSystem;
import org.eclipse.rse.model.IHost;
+import org.eclipse.rse.services.shells.IHostShell;
import org.eclipse.rse.services.shells.IShellService;
import org.eclipse.rse.services.ssh.ISshService;
import org.eclipse.rse.services.ssh.shell.SshShellService;
+import org.eclipse.rse.subsystems.shells.core.subsystems.IRemoteCmdSubSystem;
+import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.IServiceCommandShell;
import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.ShellServiceSubSystem;
import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.ShellServiceSubSystemConfiguration;
@@ -72,4 +75,9 @@ public class SshShellSubSystemConfiguration extends
return ISshService.class;
}
+ public IServiceCommandShell createRemoteCommandShell(IRemoteCmdSubSystem cmdSS, IHostShell hostShell)
+ {
+ return new SshServiceCommandShell(cmdSS, hostShell);
+ }
+
}