/********************************************************* begin of preamble
**
** Copyright (C) 2003-2010 Software- und Organisations-Service GmbH.
** All rights reserved.
**
** This file may be used under the terms of either the
**
** GNU General Public License version 2.0 (GPL)
**
** as published by the Free Software Foundation
** http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
** LICENSE.GPL included in the packaging of this file.
**
** or the
**
** Agreement for Purchase and Licensing
**
** as offered by Software- und Organisations-Service GmbH
** in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package com.sos.VirtualFileSystem.SSH;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Vector;
import org.apache.log4j.Logger;
import sos.spooler.Variable_set;
import com.sos.JSHelper.Basics.JSJobUtilities;
import com.sos.JSHelper.Exceptions.JobSchedulerException;
import com.sos.VirtualFileSystem.DataElements.SOSFileList;
import com.sos.VirtualFileSystem.DataElements.SOSFolderName;
import com.sos.VirtualFileSystem.FTP.SOSVfsFtp;
import com.sos.VirtualFileSystem.Interfaces.ISOSAuthenticationOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSConnection;
import com.sos.VirtualFileSystem.Interfaces.ISOSConnectionOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSSession;
import com.sos.VirtualFileSystem.Interfaces.ISOSShell;
import com.sos.VirtualFileSystem.Interfaces.ISOSShellOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSVFSHandler;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFileSystem;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFolder;
import com.sos.VirtualFileSystem.Options.SOSConnection2OptionsAlternate;
import com.sos.VirtualFileSystem.common.SOSVfsBaseClass;
import com.sos.i18n.Msg;
import com.sos.i18n.Msg.BundleBaseName;
import com.sos.i18n.annotation.I18NResourceBundle;
import com.trilead.ssh2.ChannelCondition;
import com.trilead.ssh2.Connection;
import com.trilead.ssh2.HTTPProxyData;
import com.trilead.ssh2.SFTPException;
import com.trilead.ssh2.SFTPv3Client;
import com.trilead.ssh2.SFTPv3FileAttributes;
import com.trilead.ssh2.SFTPv3FileHandle;
import com.trilead.ssh2.Session;
import com.trilead.ssh2.StreamGobbler;
/**
* \class SOSSSH2SuperClass
*
* \brief SOSSSH2SuperClass -
*
* \details
*
* \code
* .... code goes here ...
* \endcode
*
* <p style="text-align:center">
* <br />---------------------------------------------------------------------------
* <br /> APL/Software GmbH - Berlin
* <br />##### generated by ClaviusXPress (http://www.sos-berlin.com) #########
* <br />---------------------------------------------------------------------------
* </p>
* \author KB
* @version $Id: SOSSSH2TriLeadImpl.java 14789 2011-07-08 15:51:52Z sos $16.05.2010
* \see reference
*
* Created on 16.05.2010 19:17:53
*/
@I18NResourceBundle(baseName = "SOSVirtualFileSystem", defaultLocale = "en")
public class SOSSSH2TriLeadImpl extends SOSVfsBaseClass implements ISOSShell, ISOSVFSHandler, ISOSVirtualFileSystem, ISOSConnection, ISOSSession {
private final String conClassName = "SOSSSH2TriLeadImpl";
private Logger logger = Logger.getLogger(SOSSSH2TriLeadImpl.class);
final private String strEndOfLine = System.getProperty("line.separator");
protected Msg objMsg = new Msg(new BundleBaseName(this.getClass().getAnnotation(I18NResourceBundle.class).baseName()));
public SOSSSH2TriLeadImpl() {
//
}
private ISOSConnectionOptions objCO = null;
private ISOSAuthenticationOptions objAO = null;
private ISOSShellOptions objSO = null;
boolean isAuthenticated = false;
boolean isConnected = false;
/** Line currently being displayed on the shell **/
protected String strCurrentLine = "";
/** ssh connection object */
protected Connection sshConnection = null;
/** ssh session object */
protected Session sshSession = null;
/** Inputstreams for stdout and stderr **/
protected InputStream ipsStdOut;
protected InputStream ipsStdErr;
private boolean flgIsRemoteOSWindows = false;
private SFTPv3Client sftpClient = null;
private RemoteConsumer stdoutConsumer = null;
private RemoteConsumer stderrConsumer = null;
/** Output from stdout and stderr **/
protected StringBuffer strbStdoutOutput;
protected StringBuffer strbStderrOutput;
/** timestamp of the last text from stdin or stderr **/
protected long lngLastTime = 0;
private OutputStream stdin;
private OutputStreamWriter stdinWriter = null;
private Integer exitStatus = null;
private String exitSignal = null;
private Vector<String> vecFilesToDelete = new Vector<String>();
private Vector<String> getFilesToDelete() {
if (vecFilesToDelete == null) {
vecFilesToDelete = new Vector<String>();
}
return vecFilesToDelete;
}
public ISOSConnection Connect(final String pstrHostName, final int pintPortNumber) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::Connect";
try {
isConnected = false;
this.setSshConnection(new Connection(pstrHostName, pintPortNumber));
}
catch (Exception e) {
if (this.getSshConnection() != null)
try {
this.getSshConnection().close();
this.setSshConnection(null);
}
catch (Exception ex) {
}
throw new Exception(e.getMessage());
}
return this;
}
/**
*
* \brief Connect
*
* \details
*
* \return
*
* @return
* @throws Exception
*/
public ISOSConnection Connect() throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::Connect";
try {
isConnected = false;
String strHostName = objCO.getHost().Value();
int intPortNo = objCO.getPort().value();
this.setSshConnection(new Connection(strHostName, intPortNo));
if (objCO.getProxy_host().IsNotEmpty()) {
HTTPProxyData objProxy = null;
if (objCO.getProxy_user().IsEmpty()) {
objProxy = new HTTPProxyData(objCO.getProxy_host().Value(), objCO.getProxy_port().value());
}
else {
objProxy = new HTTPProxyData(objCO.getProxy_host().Value(), objCO.getProxy_port().value(), objCO.getProxy_user().Value(),
objCO.getProxy_password().Value());
}
this.getSshConnection().setProxyData(objProxy);
}
this.getSshConnection().connect();
isConnected = true;
logger.debug(String.format(objMsg.getMsg(SOSVfsFtp.SOSVfs_D_0102), strHostName, intPortNo));
}
catch (Exception e) {
try {
this.setSshConnection(null);
}
catch (Exception ex) {
}
throw e;
}
return this;
}
/**
* Check existence of a file or directory
*
* @param sftpClient
* @param filename
* @return true, if file exists
* @throws Exception
*/
protected boolean sshFileExists(SFTPv3Client psftpClient, String filename) {
try {
SFTPv3FileAttributes attributes = psftpClient.stat(filename);
if (attributes != null) {
return (attributes.isRegularFile() || attributes.isDirectory());
}
else {
return false;
}
}
catch (Exception e) {
return false;
}
}
/**
* Checks if file is a directory
*
* @param sftpClient
* @param filename
* @return true, if filename is a directory
*/
protected boolean isDirectory(SFTPv3Client psftpClient, String filename) {
try {
return psftpClient.stat(filename).isDirectory();
}
catch (Exception e) {
}
return false;
}
/**
* Returns the file size of a file
*
* @param sftpClient
* @param filename
* @return the size of the file
* @throws Exception
*/
protected long getFileSize(SFTPv3Client psftpClient, String filename) throws Exception {
return psftpClient.stat(filename).size.longValue();
}
/**
* Check existence of a file or directory
*
* @param sftpClient
* @param filename
* @return integer representation of file permissions
* @throws Exception
*/
protected int sshFilePermissions(SFTPv3Client psftpClient, String filename) {
try {
SFTPv3FileAttributes attributes = psftpClient.stat(filename);
if (attributes != null) {
return attributes.permissions.intValue();
}
else {
return 0;
}
}
catch (Exception e) {
return 0;
}
}
/**
* normalize / to \ and remove trailing slashes from a path
*
* @param pstrPathName
* @return normalized path
* @throws Exception
*/
@SuppressWarnings("unused")
private String normalizePath(String pstrPathName) throws Exception {
String normalizedPath = pstrPathName.replaceAll("\\\\", "/");
while (normalizedPath.endsWith("\\") || normalizedPath.endsWith("/")) {
normalizedPath = normalizedPath.substring(0, normalizedPath.length() - 1);
}
return normalizedPath;
}
/**
* @return Returns the sshConnection.
*/
protected Connection getSshConnection() {
return sshConnection;
}
protected void setSshConnection(Connection psshConnection) {
String conClosedMsg = "'%1$s' closed";
if (psshConnection == null) {
isConnected = false;
if (sftpClient != null) {
if (this.getFilesToDelete() != null) {
for (String strFileNameToDelete : vecFilesToDelete) {
try {
this.deleteFile(strFileNameToDelete);
}
catch (Exception e) {
e.printStackTrace();
}
}
vecFilesToDelete = null;
}
sftpClient.close();
sftpClient = null;
logger.debug(String.format(conClosedMsg, "sftpClient"));
}
if (stderrConsumer != null) {
stderrConsumer.end();
stderrConsumer = null;
logger.debug(String.format(conClosedMsg, "stderrConsumer"));
}
if (stdoutConsumer != null) {
stdoutConsumer.end();
stdoutConsumer = null;
logger.debug(String.format(conClosedMsg, "stdoutConsumer"));
}
if (sshSession != null) {
sshSession.close();
sshSession = null;
logger.debug(String.format(conClosedMsg, "sshSession"));
}
if (this.sshConnection != null) {
sshConnection.close();
logger.debug(String.format(conClosedMsg, "sshConnection"));
}
}
this.sshConnection = psshConnection;
}
/**
* @return Returns the sshSession.
*/
public Session getSshSession() {
return sshSession;
}
/**
* @param sshSession The sshSession to set.
*/
public void setSshSession(Session psshSession) {
this.sshSession = psshSession;
}
/**
* \todo
* TODO Variable_set mu� hier raus und in den Adapter f�r den JobScheduler
*
*/
private Variable_set params = null;
/**
*
* \brief setJSParam
*
* \details
*
* \return SOSSSH2SuperClass
*
* @param pstrKey
* @param pstrValue
* @return
*/
public SOSSSH2TriLeadImpl setJSParam(final String pstrKey, final String pstrValue) {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::setJSParam";
if (params != null) {
params.set_var(pstrKey, pstrValue);
}
return this;
} // private SOSSSH2SuperClass setJSParam
public SOSSSH2TriLeadImpl setParameters(Variable_set pVariableSet) {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::setParameters";
this.params = pVariableSet;
return this;
} // private void setParameters
/**
*
* \brief createCommandScript
*
* \details
*
* \return File
*
* @param isWindows
* @return
* @throws Exception
*/
public String createScriptFile(final String pstrContent) throws Exception {
try {
String commandScript = pstrContent;
logger.info("pstrContent = " + pstrContent);
if (flgIsRemoteOSWindows == false) {
commandScript = commandScript.replaceAll("(?m)\r", "");
}
logger.info("commandScript = " + pstrContent);
// TODO solve via callback
replaceSchedulerVars(flgIsRemoteOSWindows, commandScript);
File resultFile = File.createTempFile("sos-sshscript", getScriptFileNameSuffix());
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(resultFile)));
out.write(commandScript);
out.flush();
out.close();
resultFile.deleteOnExit();
putFile(resultFile);
String strFileName2Return = resultFile.getName();
if (flgIsRemoteOSWindows == false) {
strFileName2Return = "./" + strFileName2Return;
}
this.getFilesToDelete().add(strFileName2Return);
return strFileName2Return;
}
catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
*
* \brief replaceSchedulerVars
*
* \details
*
* \return void
*
* @param isWindows
*/
protected String replaceSchedulerVars(boolean isWindows, final String pstrString2Modify) {
String strTemp = pstrString2Modify;
if (params != null) {
logger.debug("Replacing task and order parameters...");
String[] paramNames = params.names().split(";");
for (int i = 0; i < paramNames.length; i++) {
String name = paramNames[i];
SignalDebug("Replacing parameter " + name);
String regex = "(?i)";
/**
* \todo
* TODO os-abh�ngigkeit besser herstellen als hier gemacht
*
* TODO Es ist doch eigentlich viel besser, wenn die Variablen
* (zus�tzlich) als Environment-variablen gesetzt werden.
*/
if (isWindows) {
regex += "%SCHEDULER_PARAM_" + name + "%";
}
else {
regex += "\\$\\{?SCHEDULER_PARAM_" + name + "\\}?";
}
strTemp = myReplaceAll(strTemp, regex, params.value(name));
}
}
return strTemp;
}
/**
*
* \brief myReplaceAll
*
* \details
*
* \return String
*
* @param source
* @param what
* @param replacement
* @return
*/
public String myReplaceAll(String source, String what, String replacement) {
String newReplacement = replacement.replaceAll("\\$", "\\\\\\$");
return source.replaceAll("(?m)" + what, newReplacement);
}
@Override
public ISOSConnection getConnection() {
return this;
}
@Override
public ISOSSession getSession() {
return this;
}
@Override
public ISOSConnection Connect(ISOSConnectionOptions pobjConnectionOptions) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::Connect";
this.objCO = pobjConnectionOptions;
if (objCO != null) {
this.Connect();
}
return this;
}
@Override
public void CloseConnection() throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::CloseConnection";
this.setSshConnection(null);
}
/**
*
* \brief Authenticate
*
* \details
*
* \return
*
* @param pobjAO
* @return
* @throws Exception
*/
@Override
public ISOSConnection Authenticate(ISOSAuthenticationOptions pobjAO) throws Exception {
final String conMethodName = conClassName + "::Authenticate";
objAO = pobjAO;
if (objAO.getAuth_method().isPublicKey()) {
/**
* \todo
* TODO File-Handling in der Option-Klasse abhandeln. Return vom Type JSFile einbauen
*/
File authenticationFile = new File(objAO.getAuth_file().Value());
if (authenticationFile.exists() == false)
throw new JobSchedulerException("SOS-SSH-E-010: authentication file does not exist: " + authenticationFile.getCanonicalPath());
if (authenticationFile.canRead() == false)
throw new JobSchedulerException("SOS-SSH-E-020: authentication file not accessible: " + authenticationFile.getCanonicalPath());
isAuthenticated = this.getSshConnection().authenticateWithPublicKey(objAO.getUser().Value(), authenticationFile, objAO.getPassword().Value());
}
else
if (objAO.getAuth_method().isPassword()) {
isAuthenticated = getSshConnection().authenticateWithPassword(objAO.getUser().Value(), objAO.getPassword().Value());
}
if (isAuthenticated == false) {
throw new JobSchedulerException(String.format("SOS-SSH-E-030: %1$s: authentication failed %2$s", conMethodName, objAO.toString()));
}
logger.info(String.format("SOS-SSH-I-040: user %1$s logged in", objAO.getUser().Value()));
return this;
}
@Override
public ISOSVFSHandler getHandler() {
return this;
}
/**
*
* \brief remoteIsWindowsShell
*
* \details
*
* \return boolean
*
* @return
*/
public boolean remoteIsWindowsShell() {
Session objSSHSession = null;
flgIsRemoteOSWindows = false;
try {
// TODO the testcommand should be defined by an option
String checkShellCommand = "echo %ComSpec%";
logger.debug("Opening new session...");
objSSHSession = this.getSshConnection().openSession();
logger.debug("Executing command " + checkShellCommand);
objSSHSession.execCommand(checkShellCommand);
logger.debug("output to stdout for remote command: " + checkShellCommand);
ipsStdOut = new StreamGobbler(objSSHSession.getStdout());
ipsStdErr = new StreamGobbler(objSSHSession.getStderr());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(ipsStdOut));
String stdOut = "";
while (true) {
String line = stdoutReader.readLine();
if (line == null)
break;
logger.debug(line);
stdOut += line;
}
logger.debug("output to stderr for remote command: " + checkShellCommand);
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(ipsStdErr));
while (true) {
String line = stderrReader.readLine();
if (line == null)
break;
logger.debug(line);
}
// TODO The expected result-string for testing the os should be defined by an option
if (stdOut.indexOf("cmd.exe") > -1) {
logger.debug("Remote shell is a Windows shell.");
flgIsRemoteOSWindows = true;
return true;
}
}
catch (Exception e) {
logger.debug("Failed to check if remote system is windows shell: " + e);
}
finally {
if (objSSHSession != null)
try {
objSSHSession.close();
}
catch (Exception e) {
logger.debug("Failed to close session: ", e);
}
}
return false;
}
private String getScriptFileNameSuffix() {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::getScriptFileNameSuffix";
String strSuffix = (flgIsRemoteOSWindows ? ".cmd" : ".sh");
return strSuffix;
} // private String getScriptFileNameSuffix
/**
*
* \brief transferCommandScript
*
* \details
*
* \return File
*
* @param pfleCommandFile
* @param isWindows
* @return
* @throws Exception
*/
public void putFile(File pfleCommandFile) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::putFile";
String suffix = getScriptFileNameSuffix();
String strFileName = pfleCommandFile.getName();
try {
boolean exists = true;
// check if File already exists
while (exists) {
try {
FtpClient().stat(strFileName);
}
catch (SFTPException e) {
logger.debug("Error code when checking file existence: " + e.getServerErrorCode());
exists = false;
}
if (exists) {
logger.debug("file with that name already exists, trying another name...");
/**
* \todo
* TODO Tempfile-NamePrefix variable via options
*/
File fleResultFile = File.createTempFile("sos", suffix);
fleResultFile.delete();
pfleCommandFile.renameTo(fleResultFile);
pfleCommandFile = fleResultFile;
}
}
// set execute permissions for owner
SFTPv3FileHandle fileHandle = this.getFileHandle(strFileName, new Integer(0700));
FileInputStream fis = null;
long offset = 0;
try {
fis = new FileInputStream(pfleCommandFile);
// TODO BufferSize as an Option
byte[] buffer = new byte[1024];
while (true) {
int len = fis.read(buffer, 0, buffer.length);
if (len <= 0)
break;
sftpClient.write(fileHandle, offset, buffer, 0, len);
offset += len;
}
fis.close();
fis = null;
}
catch (Exception e) {
e.printStackTrace();
throw e;
}
finally {
if (fis != null)
try {
fis.close();
fis = null;
}
catch (Exception ex) {
}
}
logger.debug("canonical path: " + sftpClient.canonicalPath(strFileName));
sftpClient.closeFile(fileHandle);
fileHandle = null;
}
catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
*
* \brief getFileHandle
*
* \details
*
* \return SFTPv3FileHandle
*
* @param pstrFileName
* @param pintPermissions
* @return
* @throws Exception
*/
public SFTPv3FileHandle getFileHandle(final String pstrFileName, final Integer pintPermissions) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::setFilePermissions";
SFTPv3FileAttributes attr = new SFTPv3FileAttributes();
attr.permissions = pintPermissions;
SFTPv3FileHandle fileHandle = this.FtpClient().createFileTruncate(pstrFileName, attr);
return fileHandle;
} // private void setFilePermissions
/**
*
* \brief setFilePermissions
*
* \details
*
* \return void
*
* @param pstrFileName
* @param pintPermissions
* @throws Exception
*/
public void setFilePermissions(final String pstrFileName, final Integer pintPermissions) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::setFilePermissions";
SFTPv3FileAttributes attr = new SFTPv3FileAttributes();
attr.permissions = pintPermissions;
@SuppressWarnings("unused")
SFTPv3FileHandle fileHandle = this.FtpClient().createFileTruncate(pstrFileName, attr);
} // private void setFilePermissions
/**
*
* \brief deleteCommandScript
*
* \details
*
* \return void
*
* @param pstrCommandFile
* @throws Exception
*/
public void deleteFile(String pstrCommandFile) throws Exception {
try {
if (isNotEmpty(pstrCommandFile)) {
this.FtpClient().rm(pstrCommandFile);
logger.debug("File deleted : " + pstrCommandFile);
}
}
catch (Exception e) {
logger.error("Failed to delete remote command script: ", e);
}
}
private SFTPv3Client FtpClient() throws Exception {
if (sftpClient == null) {
sftpClient = new SFTPv3Client(this.getSshConnection());
}
return sftpClient;
}
/**
*
* \brief CloseSession
*
* \details
*
* \return
*
* @throws Exception
*/
public void CloseSession() throws Exception {
}
/**
*
* \brief OpenSession
*
* \details
*
* \return
*
* @param pobjShellOptions
* @return
* @throws Exception
*/
public ISOSSession OpenSession(ISOSShellOptions pobjShellOptions) throws Exception {
this.objSO = pobjShellOptions;
if (objSO == null) {
throw new JobSchedulerException("no shell-options specified but mandatory");
}
long loginTimeout = objSO.getSimulate_shell_login_timeout().value();
String strPromptTrigger = objSO.getSimulate_shell_prompt_trigger().Value();
this.setSshSession(this.getSshConnection().openSession());
if (objSO.getSimulate_shell().value() == true) {
logger.debug("Requesting PTY...");
this.getSshSession().requestDumbPTY();
logger.debug("Starting shell...");
this.getSshSession().startShell();
ipsStdOut = getSshSession().getStdout();
ipsStdErr = getSshSession().getStderr();
stdoutConsumer = new RemoteConsumer(strbStdoutOutput, true, ipsStdOut);
stderrConsumer = new RemoteConsumer(strbStderrOutput, false, ipsStdErr);
stdoutConsumer.start();
stderrConsumer.start();
stdin = getSshSession().getStdin();
stdinWriter = new OutputStreamWriter(stdin);
logger.debug("Waiting for login prompt...");
boolean loggedIn = false;
while (!loggedIn) {
if (lngLastTime > 0) {
loggedIn = Check4TimeOutOrPrompt(loginTimeout, strPromptTrigger);
}
}
}
else {
if (objSO.getIgnore_hangup_signal().value() == false) {
// TODO Terminaltype must be an option
sshSession.requestPTY("vt100");
}
}
return this;
}
private boolean Check4TimeOutOrPrompt(final long plngLoginTimeOut, final String pstrPromptTrigger) {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::Check4TimeOutOrPrompt";
long now = System.currentTimeMillis();
if (plngLoginTimeOut > 0 && lngLastTime + plngLoginTimeOut < now) {// kommt nichts mehr
return true;
}
if (pstrPromptTrigger.length() > 0 && strCurrentLine.indexOf(pstrPromptTrigger) != -1) {
logger.debug("Found login prompt " + pstrPromptTrigger);
strCurrentLine = "";
return true;
}
return false;
} // private boolean Check4TimeOutOrPrompt
/**
*
* \brief ExecuteCommand
*
* \details
* Executes a command which is given as parameter.
* \return
*
* @param pstrCmd
* @throws Exception
*/
public void ExecuteCommand(final String pstrCmd) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::ExecuteCommand";
exitStatus = null;
exitSignal = null;
String strCmd = pstrCmd;
long loginTimeout = objSO.getSimulate_shell_login_timeout().value();
String strPromptTrigger = objSO.getSimulate_shell_prompt_trigger().Value();
if (objSO.getSimulate_shell().value() == true) {
stdinWriter.write(strCmd + strEndOfLine);
stdinWriter.flush();
boolean prompt = false;
while (!prompt) {
prompt = Check4TimeOutOrPrompt(loginTimeout, strPromptTrigger);
}
strCurrentLine = "";
logger.debug("output to stdout for remote command: " + strCmd);
logger.debug(strbStdoutOutput.toString());
strbStdoutOutput = new StringBuffer();
}
else {
if (flgIsRemoteOSWindows == false) {
strCmd = "echo $$ && " + strCmd;
}
this.getSshSession().execCommand(strCmd);
logger.debug("output to stdout for remote command: " + strCmd);
ipsStdOut = new StreamGobbler(this.getSshSession().getStdout());
ipsStdErr = new StreamGobbler(this.getSshSession().getStderr());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(ipsStdOut));
strbStdoutOutput = new StringBuffer();
while (true) {
String line = stdoutReader.readLine();
if (line == null)
break;
SignalInfo(line);
// logger.debug(line);
strbStdoutOutput.append(line + strEndOfLine);
}
logger.debug("output to stderr for remote command: " + strCmd);
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(ipsStdErr));
strbStderrOutput = new StringBuffer();
while (true) {
String line = stderrReader.readLine();
if (line == null)
break;
logger.debug(line);
strbStderrOutput.append(line + strEndOfLine);
}
}
// give the session some time to end
// TODO waitForCondition as an Option
@SuppressWarnings("unused")
int res = getSshSession().waitForCondition(ChannelCondition.EOF, 30 * 1000);
try {
exitStatus = this.getSshSession().getExitStatus();
}
catch (Exception e) {
logger.info("could not retrieve exit status, possibly not supported by remote ssh server");
}
try {
exitSignal = this.getSshSession().getExitSignal();
}
catch (Exception e) {
logger.info("could not retrieve exit signal, possibly not supported by remote ssh server");
}
}
@Override
public Integer getExitCode() {
return exitStatus;
}
@Override
public String getExitSignal() {
return exitSignal;
}
@Override
public StringBuffer getStdErr() throws Exception {
return strbStderrOutput;
}
@Override
public StringBuffer getStdOut() throws Exception {
return strbStdoutOutput;
}
/**
* This thread consumes output from the remote server puts it into fields of
* the main class
*/
class RemoteConsumer extends Thread {
private StringBuffer sbuf;
private boolean writeCurrentline = false;
private InputStream stream;
boolean end = false;
RemoteConsumer(StringBuffer buffer, boolean writeCurr, InputStream str) {
this.sbuf = buffer;
this.writeCurrentline = true;
this.stream = str;
}
/**
*
* \brief addText
*
* \details
*
* \return void
*
* @param data
* @param len
*/
private void addText(byte[] data, int len) {
lngLastTime = System.currentTimeMillis();
String outstring = new String(data).substring(0, len);
sbuf.append(outstring);
if (writeCurrentline) {
int newlineIndex = outstring.indexOf(strEndOfLine);
if (newlineIndex > -1) {
String stringAfterNewline = outstring.substring(newlineIndex);
strCurrentLine = stringAfterNewline;
}
else {
strCurrentLine += outstring;
}
}
}
/**
*
* \brief run
*
* \details
*
* \return
*
*/
public void run() {
byte[] buff = new byte[64];
try {
while (!end) {
buff = new byte[8];
int len = stream.read(buff);
if (len == -1)
return;
addText(buff, len);
}
}
catch (Exception e) {
}
}
/**
*
* \brief end
*
* \details
*
* \return void
*
*/
public synchronized void end() {
end = true;
}
} // RemoteConsumer
@Override
public SOSFileList dir(SOSFolderName pobjFolderName) {
// TODO Auto-generated method stub
return null;
}
@Override
public SOSFileList dir(String pathname, int flag) {
// TODO Auto-generated method stub
return null;
}
@Override
public ISOSVirtualFolder mkdir(SOSFolderName pobjFolderName) throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean rmdir(SOSFolderName pobjFolderName) throws IOException {
// TODO Auto-generated method stub
return false;
}
@Override
public void setJSJobUtilites(JSJobUtilities pobjJSJobUtilities) {
// TODO Auto-generated method stub
}
@Override
public ISOSConnection Connect(SOSConnection2OptionsAlternate pobjConnectionOptions) throws Exception {
// TODO Auto-generated method stub
return null;
}
}