/********************************************************* 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 sos.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import sos.configuration.SOSConfiguration;
import sos.util.SOSArguments;
import sos.util.SOSClassUtil;
import sos.util.SOSCommandline;
import sos.util.SOSLogger;
import sos.util.SOSStandardLogger;
import sos.util.SOSString;
import com.sos.JSHelper.Basics.JSVersionInfo;
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;
/**
*
* Send/Receive files by FTP/FTPS/SFTP and execute commands by SSH
*
* This program is used as a standalone, synchroneous File Transfer solution.
* For asynchroneous file transfer see the respective standard jobs with the Job Scheduler.
*
* File Transfer Features
*
* - Send and receive files by FTP to/from some target host.
* - Send and receive files by SFTP to/from some target host.
* - Execute commands by SSH on some host.
* - Send files by FTP or SFTP to a "jump host" and forward them by FTP or SFTP to a target host.
* Different transfer protocols can be used between localhost and "jump_host" and between "jump_host" and target host.
* - Receive files from a remote host by FTP or SFTP to a "jump host" and forward them by FTP or SFTP to the local host.
* Different protocols can be used for transfer between the hosts.
* - Both password and publickey authentication are supported for SFTP.
* - The parameterization is effected by command line parameters and by configuration files.
* - All parameters are specified on the localhost exclusively, this applies in the same way when using
* a "jump host" as local parameters are dynamically forwarded to the "jump host".
* - Logging and error handling are provided, errors are detected on a per file basis.
*
* - Security: no configuration files are used on the "jump host" (except for private key files that were used to access a target host);
* no passwords are stored on the "jump host"; no use is made of system proxy functionalities.
*
* @author andreas.pueschel@sos-berlin.com
* @author mueruevet.oeksuez@sos-berlin.com
* @version 2009-09-22
* @see documentation ./doc/sosftp.xml
*
*/
abstract public class SOSFTPCommand {
public static final String USE_PATH_AND_FILE_NAME_4_MATCHING = "use_path_and_file_name_4_matching";
public static final String CHECK_SERVER_FEATURES = "check_server_features";
public static final String CONVERT_UMLAUTE = "convert_umlaute";
public static final String FILENAME_ENCODING = "Filename_encoding";
public static final String CONTROL_ENCODING = "control_encoding";
public static final String PRE_FTP_COMMANDS = "pre_ftp_commands";
private static String conClassName = "SOSFTPCommandReceive";
protected static final String conNewLine = "\n";
protected static final String conRegExpBackslash = "\\\\";
protected static final String conRegExpAllChars = ".*";
protected SOSFTP sosftp = null;
protected String strPreFtpCommands = "";
protected boolean flgCheckServerFeatures = false;
protected boolean flgUsePathAndFileName4Matching = false;
protected String strControlEncoding = "";
protected String strFileNameEncoding = "";
protected boolean flgConvertUmlaute = false;
/** The FTP server will always reply the ftp error codes,
* see http://www.the-eggman.com/seminars/ftp_error_codes.html */
public static final int ERROR_CODE = 300;
/** default command delimiter */
protected final static String DEFAULT_COMMAND_DELIMITER = "%%";
/** sos.util.SOSString Object */
protected static SOSString sosString = new SOSString();
/** sos.util.SOSLogger Object */
private static SOSLogger logger = null;
/** optional mail configuration */
protected String mailSMTP = "localhost";
protected String mailPortNumber = "25";
protected String mailFrom = "SOSFTP";
protected String mailQueueDir = "";
/** array of commands that have been separated by the commandDelimiter */
protected String[] commands = {};
/** ignore errors reported by the exit status of commands */
protected boolean ignoreError = false;
/** ignore signals terminating remote execution */
protected boolean ignoreSignal = false;
/** ignore output to stderr */
protected boolean ignoreStderr = false;
/** timestamp of the last text from stdin or stderr **/
protected long lasttime = 0;
/** regular expression for delimiter of multiple commands specified as job or order parameter */
protected String commandDelimiter = DEFAULT_COMMAND_DELIMITER;
/** ssh connection object */
private Connection sshConnection = null;
/** ssh session object */
protected Session sshSession = null;
/** Inputstreams for stdout and stderr **/
protected InputStream stdout = null;
protected InputStream stderr = null;
/** Script for a command which will be submitted and then executed **/
protected String commandScript = "";
/** Line currently being displayed on the shell **/
protected String currentLine = "";
/** remote host name or ip address */
protected String host = "";
/** remote ssh2 port */
// protected int port = 0;
protected int port = 21; // JS-649
/** user name on remote host */
protected String user = "";
/** for publickey authentication this password secures the authentication file, for password authentication this is the password */
protected String password = "";
/** optional proxy configuration */
protected String proxyHost = "";
protected int proxyPort = 0;
protected String proxyUser = "";
protected String proxyPassword = "";
/** key file: ~/.ssh/id_rsa or ~/.ssh/id_dsa */
protected String authenticationFilename = "";
/** authentication method: publickey, password */
protected String authenticationMethod = "publickey";
/** Program Arguments */
protected Properties arguments = null;
/** hilfgsvariable, gibt an ob ein jump Host existiert */
protected boolean jump = false;
/** temporary Directory of jump host:
* Security: no configuration files are used on the "jump host"
* (except for private key files that were used to access a target host);
* no passwords are stored on the "jump host"; no use is made of system proxy functionalities.
*/
protected static String tempJumpRemoteDir = "";
/**
* The value of this parameter specifies an post command that is executed by the remote host.
*/
protected String postCommands = "";
/**
* Anlegen einer tempor�ren Historien Datei, die anschliessend in der globalen Historie Datei (siehe historyFile)
* angeh�ngt wird
*/
private static File tempHistoryFile = null;
/**
* Diese Parameter gibt die globale Historien Dateinamen an.
*/
private static File historyFile = null;
/**
* java.io.BufferedWriter Objekt for history
*/
private static BufferedWriter history = null;
/**
* Angabe einer Default Mandatory, wenn keine Parameter mandator angegeben wurde.
* Der Mandator wird in die Historie geschrieben
*/
private String defaultMandator = "SOS";
/**
* Felder der Historiendatei
*/
private String historyFields = "guid;mandator;transfer_timestamp;pid;ppid;operation;localhost;localhost_ip;local_user;remote_host;remote_host_ip;remote_user;protocol;port;local_dir;remote_dir;local_filename;remote_filename;file_size;md5;status;last_error_message;log_filename";
/**
* neue Felder der Historiendatei. Der Aufbau ist wie folgt: historyFields;<history_entry_>;newHistoryFields
*/
private String newHistoryFields = "jump_host;jump_host_ip;jump_port;jump_protocol;jump_user";
/**
* Alle Parameter, die mit history_entry_ anfangen werden mit in historie geschrieben.
*/
@SuppressWarnings("rawtypes")
private static ArrayList historyEntrys = new ArrayList();
/**
* hilfsbariable, damit der banner header einmal geschrieben wird
*/
private boolean writeBannerHeader = false;
/**Es wird eine scheduler Signal geschickt wenn ein Parameter scheduler_host, scheduler_port, scheduler_messages angegeben wurde */
private boolean sendSchedulerSignale = false;
/**Account for authorization at the FTP server */
protected String account = "";
/** sos.net.SOSFileTransfer */
protected SOSFileTransfer ftpClient = null;
/** check is ftp Connect*/
protected boolean isLoggedIn = false;
/** Default Bannerheader*/
protected String bannerHeader =
"\n*************************************************************************"
+ "\n* *"
+ "\n* SOSFTP - Managed File Transfer Utility *"
+ "\n* -------------------------------------- *"
+ "\n* *"
+ "\n*************************************************************************"
+ "\nversion = %{version}"
+ "\ndate = %{date} %{time}"
+ "\noperation = %{operation}"
+ "\nprotocol = %{protocol}"
+ "\nport = %{port}"
+ "\nfile specification = %{file_spec}"
+ "\nfile path = %{file_path}"
+ "\nsource host = %{localhost} (%{local_host_ip})"
+ "\nlocal directory = %{local_dir}"
+ "\njump host = %{jump_host}"
+ "\ntarget host = %{host} (%{remote_host_ip})"
+ "\ntarget directory = %{remote_dir}"
+ "\npid = %{current_pid}"
+ "\nppid = %{ppid}"
+ "\n*************************************************************************";
/** Default Banner Footer*/
protected String bannerFooter = "\n*************************************************************************"
+ "\n execution status = %{status}"
+ "\n successful transfers = %{successful_transfers}"
+ "\n failed transfers = %{failed_transfers}"
+ "\n last error = %{last_error}"
+ "\n*************************************************************************";
protected boolean utf8Supported = false;
protected boolean restSupported = false;
protected boolean mlsdSupported = false;
protected boolean modezSupported = false;
protected boolean dataChannelEncrypted = false;
// /** 1. Stelle: ist die Major Version. wir erh�hen Sie nur nach Absprache */
// private static int major = 1;
// /** 2. Stelle: ist die Minor Version: wir erh�hen Sie nur nach Absprache */
// private static int minor = 0;
// /**3. Stelle: ist die Bug Fix Nummer: Sie erh�hen Sie automatisch bei jeder Auslieferung
// * 1 = 23.01.2009
// * a) Erstellen der Versionsnummer;
// * b) Jeweils beim polling interval soll die Meldung ausgegeben werden.
// * c) -skip_transfer: falsche Ausgabe im Protokoll
// *
// * 2 = 26.01.2009
// * a) File Transfer Transactions -> transaktionsabh�ngige �bertragung, d.h. l�schen oder umbennen der transferierten dateien (atomic
// suffx)
// * erfolgt erst dann, wenn alle Dateien transferiert wurden.
// *
// * 3 = 11.02.2009
// * a) Different file operations within one session.
// *
// * 4 = 12.02.2009
// * a) Substitution von Environment-Variablen in Konfigurationsdateien
// *
// * 5 = 19.02.2009
// * a)-file_spec2=.*\.xml$::parameter_set_2 sollen jetzt mit doppelpunkt
// * b) Korrektur von Polling
// *
// * 6 = 20.02.2009
// *
// * a) schedulerMessages -> die mandantenspezifische Parameter werden an scheduler_meaages ohne den Pr�fix
// * history_entry_ �bergeben
// *
// * 7 = 24.02.2009
// *
// * a) Die Integration eines neuen Mechanismus, um Kennw�rter via Shell Script dynamisch einzulesen.
// *
// * 8 = 09.03.2009
// *
// * a) Erweiterung f�r 3: unterschiedliche Parametrisierun mit unterschiedliche operation (z.B. einmal mit send und einmal mit receive)
// *
// * 9 = 12.03.2009
// *
// * a) neue Parameter: -transfer_success=parameter_set_1 und -transfer_error=parameter_set_1; Beim erfolgreichen transfer soll
// transfer_success
// * durchgef�hrt werden im Fehlerfall soll transfer_error durchgef�hrt werden
// *
// * 10 = 17.04.2009
// *
// * a) operation = install -> neues Unterordner "doc" f�r das Installieren der Unterverzeichnis;
// * b) operation = install -> neue Dateien readme.txt und ThirdParty.txt
// * c) Realisierung der Gross und Kleinschreiben der transferierten Dateinamen: Parameter -replacement=[filename:uppercase] bzw.
// -replacement=[filename:lowercase]
// *
// * 11 = 28.07.2009
// *
// * a) operation = send -> Parameter poll_interval und poll_timeout werden jetzt auch f�r operation=send verwendet
// * b) neue Parameter: testmode=yes|no
// *
// * 12 = 04.09.2009
// * a) neue History Felder jump_host;jump_host_ip;jump_port;jump_protocol;jump_user
// * b) file_spec_num -> Abarbeitung nach Reigenfolge
// *
// * 13 = 16.09.2009
// * a) JIRA-6: jump host: remove_files/delete don't work
// *
// * 14 = 24.09.3009
// * a) JIRA-5 history lock file
// *
// * 15 = 29.09.3009
// * a) JIRA-5 history lock file funktioniert jetzt auch unter windows
// *
// * 16 = 27.10.3009
// * a) JIRA-5 getParentId.exe wird jetzt verwendet
// *
// * 17 = 19.11.2009
// * a) mergen von Scheduler Parameter
// *
// * 18 = 19.11.2009
// * a) parameter simulate_shell ... l�schen
// *
// * 18 -> 19 in sf 05.01.2010
// * a) Parameter include funktioniert nicht
// *
// * 19 = 15.12.2009
// * a) Redesign auf Configuration/Parametern
// *
// * 20 = 29.01.2010
// * a) SOSFTPCommand so anpassen, das es auch im SchedulerBetrieb arbeitet
// * sos.scheduler.ftp.SOSSchedulerFTPSend.java
// * sos.scheduler.ftp.SOSSchedulerFTPReceive.java
// * sos.scheduler.job.JobSchedulerSSHJob.java
// * 21 = 10.02.2010
// * a)Anpassung der operation=install
// * -> wegen Redesign sind 4 neue Bibliotheken hinzugekommen: sos.xml.jar; xercesImpl.jar; xml-apis.jar; sos.connection.jar;
// * -> diese Bibliotheken werden bei der operation=install mitgeliefert.
// *
// * 22 = 29.03.2009
// * a) die Bibliotheken haben jetzt revisionsnummer und datum. operation=install muss angepasst werden
// * b) neue Bibiliothek com.sos.configuration.jar
// *
// *
// */
// private static int bugFix = 22;
@SuppressWarnings("rawtypes")
protected static ArrayList transactionalHistoryFile = null;
protected ArrayList transactionalSchedulerRequestFile = null;
/** Hilfsvariable. Hier werden alle urspr�ngliche/unver�nderte Parametern zum Historienschreiben geschrieben.
* Es geht mehr um die Jump Parameter*/
private static Properties originalParam = null;
/**
* All files should appear in the target system as one atomic transaction.
* Approach: Transfer all files using the �atomic_transfer parameter that
* add a suffix to the file names. Then, having transferred all files
* successfully, they would be renamed. This is approx.
* the same as the current operation for atomic transfers, however,
* the renaming should be done for all files and not on a per file basis.
*
* This feature should consider the �remove_files parameter,
* i.e. files should be removed after successfule transfer of all files,
* not on a per file basis
*/
protected static boolean transActional = false;
/**
* Parameter die nicht an jum Host �bergeben werden d�rfen
*/
private static ArrayList noJumpParameter = new ArrayList();
/**
* Substitution von Environment-Variablen in Konfigurationsdateien
*/
private static Properties environment = null;
/**
* -transfer_success=parameter_set_1 und -transfer_error=parameter_set_1; Beim erfolgreichen transfer soll transfer_success
* durchgef�hrt werden im Fehlerfall soll transfer_error durchgef�hrt werden.
* Die Argumente werden hier im listen gesammelt um im Fehlerfall bzw. Erfolgsplan alles auszuf�hren.
*/
protected static ArrayList listOfSuccessTransfer = null;
protected static ArrayList listOfErrorTransfer = null;
private static SOSFTPCommand ftpCommand = null;
protected static boolean banner = true;
/** */
private File lockHistoryFile = null;
/**
* Falls der SOSFTP im scheduler umgebung betrieben wird, werden alle Scheduler parameter aus der Umgebungsvariable
* SCHEDULER_PARAMS_<parameter> ausgelesen und den sosftp als Argument �bergeben
*/
private static Properties schedulerParams = new Properties();
private static SOSConfiguration sosConfiguration = null;
// Liste der transferierten Dateien
protected Vector<File> transferFileList = new Vector<File>();
public static Vector<String> filelist = null;
protected Vector<String> filelisttmp = null;
protected static Object schedulerJob = null;
protected static String SSHJOBNAME = "sos.scheduler.job.JobSchedulerSSHJob";
// Does not work with includes. ur 20101117
// public static String REQUIRED_DEFAULT_PARAMETERS_FILENAME = "sos/net/sosftp/Configuration.xml";
public static String REQUIRED_DEFAULT_PARAMETERS_FILENAME = "sos/net/sosftp/Configuration_norequire.xml";
private static String REQUIRED_DEFAULT_PARAMETERS_FILENAME_NOREQUIRE = "sos/net/sosftp/Configuration_norequire.xml";
private static Integer exitStatus = null;
/**
* Constructor
* @param settingsFile
* @param settingsSection
* @param logger
* @param arguments_
*/
public SOSFTPCommand(SOSLogger logger, Properties arguments_) throws Exception {
this.setLogger(logger);
this.arguments = arguments_;
arguments.put("version", getVersion());
try {
String pid = getPids();
if (sosString.parseToString(pid).length() > 0)
arguments.put("current_pid", pid);
}
catch (Exception e) {
try {
// getLogger().info("could not get PID, cause: " + e.toString());
}
catch (Exception ex) {
}
// throw new Exception("could not get PID, cause: " + e.toString());
}
}
public SOSFTPCommand(SOSConfiguration sosConfiguration_, SOSLogger logger) throws Exception {
this.setLogger(logger);
sosConfiguration = sosConfiguration_;
this.arguments = sosConfiguration.getParameterAsProperties();
arguments.put("version", getVersion());
try {
String pid = getPids();
if (sosString.parseToString(pid).length() > 0)
arguments.put("current_pid", pid);
}
catch (Exception e) {
try {
// getLogger().info("could not get PID, cause: " + e.toString());
}
catch (Exception ex) {
}
// throw new Exception("could not get PID, cause: " + e.toString());
}
}
public void setSchedulerJob(Object schedulerJob_) {
schedulerJob = schedulerJob_;
}
/**
* Receive files by FTP/SFTP from a remote server
*
* @return boolean
* @throws Exception
*/
protected boolean receive() throws Exception {
return false;
}
/**
* Sends files by FTP/SFTP to a remote server
*
* @return boolean
* @throws Exception
*/
protected boolean send() throws Exception {
return false;
}
/**
* Execute a command by SSH on a remote server
*
* @return boolean
* @throws Exception
*/
public boolean execute() throws Exception {
StringBuffer stderrOutput = new StringBuffer();
String commandScriptFileName = "";
try {
getLogger().debug1("calling " + sos.util.SOSClassUtil.getMethodName());
try { // to fetch parameters, order parameters have precedence to job parameters
if (this.getLogger() == null)
this.setLogger(new SOSStandardLogger(0));
readSettings(false);
// get basic authentication parameters
this.getBaseParameters();
if (!jump) {
if (sosString.parseToString(arguments.get("jump_command_delimiter")).length() > 0) {
this.setCommandDelimiter(sosString.parseToString(arguments.get("jump_command_delimiter")));
getLogger().debug1(".. parameter [jump_command_delimiter]: " + this.getCommandDelimiter());
}
else {
this.setCommandDelimiter(DEFAULT_COMMAND_DELIMITER);
}
if (sosString.parseToString(arguments.get("jump_command_script")).length() > 0) {
commandScript = sosString.parseToString(arguments.get("jump_command_script"));
getLogger().debug1(".. parameter [jump_command_script]: " + commandScript);
}
if (sosString.parseToString(arguments.get("jump_command_script_file")).length() > 0) {
commandScriptFileName = sosString.parseToString(arguments.get("jump_command_script_file"));
getLogger().debug1(".. parameter [jump_command_script_file]: " + commandScriptFileName);
}
if (arguments.containsKey("xx_make_temp_directory_success_transfer_xx")) {
if (sosString.parseToString(arguments.get("command")).length() > 0) {
this.setCommands(sosString.parseToString(arguments.get("command")).split(this.getCommandDelimiter()));
getLogger().debug1(".. parameter [jump_command]: " + sosString.parseToString(arguments.get("command")));
}
}
else
if (!arguments.contains("xx_make_temp_directory_xx")) {
if (sosString.parseToString(arguments.get("jump_command")).length() > 0) {
this.setCommands(sosString.parseToString(arguments.get("jump_command")).split(this.getCommandDelimiter()));
getLogger().debug1(".. parameter [jump_command]: " + sosString.parseToString(arguments.get("jump_command")));
}
else
if (commandScript.length() == 0 && commandScriptFileName.length() == 0) {
throw new Exception(
"no command (or jump_command_script or jump_command_script_file) has been specified for parameter [jump_command]");
}
}
}
if (sosString.parseToString(arguments.get("jump_ignore_error")).length() > 0) {
if (sosString.parseToBoolean(arguments.get("jump_ignore_error"))) {
ignoreError = true;
}
else {
ignoreError = false;
}
getLogger().debug1(".. parameter [jump_ignore_error]: " + ignoreError);
}
else {
ignoreError = false;
}
if (sosString.parseToString(arguments.get("jump_ignore_signal")).length() > 0) {
if (sosString.parseToBoolean(sosString.parseToString(arguments.get("jump_ignore_signal")))) {
ignoreSignal = true;
}
else {
ignoreSignal = false;
}
getLogger().debug1(".. parameter [jump_ignore_signal]: " + ignoreSignal);
}
else {
ignoreSignal = false;
}
// TODO
if (sosString.parseToString(arguments.get("jump_ignore_stderr")).length() > 0) {
if (sosString.parseToBoolean(sosString.parseToString(arguments.get("jump_ignore_stderr")))) {
ignoreStderr = true;
}
else {
ignoreStderr = false;
}
getLogger().debug1(".. parameter [jump_ignore_stderr]: " + ignoreStderr);
}
else {
ignoreStderr = false;
}
}
catch (Exception e) {
throw new Exception("error occurred processing parameters: " + e.getMessage());
}
RemoteConsumer stdoutConsumer = null;
RemoteConsumer stderrConsumer = null;
try { // to connect, authenticate and execute commands
this.getBaseAuthentication();
boolean windows = remoteIsWindowsShell();
String remoteCommandScriptFileName = "";
if (commandScript.length() > 0 || commandScriptFileName.length() > 0) {
File commandScriptFile = null;
if (commandScript.length() > 0) {
commandScriptFile = createCommandScript(windows);
}
else {
commandScriptFile = createCommandScript(new File(commandScriptFileName), windows);
}
transferCommandScript(commandScriptFile, windows);
remoteCommandScriptFileName = commandScriptFile.getName();
// change commands to execute transferred file
commands = new String[1];
if (windows) {
commands[0] = commandScriptFile.getName();
}
else {
commands[0] = "./" + commandScriptFile.getName();
}
// delete local file
if (commandScript.length() > 0) {
commandScriptFile.delete();
}
}
Class cl_ = null;
// execute commands
for (int i = 0; i < this.getCommands().length; i++) {
try {
exitStatus = null;
String exitSignal = null;
if (sosString.parseToString(getCommands()[i]).trim().length() == 0)
continue;
getLogger().debug1("executing remote command: " + normalizedPassword(this.getCommands()[i]));
this.setSshSession(this.getSshConnection().openSession());
String currentCommand = this.getCommands()[i];
if (!windows && schedulerJob != null && Class.forName(SSHJOBNAME) != null) {
currentCommand = "echo $$ && " + currentCommand;
cl_ = Class.forName(SSHJOBNAME);
if (schedulerJob.getClass().getName().equals(cl_.getName())) {
Method method = cl_.getMethod("initKillJob", new Class[] {});
method.invoke(schedulerJob, new Class[] {});
}
}
this.getSshSession().execCommand(currentCommand);
getLogger().debug("output to stdout for remote command: " + normalizedPassword(this.getCommands()[i]));
stdout = new StreamGobbler(this.getSshSession().getStdout());
stderr = new StreamGobbler(this.getSshSession().getStderr());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
int pid = 0;
while (true) {
String line = stdoutReader.readLine();
if (line == null)
break;
if (!windows && pid == 0 && schedulerJob != null && Class.forName(SSHJOBNAME) != null) {
if (schedulerJob.getClass().getName().equals(cl_.getName())) {
pid = Integer.parseInt(line);
if (cl_ != null) {
Method method = cl_.getMethod("setSchedulerSSHKillPid", new Class[] { int.class });
method.invoke(schedulerJob, new Object[] { new Integer(pid) });
}
getLogger().debug5("Parent pid: " + pid);
continue;
}
}
if (sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("execute") && banner)
getLogger().info(line);
else
if (sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("receive")
&& sosString.parseToString(line).indexOf("files found.") > -1
&& sosString.parseToBoolean(sosString.parseToString(arguments.get("skip_transfer"))))
getLogger().info(line.substring(line.indexOf("[info]") + "[info]".length()));
else
if (sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("receive")
&& sosString.parseToString(line).indexOf("Processing file") > -1
&& sosString.parseToBoolean(sosString.parseToString(arguments.get("skip_transfer")))) {
String s = line.substring(line.indexOf("Processing file") + "Processing file".length() + 1);
if (filelisttmp == null)
filelisttmp = new Vector<String>();
filelisttmp.add(s);
}
else
if (line.indexOf("[warn]") > -1 || line.indexOf("[error]") > -1) {
getLogger().warn("remote execution reports error : " + line);
}
else {
getLogger().debug1(line);
}
// Die Schreibweise bitte nicht ver�ndern, da hier String vergleiche gemacht werden
if (line.indexOf("*******ftp transfer directory is:") > -1) {
int pos1 = line.indexOf("*******ftp transfer directory is:") + "*******ftp transfer directory is:".length();
int pos2 = line.indexOf("******************");
tempJumpRemoteDir = line.substring(pos1, pos2);
}
if (line.indexOf("[info]") > -1 && line.indexOf("files found.") > -1 && sosString.parseToBoolean(arguments.get("testmode"))
&& sosString.parseToString(arguments.get("operation")).equals("receive")) {
getLogger().info(line.substring(line.indexOf("[info]") + "[info]".length()));
}
if (line.indexOf("[info]") > -1
&& (line.indexOf("removing remote file:") > -1 || line.indexOf("files remove.") > -1)
&& (sosString.parseToString(arguments.get("operation")).equals("remove") || sosString.parseToString(
arguments.get("operation")).equals("receive"))) {
getLogger().info(line.substring(line.indexOf("[info]") + "[info]".length()));
}
}
if (!windows && schedulerJob != null) {
if (cl_ != null && Class.forName(SSHJOBNAME) != null) {
if (schedulerJob.getClass().getName().equals(cl_.getName())) {
Method method = cl_.getMethod("setSchedulerSSHKillPid", new Class[] { int.class });
method.invoke(schedulerJob, new Object[] { new Integer(0) });
}
}
}
getLogger().debug1("output to stderr for remote command: " + normalizedPassword(this.getCommands()[i]));
// Beide StreamGobbler m�ssen hintereinander instanziiert werden
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
stderrOutput = new StringBuffer();
while (true) {
String line = stderrReader.readLine();
if (line == null)
break;
getLogger().error(line);
stderrOutput.append(line + conNewLine);
}
if (stderrOutput != null && stderrOutput.length() > 0) {
if (ignoreStderr) {
if (jump) {
// testen
getLogger().error("output to stderr is ignored: " + stderrOutput);
return false;
}
else {
getLogger().info("output to stderr is ignored: " + stderrOutput);
}
}
else {
throw new Exception("remote execution reports error: " + stderrOutput);
}
}
try {
exitStatus = this.getSshSession().getExitStatus();
}
catch (Exception e) {
getLogger().debug1("could not retrieve exit status, possibly not supported by remote ssh server");
}
if (exitStatus != null) {
if (!exitStatus.equals(new Integer(0))) {
if (ignoreError) {
getLogger().debug1("exit status is ignored: " + exitStatus);
}
else {
throw new Exception("remote command terminated with exit status: " + exitStatus
+ (logger.hasWarnings() ? " error: " + logger.getWarning() : ""));
}
}
}
try {
exitSignal = this.getSshSession().getExitSignal();
}
catch (Exception e) {
getLogger().debug1("could not retrieve exit signal, possibly not supported by remote ssh server");
}
if (exitSignal != null) {
if (exitSignal.length() > 0) {
if (ignoreSignal) {
getLogger().debug1("exit signal is ignored: " + exitSignal);
}
else {
throw new Exception("remote command terminated with exit signal: " + exitSignal);
}
}
}
}
catch (Exception e) {
throw e;
}
finally {
if (remoteCommandScriptFileName != null && remoteCommandScriptFileName.length() > 0) {
deleteCommandScript(remoteCommandScriptFileName);
}
if (this.getSshSession() != null)
try {
this.getSshSession().close();
this.setSshSession(null);
}
catch (Exception ex) {
} // gracefully ignore this error
}
}
}
catch (Exception e) {
throw new Exception("error occurred processing ssh command: " + e.getMessage());
}
finally {
if (stderrConsumer != null)
stderrConsumer.end();
if (stdoutConsumer != null)
stdoutConsumer.end();
if (this.getSshConnection() != null)
try {
this.getSshConnection().close();
this.setSshConnection(null);
}
catch (Exception ex) {
} // gracefully ignore this error
}
return true;
}
catch (Exception e) {
try {
getLogger().warn(e.getMessage());
}
catch (Exception ex) {
}
return false;
}
}
public File transferCommandScript(File commandFile, boolean isWindows) throws Exception {
try {
SFTPv3Client sftpClient = new SFTPv3Client(this.getSshConnection());
SFTPv3FileAttributes attr = new SFTPv3FileAttributes();
attr.permissions = new Integer(0700);
boolean exists = true;
// check if File already exists
while (exists) {
try {
SFTPv3FileAttributes attribs = sftpClient.stat(commandFile.getName());
}
catch (SFTPException e) {
getLogger().debug9("Error code when checking file existence: " + e.getServerErrorCode());
exists = false;
}
if (exists) {
getLogger().debug1("file with that name already exists, trying new name...");
String suffix = (isWindows ? ".cmd" : ".sh");
File resultFile = File.createTempFile("sos", suffix);
resultFile.delete();
commandFile.renameTo(resultFile);
commandFile = resultFile;
}
}
// set execute permissions for owner
SFTPv3FileHandle fileHandle = sftpClient.createFileTruncate(commandFile.getName(), attr);
FileInputStream fis = null;
long offset = 0;
try {
fis = new FileInputStream(commandFile);
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) {
throw new Exception("error occurred writing file [" + commandFile.getName() + "]: " + e.getMessage());
}
finally {
if (fis != null)
try {
fis.close();
fis = null;
}
catch (Exception ex) {
} // gracefully ignore this error
}
sftpClient.closeFile(fileHandle);
fileHandle = null;
sftpClient.close();
return commandFile;
}
catch (Exception e) {
throw new Exception("Error transferring command script: " + e, e);
}
}
public File createCommandScript(boolean isWindows) throws Exception {
try {
if (!isWindows)
commandScript = commandScript.replaceAll("(?m)\r", "");
String suffix = (isWindows ? ".cmd" : ".sh");
File resultFile = File.createTempFile("sos", suffix);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(resultFile)));
out.write(commandScript);
out.close();
return resultFile;
}
catch (Exception e) {
throw new Exception("Error creating command script: " + e, e);
}
}
public File createCommandScript(File scriptFile, boolean isWindows) throws Exception {
try {
commandScript = sos.util.SOSFile.readFileUnicode(scriptFile);
return createCommandScript(isWindows);
}
catch (Exception e) {
throw new Exception("Error creating command script: " + e, e);
}
}
private void deleteCommandScript(String commandFile) throws Exception {
try {
SFTPv3Client sftpClient = new SFTPv3Client(this.getSshConnection());
sftpClient.rm(commandFile);
sftpClient.close();
}
catch (Exception e) {
getLogger().warn("Failed to delete remote command script: " + e);
}
}
/**
* @return Returns the sshSession.
*/
private Session getSshSession() {
return sshSession;
}
/**
* @param sshSession The sshSession to set.
*/
private void setSshSession(Session sshSession) {
this.sshSession = sshSession;
}
/**
* Remove files by FTP/SFTP on a remote server.
*
* @return boolean
* @throws Exception
*/
public boolean remove() throws Exception {
getLogger().debug1("calling " + sos.util.SOSClassUtil.getMethodName());
// Das L�schen der Dateien per ftp ist identisch wie die Methode receive mit den Parameter
// skip_trasfer=yes (-> unterdr�cken der transferieren der Dateien) und remove_files=yes
arguments.put("skip_transfer", "yes");
arguments.put("remove_files", "yes");
return receive();
}
/**
* send mail
*
* @param recipient
* @param recipientCC carbon copy recipient
* @param recipientBCC blind carbon copy recipient
* @param subject
* @param body
* @throws Exception
*/
protected void sendMail(String recipient, String recipientCC, String recipientBCC, String subject, String body) throws Exception {
try {
SOSMail sosMail = new SOSMail(this.mailSMTP);
sosMail.setQueueDir(this.mailQueueDir);
sosMail.setFrom(this.mailFrom);
sosMail.setContentType("text/plain");
sosMail.setEncoding("Base64");
sosMail.setPort(mailPortNumber);
String recipients[] = recipient.split(",");
for (int i = 0; i < recipients.length; i++) {
sosMail.addRecipient(recipients[i].trim());
}
String recipientsCC[] = recipientCC.split(",");
for (int i = 0; i < recipientsCC.length; i++) {
sosMail.addCC(recipientsCC[i].trim());
}
String recipientsBCC[] = recipientBCC.split(",");
for (int i = 0; i < recipientsBCC.length; i++) {
sosMail.addBCC(recipientsBCC[i].trim());
}
sosMail.setSubject(subject);
sosMail.setBody(body);
sosMail.setSOSLogger(this.getLogger());
this.getLogger().debug1("sending mail: \n" + sosMail.dumpMessageAsString());
if (!sosMail.send()) {
this.getLogger().warn(
"mail server is unavailable, mail for recipient [" + recipient + "] is queued in local directory [" + sosMail.getQueueDir() + "]:"
+ sosMail.getLastError());
}
sosMail.clearRecipients();
}
catch (Exception e) {
throw new Exception("error occurred sending mai: " + e.getMessage());
}
}
protected String getAlternative(String param, String alternativeParam) throws Exception {
try {
if (sosString.parseToString(alternativeParam).length() > 0) {
return alternativeParam;
}
else {
return param;
}
}
catch (Exception e) {
this.getLogger().warn("error in getAlternative(): " + e.getMessage());
return param;
}
}
protected int getAlternative(int param, int alternativeParam) throws Exception {
try {
if (alternativeParam > 0) {
return alternativeParam;
}
else {
return param;
}
}
catch (Exception e) {
this.getLogger().warn("error in getAlternative(): " + e.getMessage());
return param;
}
}
/**
* @return Returns the logger.
*/
public SOSLogger getLogger() {
return logger;
}
/**
* @param logger The logger to set.
*/
public void setLogger(SOSLogger logger_) {
logger = logger_;
}
protected URI createURI(String fileName) throws Exception {
URI uri = null;
try {
uri = new URI(fileName);
}
catch (Exception e) {
try {
File f = new File(fileName);
String path = f.getCanonicalPath();
if (fileName.startsWith("/")) {
path = fileName;
}
String fs = System.getProperty("file.separator");
if (fs.length() == 1) {
char sep = fs.charAt(0);
if (sep != '/')
path = path.replace(sep, '/');
if (path.charAt(0) != '/')
path = '/' + path;
}
if (!path.startsWith("file://")) {
path = "file://" + path;
}
uri = new URI(path);
}
catch (Exception ex) {
throw (new Exception("error in createURI(): " + e.getMessage()));
}
}
return uri;
}
protected File createFile(String fileName) throws Exception {
try {
if (fileName == null || fileName.length() == 0) {
throw new Exception("empty file name provided");
}
if (fileName.startsWith("file://")) {
return new File(createURI(fileName));
}
else {
return new File(fileName);
}
}
catch (Exception e) {
throw new Exception("error in createFile() [" + fileName + "]: " + e.getMessage());
}
}
protected static String getErrorMessage(Exception ex) throws Exception {
String s = "";
try {
Throwable tr = ex.getCause();
if (ex.toString() != null)
s = ex.toString();
while (tr != null) {
if (s.indexOf(tr.toString()) == -1)
s = (s.length() > 0 ? s + ", " : "") + tr.toString();
tr = tr.getCause();
}
}
catch (Exception e) {
throw ex;
}
return s;
}
/**
* @return Returns the commands.
*/
protected String[] getCommands() {
return commands;
}
/**
* @param commands The commands to set.
*/
protected void setCommands(String[] commands) {
this.commands = commands;
}
/**
* Mergen von Programm Argumente und Settings Eistellungen.
*
* @throws Exception
*/
protected void mergeSettings() throws Exception {
Properties retVal = new Properties();
try {
// Umgebungsvariable, die alle mit SOSFTP anfangen
Properties arg = getEnvVars(logger);
retVal.putAll(arg);
// zus�tzliche Parametern generieren
retVal.put("date", sos.util.SOSDate.getCurrentDateAsString());
retVal.put("time", sos.util.SOSDate.getCurrentTimeAsString("hh:mm:ss"));
retVal.put("transfer_timestamp", sos.util.SOSDate.getCurrentTimeAsString());
retVal.put("local_user", sosString.parseToString(System.getProperty("user.name")));
// zuweisen von Defaults bei leeren Parametern
if (sosString.parseToString(arg, "current_pid").length() > 0)
retVal.put("current_pid", sosString.parseToString(arg, "current_pid"));
if (sosString.parseToString(arg, "ppid").length() > 0)
retVal.put("ppid", sosString.parseToString(arg, "ppid"));
try {
java.net.InetAddress localMachine = java.net.InetAddress.getLocalHost();
if (sosString.parseToString(localMachine.getHostName()).length() > 0)
retVal.put("localhost", localMachine.getHostName());
retVal.put("local_host_ip", localMachine.getHostAddress());
}
catch (java.net.UnknownHostException uhe) {
} // tu nichts
if (arguments != null)
retVal.putAll(arguments);
if (originalParam == null || originalParam.isEmpty())
originalParam = (Properties) retVal.clone();
arguments = retVal;
try {
String host = sosString.parseToString(arguments, "host");
if (host.length() > 0)
arguments.put("remote_host_ip", java.net.InetAddress.getByName(host).getHostAddress());
}
catch (java.net.UnknownHostException uhe) {
}
if (!writeBannerHeader && !sosString.parseToString(arguments, "operation").startsWith("install")) {
if (banner)
getLogger().info(getBanner(true));
else
getLogger().debug1(getBanner(true));
writeBannerHeader = true;// header nur einmal schreiben
}
int jumpParameterLength = sosString.parseToString(arguments.get("jump_host")).length()
+ sosString.parseToString(arguments.get("jump_port")).length() + sosString.parseToString(arguments.get("jump_user")).length();
if (jumpParameterLength > 0 && !sosString.parseToString(arguments.get("operation")).equals("execute"))
jump = true;
createHistoryFile();
checkSchedulerRequest();
}
catch (Exception e) {
throw new Exception("Failed to merge program arguments and settings: " + e);
}
}
/**
* Substitution von Environment-Variablen in Konfigurationsdateien
*
* F�r Unix und Windows soll bei allen Einstellungen in einer Konfigurationsdatei
* Substitution von Environment-Variablen unterst�tzt werden.
* Variablen m�ssen in der Form %VAR% bzw. ${VAR} geschrieben sein.
*
*/
private static Properties substituteEnvironment(Properties prop) throws Exception {
Properties newProp = new Properties();
try {
Iterator it = prop.keySet().iterator();
String key = "";
String value = "";
while (it.hasNext()) {
key = sosString.parseToString(it.next());
if (!key.startsWith(";")) {
value = sosString.parseToString(prop.get(key));
// if(key.indexOf("password") == -1 || !sosConfiguration.getPasswordnames().contains(key))
String msg = ".." + key + "=" + normalizedPassword(value) + " ";
// logger.debug9(".." + key + "=" + normalizedPassword(value) + " wird ersetz mit ");
value = normalizedFields(value, environment, "${", "}");
value = normalizedFields(value, environment, "%", "%");
// if(key.indexOf("password") == -1 || !sosConfiguration.getPasswordnames().contains(key))
// logger.debug9(msg + " is normalized in " + key + " --> " + normalizedPassword(value));
newProp.put(key, value);
}
}
}
catch (Exception e) {
logger.warn("Failed to substitute environment variables in configuration file, cause: " + e.toString());
return prop;
}
return newProp;
}
/**
* Create History File if not exist
* @throws Exception
*/
private void createHistoryFile() throws Exception {
boolean writeHeaderFields = false;
getLogger().debug1("calling " + sos.util.SOSClassUtil.getMethodName());
try {
if (sosString.parseToBoolean(arguments.get("testmode")))
return;
if (tempHistoryFile != null && tempHistoryFile.exists())
return;
if (sosString.parseToString(arguments, "history").length() > 0) {
if (sosString.parseToString(arguments, "operation").equals("send") || sosString.parseToString(arguments, "operation").equals("receive")) {
historyFile = new File(sosString.parseToString(arguments, "history"));
if (!historyFile.exists()) {
if (historyFile.createNewFile()) {
getLogger().info("creating global history file " + historyFile.getAbsolutePath());
}
else {
getLogger().warn("could not create history file : " + historyFile.getAbsolutePath());
}
}
if (historyFile.length() == 0)
writeHeaderFields = true;
if (!historyFile.canWrite()) {
getLogger().warn("history file is read only: " + historyFile.getAbsolutePath());
return;
}
tempHistoryFile = File.createTempFile("sosftp_history", ".csv", new File(System.getProperty("java.io.tmpdir")));
tempHistoryFile.deleteOnExit();
// �berpr�fen ob die Historien Felder Reihenfolge anders ist als in der Historiendatei.
checkHistoryField(historyFields);
history = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempHistoryFile)));
if (writeHeaderFields) {
historyFields = historyFields + ";" + newHistoryFields;
for (int i = 0; i < historyEntrys.size(); i++) {
String key = sosString.parseToString(historyEntrys.get(i));
historyFields = historyFields + ";" + sosString.parseToString(key).substring("history_entry_".length()); //
}
history.write(historyFields);
history.newLine();
}
}
}
else {
if (getHistory() != null) {
getHistory().close();
history = null;
}
}
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + " could not create history file, cause: " + e);
}
}
private boolean existHistoryLockFile() throws Exception {
BufferedReader bra = null;
BufferedReader procout = null;
int countOfDelay = 3;
String pid = "";
int delay = 5;
boolean existPID = false;
try {
if (sosString.parseToBoolean(arguments.get("testmode"))) {
return false;
}
// �berpr�fen, ob eine lock Datei existiert
lockHistoryFile = new File(System.getProperty("java.io.tmpdir"), historyFile.getName() + ".lock");
if (lockHistoryFile.exists()) {
getLogger().debug9("..history lock File exists.");
getLogger().debug("timestamp of last modification of history file: " + lockHistoryFile.lastModified());
// delay einbauen
for (int i = 0; i < countOfDelay; i++) {
getLogger().debug5("..history lock file exist. wait 5 Seconds.");
Thread.sleep(delay + 1000);
if (!lockHistoryFile.exists()) {
break;
}
}
// gucken ob die lockdatei weiterhin existiert
if (lockHistoryFile.exists()) {
getLogger().debug5("..history lock file exist.");
// wenn ja, pid ermitteln
bra = new BufferedReader(new FileReader(lockHistoryFile));
// �berpr�fen, ob dieser pid existiert
if ((pid = bra.readLine()) != null) {
getLogger().debug("reading from history lock file: pid = " + pid);
// F�r Window
Process proc = null;
if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1)
proc = Runtime.getRuntime().exec("tasklist /FI \"PID eq " + pid + "\"");
else
proc = Runtime.getRuntime().exec("ps -p " + pid);
procout = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String s;
while ((s = procout.readLine()) != null) {
getLogger().debug5("command output =\t" + s);
if (s.indexOf(pid) > -1) {// process ist aktuell
existPID = true;
break;
}
}
if (bra != null)
bra.close();
if (procout != null)
procout.close();
}
}
}
if (!existPID && sosString.parseToString(pid).trim().length() > 0) {
getLogger().debug("History lock File is deleting cause Process ID not exist.");
// Es existiert eine History Lock datei aber keine PID. Die Lock Datei kann gel�scht werden
if (lockHistoryFile.delete()) {
getLogger().info("History lock File successfully deleted, cause Process ID not exist.");
}
else {
throw new Exception("History lock File " + lockHistoryFile.getCanonicalPath() + " could not delete. There is no Process Id exist[pid="
+ pid + "]");
}
existPID = false;
}
if (existPID)// History Datei existiert und der entsprechende pid ist aktuell. Andere Instanzen d�rfen nicht schreiben.
throw new Exception("Could not write in History File, cause there is existing History Lock File.");
return existPID;
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + " while looking-up existing history lock file, cause: " + e);
}
finally {
if (bra != null)
bra.close();
if (procout != null)
procout.close();
}
}
/**
* �berpr�ft, ob die Historienfelder in der Historien datei identisch sind.
*/
private void checkHistoryField(String historyFields_) throws Exception {
BufferedReader br = null;
BufferedWriter bw = null;
String thisLine = "";
boolean historyFilesChanged = false;
try {
getLogger().debug1("calling " + sos.util.SOSClassUtil.getMethodName());
br = new BufferedReader(new FileReader(historyFile));
int line = 0;
while ((thisLine = br.readLine()) != null) { // while loop begins here
if (line > 0 && !historyFilesChanged) {
return;// es hat sich nichts ge�ndert, abbruchbedingung
}
if (line == 0) {// erste zeile, Historienfelder aus der Datei lesen und vergleichen, ob alle Felder vorhanden sind
for (int i = 0; i < historyEntrys.size(); i++) {
newHistoryFields = newHistoryFields + ";" + historyEntrys.get(i).toString().substring("history_entry_".length());
}
String[] splitnewHistoryFields = newHistoryFields.split(";");
for (int i = 0; i < splitnewHistoryFields.length; i++) {
// �berpr�fe, ob die neuen Felder bereits in der HistorienDatei vorhanden sind
if (thisLine.indexOf(";" + splitnewHistoryFields[i] + ";") == -1 && !thisLine.startsWith(splitnewHistoryFields[i] + ";")
&& !thisLine.endsWith(splitnewHistoryFields[i])) {
// neue Felder sind hinzugekommen
thisLine = thisLine + ";" + splitnewHistoryFields[i];
historyFilesChanged = true;
}
}
this.historyFields = thisLine;
if (historyFilesChanged) {
if (!existHistoryLockFile()) {
// lock Datei erzeugen, der verhindert, historien Eintr�ge zu schreiben
createHistoryLockFile();
bw = new BufferedWriter(new FileWriter(historyFile));
bw.write(thisLine);
bw.newLine();
}
}
}
else {
bw.write(thisLine);
bw.newLine();
}
line++;
}
}
catch (Exception e) {
throw new Exception("\n -> ..error in " + SOSClassUtil.getMethodName() + " " + e);
}
finally {
if (bw != null)
bw.close();
if (br != null)
br.close();
if (historyFilesChanged) {
removeHistoryLockFile();
}
}
}
/**
* Beim Schreiben in die Historien Datei wird vorher eine lock Datei generiert. Das soll parallele
* SOSFTP Instanzen verhindert gleichzeitig in die Historie Datei zu schreiben.
* @throws Exception
*/
private void createHistoryLockFile() throws Exception {
BufferedWriter lockBW = null;
try {
lockBW = new BufferedWriter(new FileWriter(lockHistoryFile));
lockBW.write(sosString.parseToString(arguments, "current_pid"));
}
catch (Exception e) {
throw new Exception("could not create a history lock file, cause: " + e.toString());
}
finally {
if (lockBW != null)
lockBW.close();
}
}
/**
* Beim Schreiben in die Historien Datei wird vorher eine lock Datei generiert. Das soll parallele
* SOSFTP Instanzen verhindert gleichzeitig in die Historie Datei zu schreiben.
* Hier soll die Lock Datei gel�scht werden, damit parallele SOSFTP Instanzen in die Historie schreiben k�nnen.
* @throws Exception
*/
private void removeHistoryLockFile() throws Exception {
try {
getLogger().debug1("calling " + sos.util.SOSClassUtil.getMethodName());
getLogger().debug9("lockHistoryFile=" + lockHistoryFile.getCanonicalPath());
if (lockHistoryFile != null && lockHistoryFile.exists()) {
if (!lockHistoryFile.delete()) {
getLogger().debug3("history lock file could not be deleted: " + lockHistoryFile.getCanonicalPath());
Thread.sleep(1000);
if (!lockHistoryFile.delete()) {
throw new Exception("history lock file could not be deleted: " + lockHistoryFile.getCanonicalPath());
}
}
}
}
catch (Exception e) {
throw new Exception("could not delete a history lock file, cause: " + e.toString());
}
}
/**
* �berpr�ft ob ein Jump Host angegeben wurde.
* Hier wird auf der jump host ein tempor�res Verzeichnis erzeugt,
* indem die Verzeichnisse tempor�r transferiet werden. Dieses verzecinis wird anschliessend
* gel�scht.
*
* Hier werden neue Kommandos generiert.
*/
protected void hasJumpArguments() throws Exception {
String curCommands = "";
try {
if (!jump)
return;
// Parameter die nicht an die SSH Commands �bergeben werden sollen
noJumpParameter.add("transfer_timestamp");
noJumpParameter.add("date");
noJumpParameter.add("time");
noJumpParameter.add("current_pid");
noJumpParameter.add("ppid");
noJumpParameter.add("pid");
noJumpParameter.add("local_user");
noJumpParameter.add("status");
noJumpParameter.add("successful_transfers");
noJumpParameter.add("failed_transfers");
noJumpParameter.add("last_error");
noJumpParameter.add("history");
noJumpParameter.add("history");
noJumpParameter.add("history_repeat");
noJumpParameter.add("history_interval");
noJumpParameter.add("localhost");
noJumpParameter.add("include");
noJumpParameter.add("remote_host_ip");
noJumpParameter.add("local_host_ip");
noJumpParameter.add("mandator");
noJumpParameter.add("scheduler_host");
noJumpParameter.add("scheduler_port");
noJumpParameter.add("scheduler_message");
noJumpParameter.add("scheduler_job_chain");
noJumpParameter.add("file_size");
noJumpParameter.add("log_filename");
noJumpParameter.add("command");
noJumpParameter.add("remove_after_jump_transfer");
noJumpParameter.add("root");
noJumpParameter.add("version");
noJumpParameter.add("replacing");
noJumpParameter.add("replacement");
noJumpParameter.add("getpidsexe");
noJumpParameter.add("verbose");
if (sosString.parseToString(arguments.get("ssh_auth_file")).startsWith("local:")) {
String filename = sosString.parseToString(arguments.get("ssh_auth_file")).substring("local:".length());
String text = sos.util.SOSFile.readFile(new File(filename));
arguments.put("ssh_auth_file", "filecontent:" + text);
}
if (sosString.parseToString(arguments.get("operation")).startsWith("install"))
noJumpParameter.add("operation");
if (!sosString.parseToString(arguments.get("operation")).equals("remove") && !sosString.parseToString(arguments.get("operation")).equals("receive"))
noJumpParameter.add("file_spec");
arguments.put("xx_make_temp_directory_xx", "ok");// hilfsvariable, wenn dieses key existiert, dann gilt im execute diese
// jump_command Parameter
// jump_command nicht ausgelesen
curCommands = sosString.parseToString(arguments.get("jump_command")) + " -operation=make_temp_directory -root="
+ sosString.parseToString(arguments, "root");
this.setCommands(curCommands.split(getCommandDelimiter()));
if (!execute()) {
throw new Exception("error occurred processing command: " + normalizedPassword(curCommands));
}
arguments.remove("xx_make_temp_directory_xx");
curCommands = sosString.parseToString(arguments.get("jump_command"));
String arg = "";
String arg4postCommands = "";
java.util.Iterator keys = arguments.keySet().iterator();
while (keys.hasNext()) {
String key = sosString.parseToString(keys.next());
// System.out.println("test: " + key);
if (!key.startsWith("jump") && !key.startsWith(";") && !key.startsWith("history_entry_") && !key.equals("profile") && !key.equals("settings")
&& !key.equals("local_dir") && !key.equals("file_path") && !key.equals("remove_files") && !noJumpParameter.contains(key))
{
String val = sosString.parseToString(arguments, key);
if (val.length() == 0)
continue;
if (key.equals("password")) {
val = SOSCommandline.getExternalPassword(val, logger);
}
/*if(!(key.equals("atomic_suffix") &&
sosString.parseToBoolean(sosString.parseToString(arguments.get("transactional"))) &&
sosString.parseToString(arguments.get("operation")).equals("send")))
*/
arg = arg + " -" + key + "=" + "\"" + val + "\"";
if (!key.equals("operation") && !key.equals("make_dirs") && !key.equals("root")
&& !((key.equals("transactional") && sosString.parseToString(arguments.get("operation")).equals("receive")))) {
// System.out.println(key);
arg4postCommands = arg4postCommands + " -" + key + "=" + "\"" + val + "\"";
}
}
}
if (sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("receive")
&& sosString.parseToBoolean(sosString.parseToString(arguments.get("skip_transfer")))
&& sosString.parseToBoolean(sosString.parseToString(arguments.get("remove_files")))) {
arg = arg + " -remove_files=\"yes\"";
}
if (sosString.parseToString(arguments.get("operation")).startsWith("receive")
&& sosString.parseToBoolean(sosString.parseToString(arguments.get("skip_transfer")))) {
// wenn jump host �berpr�fen soll, welche Dateien es im target host liegen, dann wird dieser in execute
// mit Hilfe String operationen ausgelesen. Damit sparen wird das �bertragen der Dateien auf jump Host um von Lokal Host
// die Dateien zu �berpr�fen. Diese �nderung ist notwendig, wenn SOSFTP vom JobSchedulerReceive.java mit der Parameter
// parallel = yes aufgerufen wird.
arg = arg + " -verbose=\"9\"";
}
else {
arg = arg + " -verbose=\"" + getLogger().getLogLevel() + "\"";
}
if (sosString.parseToString(arguments.get("operation")).startsWith("install"))
arg = arg + " -operation=\"send\"";
arg = arg + " -local_dir=\"" + tempJumpRemoteDir + "\"";
if ((sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("remove") || (sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("receive")))
&& sosString.parseToString(arguments, "file_path").length() > 0) {
arg = arg + " -file_path=\"" + sosString.parseToString(arguments, "file_path") + "\"";
}
if (sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("send")
|| sosString.parseToString(arguments.get("operation")).startsWith("install")
|| sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("remove")) {
arg = arg + " -remove_files=yes";
// - niemals bei 1. Transfer-Operation zum jump_host lokal l�schen
// - erst nach 2. Transfer-Operation l�schen, wenn erfolgreich
curCommands = curCommands + " " + arg;
if (!sosString.parseToString(arguments.get("operation")).equalsIgnoreCase("remove"))
postCommands = curCommands;
}
else {
curCommands = curCommands + " " + arg;
if (sosString.parseToBoolean(arguments.get("remove_files")))
postCommands = sosString.parseToString(arguments.get("jump_command")) + " -operation=\"remove\" " + arg4postCommands + " -file_path=\""
+ sosString.parseToString(arguments, "file_path") + "\"";
}
if (sosString.parseToString(postCommands).length() > 0) {
if (sosString.parseToString(arguments.get("replacement")).length() > 0 || sosString.parseToString(arguments.get("replacing")).length() > 0) {
postCommands = postCommands + " -replacement=\"" + sosString.parseToString(arguments, "replacement") + "\"" + " -replacing=\""
+ sosString.parseToString(arguments, "replacing") + "\"";
}
postCommands = postCommands + commandDelimiter;
}
curCommands = curCommands + commandDelimiter;
this.setCommands(curCommands.split(this.getCommandDelimiter()));
getLogger().debug1("new Commands: " + normalizedPassword(curCommands));
// Anpassen der Parameter f�r einen jump transfer per ftp
// L�schen der Dateien erst nach erfolgreichen �bertragen
arguments.put("remove_after_jump_transfer", sosString.parseToString(arguments.get("remove_files")));
arguments.put("remove_files", "no");
arguments.put("make_dirs", "yes");// erlaubt das Generierne einer Tempor�ren verzeichnis auf den lokalen Rechner
arguments.put("jump_remote_dir", tempJumpRemoteDir);// Name des tempor�ren Verezcinis als remote_dir angeben
if (!arguments.containsKey("jump_protocol"))
arguments.put("jump_protocol", "sftp");
// jump Parameter jetzt in ftp Parameter umbennen um die Dateien tempor�r zu �bertragen
Properties prop = new Properties();
java.util.Iterator keys2 = arguments.keySet().iterator();
while (keys2.hasNext()) {
String key = sosString.parseToString(keys2.next());
if (key.startsWith("jump_")) {
prop.put(key.substring(5), sosString.parseToString(arguments, key));
}
}
arguments.putAll(prop);
}
catch (Exception e) {
throw new Exception("Failed to jump to: " + e);
}
}
/**
* Alle Umgebungsvariable die mit sosftp_ anfangen werden ausgelesen.
*
* Umgebungsvaribalen werden in einem globalen Parametern gemerkt, um
* Substitution von Environment-Variablen in Konfigurationsdateien vorzunehmen.
*
* @param logger
* @return sos.util.Properties
* @throws Exception
*/
private static Properties getEnvVars(SOSLogger logger_) throws Exception {
try {
if (logger != null)
logger.debug5("reading environment");
Process p = null;
Properties envVars = new Properties();
Runtime r = Runtime.getRuntime();
String OS = System.getProperty("os.name").toLowerCase();
environment = new Properties();
if (OS.indexOf("windows 9") > -1) {
p = r.exec("command.com /c set");
}
else
if ((OS.indexOf("nt") > -1) || (OS.indexOf("windows") > -1)) {
p = r.exec("cmd.exe /c set");
}
else {
p = r.exec("env");
}
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
int idx = line.indexOf('=');
if (idx > -1) {
String key = line.substring(0, idx);
String value = "";
if (key.toLowerCase().startsWith("sosftp_")) {
value = line.substring(idx + 1);
envVars.setProperty(key.substring(7).toLowerCase(), value);
}
else
if (key.toLowerCase().startsWith("current_pid") || key.toLowerCase().startsWith("ppid")) {
value = line.substring(idx + 1);
envVars.setProperty(key.toLowerCase(), value);
}
else
if (key.toLowerCase().indexOf("scheduler_param_") > -1) {
value = line.substring(idx + 1);
// envVars.setProperty( key.toLowerCase(), value );
schedulerParams.setProperty(key.toLowerCase().substring("scheduler_param_".length()), value);
if (logger != null)
logger.debug5(".. environment [" + key + "]: " + value);
}
environment.put(key, line.substring(idx + 1));
}
}
return envVars;
}
catch (Exception e) {
if (logger != null)
logger.warn("[ERROR] could not read environment, cause: " + e.getMessage());
throw new Exception("error occurred reading environment: " + e.toString());
}
}
/**
* L�scht das Tempor�res Verzeichnis
* @return boolean
*/
private boolean removeTempDirectory() {
try {
getLogger().debug1("***********remove Temporary Directory*************");
String inputFile = "";
String[] split = sosString.parseToString(arguments, "input").split(";");
for (int i = 0; i < split.length; i++) {
inputFile = sosString.parseToString(split[i]);
getLogger().debug5("remove: " + inputFile);
if (inputFile.length() == 0) {
getLogger().debug1("no directory/file has been specified for removal: " + inputFile);
return false;
}
getLogger().debug1("..parameter [input=" + inputFile + "]");
File tmpDir = new File(inputFile);
if (!tmpDir.exists()) {
getLogger().debug1("directory/file to be removed does not exist: " + tmpDir.getCanonicalPath());
return false;
}
// Verzeichnis kann nicht gel�scht werden, wenn eine Datei unterhalb dieses Verzeichnis besteht
File[] listOfFiles = tmpDir.listFiles();
for (int j = 0; j < listOfFiles.length; j++) {
if (listOfFiles.length > 0) {
if (!listOfFiles[j].delete())
getLogger().warn(listOfFiles[j].getCanonicalPath() + " could not be deleted");
else
getLogger().debug1(listOfFiles[j].getCanonicalPath() + " was successfully deleted");
}
}
if (tmpDir.delete())
getLogger().debug1(tmpDir.getCanonicalPath() + " was successfully deleted");
else {
getLogger().warn(tmpDir.getCanonicalPath() + " could not be deleted");
}
}
}
catch (Exception e) {
try {
getLogger().warn("error deleting temporary directory, cause: " + e.toString());
}
catch (Exception ex) {
}
}
return true;
}
/**
* Generiert ein Tempor�res Verzeichnis f�r ftp transfer auf der Jump Host
* @return
*/
private boolean makeTempDirectory() throws Exception {
String output = "";
try {
getLogger().debug1("***********make Temporary Directory*************");
if (sosString.parseToString(arguments, "root").length() > 0) {
output = File.createTempFile("sos_ftp", null, new File(normalized(sosString.parseToString(arguments, "root")))).getCanonicalPath();
}
else {
output = File.createTempFile("sos_ftp", null, new File(System.getProperty("java.io.tmpdir"))).getCanonicalPath();
}
tempJumpRemoteDir = output;
// diese Logausgabe darf nicht ver�ndert werden. Wenn doch dann auch in execute-Methode anpassen. Der Log Level muss INFO sein
getLogger().info("*******ftp transfer directory is:" + output + "******************");
if (new File(output).getCanonicalFile().exists()) {
// nur ein tempname wird gebraucht File.createTempFile erzeugt automatisch eine Datei, wir brauchen nur einen
// eindeutigen Namen f�r einen Verzeichnis
new File(output).getCanonicalFile().delete();
}
if (!new File(output).getCanonicalFile().mkdirs())
throw new Exception("could not create temporary directory");
}
catch (Exception e) {
getLogger().warn("error creating temporary directory, cause: " + e.toString());
throw new Exception("error creating temporary directory, cause: " + e.toString());
}
return true;
}
protected String normalized(String str) {
str = str.replaceAll(conRegExpBackslash, "/");
return (str.endsWith("/") || str.endsWith("\\") ? str : str + "/");
}
/**
* This program logs output to stdout or to a file that has been specified by the parameter log_filename.
* A template can be used in order to organize the output that is created. The output is grouped into header, file list and footer.
* This specifies a template file for header and footer output.
* Templates can use internal variables and parameters as placeholders in the form %{placeholder}.
*
* @param header
* @return String
* @throws Exception
*/
public String getBanner(boolean header) throws Exception {
String curBannerHeader = "";
String curBannerFooter = "";
String banner = "";
try {
if (header) {
curBannerHeader = bannerHeader;
if (sosString.parseToString(arguments, "banner_header").length() > 0) {
String b = sosString.parseToString(arguments, "banner_header");
File fBanner = new File(b);
if (!fBanner.exists()) {
getLogger().warn("[banner_header=" + b + "] does not exist. Using default banner");
}
else {
curBannerHeader = sos.util.SOSFile.readFile(fBanner);
}
}
Iterator it = arguments.keySet().iterator();
while (it.hasNext()) {
String key = sosString.parseToString(it.next());
if (key.length() > 0) {
if (key.equals("file_spec") && sosString.parseToString(arguments, "file_path").length() > 0)
continue;
int pos1 = -1;
int pos2 = -1;
boolean loop = true;
while (loop) {
pos1 = curBannerHeader.indexOf("%{" + key + "}");
pos2 = pos1 + ("%{" + key + "}").length();
if (pos1 > -1 && pos2 > pos1) {
curBannerHeader = curBannerHeader.substring(0, pos1) + sosString.parseToString(arguments, key)
+ curBannerHeader.substring(pos2);
}
pos1 = curBannerHeader.indexOf("%{" + key + "}", pos2);
if (pos1 == -1)
loop = false;
}
}
}
// alle Platzhalter, die keinen Wert haben l�schen
curBannerHeader = clearBanner(curBannerHeader);
banner = curBannerHeader;
}
else {
curBannerFooter = bannerFooter;
if (sosString.parseToString(arguments, "banner_footer").length() > 0) {
String b = sosString.parseToString(arguments, "banner_footer");
File fBanner = new File(b);
if (!fBanner.exists()) {
getLogger().warn("[banner_footer=" + b + "] does not exist. Using default banner");
}
else {
curBannerFooter = sos.util.SOSFile.readFile(fBanner);
}
}
@SuppressWarnings("rawtypes")
Iterator it = arguments.keySet().iterator();
while (it.hasNext()) {
String key = sosString.parseToString(it.next());
if (key.length() > 0) {
if (key.equals("file_spec") && sosString.parseToString(arguments, "file_path").length() > 0)
continue;
boolean loop = true;
loop = true;
int pos3 = -1;
int pos4 = -1;
while (loop) {
pos3 = curBannerFooter.indexOf("%{" + key + "}");
pos4 = pos3 + ("%{" + key + "}").length();
if (pos3 > -1 && pos4 > pos3)
curBannerFooter = curBannerFooter.substring(0, pos3) + sosString.parseToString(arguments, key)
+ curBannerFooter.substring(pos4);
pos3 = curBannerFooter.indexOf("%{" + key + "}", pos4);
if (pos3 == -1)
loop = false;
}
}
}
// alle Platzhalter, die keinen Wert haben l�schen
curBannerFooter = clearBanner(curBannerFooter);
banner = curBannerFooter;
// arguments.remove("for_banner");
}
}
catch (Exception e) {
throw new Exception("error occurred getting banner: " + e.getMessage());
}
return banner;
}
/**
* L�schen von leeren Platzhalter
* @param str
* @return
*/
private String clearBanner(String str) {
boolean loop = true;
while (loop) {
int pos1 = str.indexOf("%{");
int pos2 = str.indexOf("}", pos1) + "}".length();
if (pos1 > -1 && pos2 > pos1) {
int iSpace = pos2 - pos1;
String space = " ";
while (iSpace != 0) {
space = space + " ";
iSpace--;
}
str = str.substring(0, pos1) + space + str.substring(pos2);
}
pos1 = str.indexOf("%{", pos2);
if (pos1 == -1)
loop = false;
}
return str;
}
/**
* @return Returns the sshConnection.
*/
protected Connection getSshConnection() {
return sshConnection;
}
/**
* @param sshConnection The sshConnection to set.
*/
protected void setSshConnection(Connection sshConnection) {
this.sshConnection = sshConnection;
}
/**
* Install SOSFTP on a remote server
*
* @return boolean
* @throws Exception
*/
protected boolean install() throws Exception {
return false;
}
/**
* Initialisieren der sos.net.SOSFTP
* @throws Exception
*/
protected void initSOSFTP() throws Exception {
try {
try {
sosftp = new SOSFTP(host, port);
}
catch (Exception e) {
this.getLogger().debug("SOSFtp exception raised");
// e.printStackTrace();
throw e; // kb 2011-04-27 grrrrr
}
// sos.net.SOSFTP sosftp = new sos.net.SOSFTP(host, port);
// sosftp.connect(host, port);
ftpClient = sosftp;
this.getLogger().debug("..ftp server reply [init] [host=" + host + "], [port=" + port + "]: " + ftpClient.getReplyString());
if (account != null && account.length() > 0) {
isLoggedIn = sosftp.login(user, SOSCommandline.getExternalPassword(password, logger), account);
this.getLogger().debug("..ftp server reply [login] [user=" + user + "], [account=" + account + "]: " + ftpClient.getReplyString());
}
else {
isLoggedIn = sosftp.login(user, SOSCommandline.getExternalPassword(password, logger));
this.getLogger().debug("..ftp server reply [login] [user=" + user + "]: " + ftpClient.getReplyString());
}
if (!isLoggedIn || sosftp.getReplyCode() > ERROR_CODE) {
throw new Exception("..ftp server reply [login failed] [user=" + user + "], [account=" + account + "]: " + ftpClient.getReplyString());
}
postLoginOperations();
}
catch (Exception e) {
e.printStackTrace();
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + ", cause: " + e);
}
}
/**
* Performs some post-login operations, such trying to detect server support
* for utf8.
*
*/
private void postLoginOperations() throws Exception {
// synchronized (lock) {
utf8Supported = false;
restSupported = false;
mlsdSupported = false;
modezSupported = false;
dataChannelEncrypted = false;
if (flgCheckServerFeatures == true) { // JIRA SOSFTP-92
String strCmd = "FEAT";
sosftp.sendCommand(strCmd);
this.getLogger().info("..ftp server reply [" + strCmd + "]: " + ftpClient.getReplyString());
}
// FTPReply r = sosftp.readFTPReply();
// if (r.getCode() == 211) {
// String[] lines = r.getMessages();
// for (int i = 1; i < lines.length - 1; i++) {
// String feat = lines[i].trim().toUpperCase();
// // REST STREAM supported?
// if ("REST STREAM".equalsIgnoreCase(feat)) {
// restSupported = true;
// continue;
// }
// // UTF8 supported?
// if ("UTF8".equalsIgnoreCase(feat)) {
// utf8Supported = true;
// sosftp.changeCharset("UTF-8");
// continue;
// }
// // MLSD supported?
// if ("MLSD".equalsIgnoreCase(feat)) {
// mlsdSupported = true;
// continue;
// }
// // MODE Z supported?
// if ("MODE Z".equalsIgnoreCase(feat) || feat.startsWith("MODE Z ")) {
// modezSupported = true;
// continue;
// }
// }
// }
// // Turn UTF 8 on (if supported).
// if (utf8Supported) {
// sosftp.sendFTPCommand("OPTS UTF8 ON");
// sosftp.readFTPReply();
// }
// // Data channel security.
// if (security == SECURITY_FTPS || security == SECURITY_FTPES) {
// sosftp.sendFTPCommand("PBSZ 0");
// sosftp.readFTPReply();
// sosftp.sendFTPCommand("PROT P");
// FTPReply reply = sosftp.readFTPReply();
// if (reply.isSuccessCode()) {
// dataChannelEncrypted = true;
// }
// }
// }
}
/**
* Initialisieren der sos.net.SOSSFTP
* @throws Exception
*/
protected void initSOSSFTP() throws Exception {
try {
SOSSFTP sftpClient = new SOSSFTP(host, port);
ftpClient = sftpClient;
sftpClient.setAuthenticationFilename(authenticationFilename);
sftpClient.setAuthenticationMethod(authenticationMethod);
sftpClient.setPassword(SOSCommandline.getExternalPassword(password, logger));
sftpClient.setProxyHost(proxyHost);
sftpClient.setProxyPort(proxyPort);
sftpClient.setProxyPassword(SOSCommandline.getExternalPassword(proxyPassword, logger));
sftpClient.setProxyUser(proxyUser);
sftpClient.setUser(user);
sftpClient.connect();
this.getLogger().debug("..sftp server logged in [user=" + user + "], [host=" + host + "]");
}
catch (Exception e) {
throw new Exception("..sftp server login failed [user=" + user + "], [host=" + host + "]: " + e);
}
}
protected void initSOSFTPS() throws Exception {
try {
if (proxyHost != null && proxyPort != 0) {
System.getProperties().setProperty("proxyHost", proxyHost);
System.getProperties().setProperty("proxyPort", String.valueOf(proxyPort));
System.getProperties().setProperty("proxySet", "true");
}
SOSFTPS sosftp = new SOSFTPS(host, port);
ftpClient = sosftp;
this.getLogger().debug("..ftps server reply [init] [host=" + host + "], [port=" + port + "]: " + ftpClient.getReplyString());
isLoggedIn = sosftp.login(user, SOSCommandline.getExternalPassword(password, logger));
this.getLogger().debug("..ftps server reply [login] [user=" + user + "]: " + ftpClient.getReplyString());
if (!isLoggedIn || sosftp.getReplyCode() > ERROR_CODE) {
throw new Exception("..ftps server reply [login failed] [user=" + user + "], [account=" + account + "]: " + ftpClient.getReplyString());
}
}
catch (Exception e) {
throw new Exception("..ftps server login failed [user=" + user + "], [host=" + host + "]: " + e);
}
}
public Properties getArguments() {
return arguments;
}
private BufferedWriter getHistory() {
return history;
}
/**
* History Eintrag schreiben
* @param localFilename
* @param remoteFilename
* @throws Exception
*/
@SuppressWarnings("unchecked")
protected void writeHistory(String localFilename, String remoteFilename) throws Exception {
String hist = "";
String EMPTY = "";
long guid = 0;
String mandator = "";
String transfer_timestamp = "";
String pid = "";
String ppid = "";
String operation = "";
String localhost = "";
String localhost_ip = "";
String local_user = "";
String remote_host = "";
String remote_host_ip = "";
String remote_user = "";
String protocol = "";
String port = "";
String local_dir = "";
String remote_dir = "";
String local_filename = "";
String remote_filename = "";
String fileSize = "";
String md5 = "";
String status = "";
String last_error_message = "";
String log_filename = "";
// new HistoryFields 04.09.2009
String jump_host = "";
String jump_host_ip = "";
String jump_port = "";
String jump_protocol = "";
String jump_user = "";
try {
if (!sosString.parseToString(arguments, "operation").equalsIgnoreCase("send")
&& !sosString.parseToString(arguments, "operation").equalsIgnoreCase("receive"))
return;
getLogger().debug9("local filename=" + localFilename + ", remote filename=" + remoteFilename);
if (sosString.parseToBoolean(sosString.parseToString(arguments, "skip_transfer")))
return;
if (history == null && !sendSchedulerSignale)
return;
File localFile = null;
if (sosString.parseToString(localFilename).length() > 0)
localFile = new File(localFilename);
guid = sos.util.SOSUniqueID.get(); // 4- GUID
mandator = (sosString.parseToString(arguments, "mandator").length() > 0 ? sosString.parseToString(arguments, "mandator") : defaultMandator); // 0-
// mandator:
// default
// SOS
transfer_timestamp = sos.util.SOSDate.getCurrentTimeAsString(); // 1- timestamp: Zeitstempel im ISO-Format
pid = (sosString.parseToString(arguments, "current_pid").length() > 0 ? sosString.parseToString(arguments, "current_pid") : "0"); // 2-
// pid=
// Environment
// PID
// |
// 0
// f�r
// Windows
ppid = (sosString.parseToString(arguments, "ppid").length() > 0 ? sosString.parseToString(arguments, "ppid") : "0"); // 3- ppid=
// Environment
// PPID
// | 0
// f�r
// Windows
operation = sosString.parseToString(arguments, "operation"); // 4- operation: send|receive
localhost = sosString.parseToString(arguments, "localhost"); // 5- local host
localhost_ip = sosString.parseToString(arguments, "local_host_ip"); // 5-1- local host IP adresse
local_user = sosString.parseToString(System.getProperty("user.name")); // 6- local user
if (jump) {
remote_host = sosString.parseToString(originalParam, "host"); // 7- remote host
if (remote_host.length() > 0)
remote_host_ip = java.net.InetAddress.getByName(remote_host).getHostAddress();
remote_user = sosString.parseToString(originalParam, "user"); // 8- remote host user
protocol = sosString.parseToString(originalParam, "protocol"); // 9- protocol
}
else {
remote_host = sosString.parseToString(arguments, "host"); // 7- remote host
remote_host_ip = sosString.parseToString(arguments, "remote_host_ip"); // 7- remote host IP
remote_user = sosString.parseToString(arguments, "user"); // 8- remote host user
protocol = sosString.parseToString(arguments, "protocol"); // 9- protocol
}
port = sosString.parseToString(arguments, "port"); // 10- port
// ab hier unterscheiden on der Fehler w�hrend dem Datei transfer oder vor dem datei transfer entstanden ist
if (sosString.parseToString(arguments, "operation").equals("send")) {
local_dir = (localFile != null && localFile.getParent() != null ? clearCRLF(localFile.getParent()) : clearCRLF(sosString.parseToString(
arguments, "local_dir"))); // 11- local dir
}
else {
local_dir = clearCRLF(sosString.parseToString(arguments, "local_dir")); // 11- local dir
}
if (sosString.parseToString(local_dir).length() == 0)
local_dir = ".";
if (jump) {
remote_dir = clearCRLF(sosString.parseToString(originalParam, "remote_dir")); // 12- remote dir
}
else {
remote_dir = clearCRLF(sosString.parseToString(arguments, "remote_dir")); // 12- remote dir
}
local_filename = localFile != null ? clearCRLF(localFile.getName()) : EMPTY; // 13- file name
remote_filename = sosString.parseToString(remoteFilename).length() > 0 ? clearCRLF(new File(remoteFilename).getName()) : EMPTY; // 14-
// file
// name
fileSize = sosString.parseToString(arguments, "file_size").length() > 0 ? sosString.parseToString(arguments, "file_size") : EMPTY;
if (sosString.parseToString(localFilename).length() == 0 || sosString.parseToString(remoteFilename).length() == 0) {
md5 = EMPTY; // MD5
}
else {
File f4md5 = localFile.getName().equals(new File(remoteFilename).getName()) ? new File(remoteFilename) : (sosString.parseToString(arguments,
"operation").equals("receive") ? new File(normalized(local_dir) + new File(remoteFilename).getName()) : new File(normalized(local_dir)
+ localFile.getName())); // falls ein replacing verwendet wurde
if (f4md5.exists()) {
getLogger().debug9("md5 for " + f4md5.getAbsolutePath());
md5 = sos.util.SOSCrypt.MD5encrypt(f4md5); // MD5
}
else {
md5 = EMPTY; // eventuell existiert die Datei nicht
}
}
status = (sosString.parseToString(arguments, "status").length() == 0 ? "success" : sosString.parseToString(arguments, "status"));// -
// status=success|error
last_error_message = clearCRLF(((getLogger().getError() != null && getLogger().getError().length() > 0) ? getLogger().getError()
: getLogger().getWarning())); // 15- last_error=|warn message
last_error_message = normalizedPassword(sosString.parseToString(last_error_message));
log_filename = sosString.parseToString(arguments, "log_filename");
jump_host = sosString.parseToString(arguments, "jump_host");
if (jump_host.length() > 0)
jump_host_ip = java.net.InetAddress.getByName(host).getHostAddress();
jump_port = sosString.parseToString(arguments, "jump_port");
jump_protocol = sosString.parseToString(arguments, "jump_protocol");
jump_user = sosString.parseToString(arguments, "jump_user");
// TODO mit den Mappings im SOSFTPHistoryJob synchronisieren. Hier muss eine *gemeinsame* Klasse verwendet werden
// am besten mit der OptionKlasse koppeln, da gleiche datentypen etc.
Properties objSchedulerOrderParameterSet = new Properties();
objSchedulerOrderParameterSet.put("guid", String.valueOf(guid)); // 1- GUID
objSchedulerOrderParameterSet.put("mandator", mandator); // 2- mandator: default SOS
objSchedulerOrderParameterSet.put("transfer_timestamp", transfer_timestamp); // 3- timestamp: Zeitstempel im ISO-Format
objSchedulerOrderParameterSet.put("pid", pid); // 4- pid= Environment PID | 0 f�r Windows
objSchedulerOrderParameterSet.put("ppid", ppid); // 5- ppid= Environment PPID | 0 f�r Windows
objSchedulerOrderParameterSet.put("operation", operation); // 6- operation: send|receive
objSchedulerOrderParameterSet.put("localhost", localhost); // 7- local host
objSchedulerOrderParameterSet.put("localhost_ip", localhost_ip); // 8- local host IP adresse
objSchedulerOrderParameterSet.put("local_user", local_user); // 9- local user
objSchedulerOrderParameterSet.put("remote_host", remote_host); // 10- remote host
objSchedulerOrderParameterSet.put("remote_host_ip", remote_host_ip); // 11- remote host IP
objSchedulerOrderParameterSet.put("remote_user", remote_user); // 12- remote host user
objSchedulerOrderParameterSet.put("protocol", protocol); // 13- protocol
objSchedulerOrderParameterSet.put("port", port); // 14- port
objSchedulerOrderParameterSet.put("local_dir", local_dir); // 15- local dir
objSchedulerOrderParameterSet.put("remote_dir", remote_dir); // 16- remote dir
objSchedulerOrderParameterSet.put("local_filename", local_filename); // 17- file name
objSchedulerOrderParameterSet.put("remote_filename", remote_filename); // 18- file name
objSchedulerOrderParameterSet.put("file_size", fileSize); // 19 - file name
objSchedulerOrderParameterSet.put("md5", md5); // 20
objSchedulerOrderParameterSet.put("status", status); // 21- status=success|error
objSchedulerOrderParameterSet.put("last_error_message", last_error_message); // 22
objSchedulerOrderParameterSet.put("log_filename", log_filename); // 23
objSchedulerOrderParameterSet.put("jump_host", jump_host); // 24
objSchedulerOrderParameterSet.put("jump_host_ip", jump_host_ip); // 25
objSchedulerOrderParameterSet.put("jump_port", jump_port); // 26
objSchedulerOrderParameterSet.put("jump_protocol", jump_protocol); // 27
objSchedulerOrderParameterSet.put("jump_user", jump_user); // 28
if (history != null) {
String[] splitHistFields = historyFields.split(";");
for (int i = 0; i < splitHistFields.length; i++) {
String key = sosString.parseToString(splitHistFields[i]);
String value = sosString.parseToString(objSchedulerOrderParameterSet, key).length() == 0 ? sosString.parseToString(arguments,
"history_entry_".concat(key)) : sosString.parseToString(objSchedulerOrderParameterSet, key);
hist = hist + (i == 0 ? "" : ";") + value; //
}
getLogger().debug9("history entry: " + hist);
if (transActional) {
if (transactionalHistoryFile == null)
transactionalHistoryFile = new ArrayList();
transactionalHistoryFile.add(hist);
}
else {
history.write(hist);
history.newLine();
}
}
if (sendSchedulerSignale) {
String schedulerMessages = "";
if (sosString.parseToString(arguments, "scheduler_message").length() > 0) {
schedulerMessages = sosString.parseToString(arguments, "scheduler_message");
schedulerMessages = normalizedFields(schedulerMessages, objSchedulerOrderParameterSet, "%{", "}");
schedulerMessages = normalizedFields(schedulerMessages, arguments, "%{", "}");
}
else {
String strJobChainName = sosString.parseToString(arguments, "scheduler_job_chain");
schedulerMessages = String.format("<add_order job_chain='%1$s'><params>", strJobChainName);
for (final Entry element : objSchedulerOrderParameterSet.entrySet()) {
final Map.Entry<String, String> mapItem = (Map.Entry<String, String>) element;
String key = mapItem.getKey().toString();
schedulerMessages += String.format("<param name='%1$s' value='%2$s'/>", key, mapItem.getValue());
}
schedulerMessages = schedulerMessages + "</params></add_order>";
}
if (transActional) {
if (transactionalSchedulerRequestFile == null)
transactionalSchedulerRequestFile = new ArrayList();
transactionalSchedulerRequestFile.add(schedulerMessages);
}
else {
sendSchedulerRequest(schedulerMessages);
getLogger().debug9("sending Job Scheduler message: " + schedulerMessages);
}
}
}
catch (Exception e) {
getLogger().warn("error occurred writing history entry, cause: " + e.getMessage());
}
}
private String clearCRLF(String txt) {
return txt.replaceAll("(\r\n|\r|\n|\n\r|;)", ",");
}
private void appendHistoryFile() throws Exception {
int repeat = 3;
int repeatIntervall = 1;
try {
if (sosString.parseToString(arguments, "history_repeat").length() > 0) {
try {
repeat = Integer.parseInt(sosString.parseToString(arguments, "history_repeat"));
}
catch (Exception e) {
repeat = 3;
}
}
if (sosString.parseToString(arguments, "history_repeat_interval").length() > 0) {
try {
repeatIntervall = Integer.parseInt(sosString.parseToString(arguments, "history_repeat_interval"));
}
catch (Exception e) {
repeatIntervall = 1;
}
}
boolean hasError = getLogger().hasErrors() || getLogger().hasWarnings();
if (getHistory() != null) {
for (int j = 0; transactionalHistoryFile != null && j < transactionalHistoryFile.size(); j++) {
String hist = sosString.parseToString(transactionalHistoryFile.get(j));
if (hasError) {
hist = hist.replaceAll(";success;;", ";error;"
+ clearCRLF(((getLogger().getError() != null && getLogger().getError().length() > 0) ? getLogger().getError()
: getLogger().getWarning())) + ";");
}
history.write(hist);
history.newLine();
getLogger().debug9("history entry: " + hist);
}
}
}
catch (Exception e) {
getLogger().warn("error occurred writing history, cause: " + e.getMessage());
}
finally {
for (int i = repeat; i > 0; i--) {
try {
if (getHistory() != null) {
getHistory().close();
// schreibe diese in die globalen history Datei
if (!existHistoryLockFile()) {
createHistoryLockFile();
sos.util.SOSFile.copyFile(getTempHistoryFile(), historyFile, true);
removeHistoryLockFile();
}
if (!tempHistoryFile.delete())
getLogger().info(tempHistoryFile.getAbsolutePath() + " could not delete");
}
break;
}
catch (Exception e) {
if (i == 1)
getLogger().warn("could not write in History File, cause: " + e.toString());
Thread.sleep(repeatIntervall * 1000);
}
}
if (tempHistoryFile != null && tempHistoryFile.exists())
if (!tempHistoryFile.delete())
getLogger().info(tempHistoryFile.getAbsolutePath() + " could not delete");
}
}
private void sendTransactionalSchedulerRequestFile() throws Exception {
if (transActional) {
if (transactionalSchedulerRequestFile != null) {
for (int i = 0; i < transactionalSchedulerRequestFile.size(); i++) {
String msg = sosString.parseToString(transactionalSchedulerRequestFile.get(i));
boolean hasError = getLogger().hasErrors() || getLogger().hasWarnings();
if (hasError) {
msg = msg.replaceAll("<param name='status' value='success'/>", "<param name='status' value='error'/>");
msg = msg.replaceAll("<param name='last_error_message' value=''/>", "<param name='last_error_message' value='"
+ clearCRLF(((getLogger().getError() != null && getLogger().getError().length() > 0) ? getLogger().getError()
: getLogger().getWarning())) + "'/>");
// sendSchedulerRequest(msg);
}
sendSchedulerRequest(msg);
}
}
}
}
/**
* sends a command to the scheduler
*
* @param command XML String containing the command
* @throws java.lang.Exception
*/
public void sendSchedulerRequest(String msg) throws Exception {
String _host = "";
int _port = 0;
DatagramSocket udpSocket = null;
try {
_host = sosString.parseToString(arguments, "scheduler_host");
if (sosString.parseToString(arguments, "scheduler_port").length() > 0)
_port = Integer.parseInt(sosString.parseToString(arguments, "scheduler_port"));
if (_host == null || _host.length() == 0)
throw (new Exception("Job Scheduler host name missing."));
if (_port == 0)
throw (new Exception("Job Scheduler port missing."));
udpSocket = new DatagramSocket();
udpSocket.connect(InetAddress.getByName(_host), _port);
// protocol=udp
if (msg.indexOf("<?xml") == -1) {
msg = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>" + msg + "\r\n";
}
getLogger().debug9("sending Job Scheduler message: " + msg);
byte[] commandBytes = msg.getBytes();
udpSocket.send(new DatagramPacket(commandBytes, commandBytes.length, InetAddress.getByName(_host), _port));
}
catch (Exception e) {
getLogger().warn("could not send message to the Job Scheduler, cause " + e.toString());
}
finally {
if (udpSocket != null)
udpSocket.disconnect();
}
}
/**
* sends a command to the scheduler
*
* �berpr�ft ob alle Parameter correkt angegeben sind
* @param command XML String containing the command
* @throws java.lang.Exception
*/
private void checkSchedulerRequest() throws Exception {
String _command = "";
String _host = "";
int _port = 0;
try {
_host = sosString.parseToString(arguments, "scheduler_host");
if (sosString.parseToString(arguments, "scheduler_port").length() > 0)
_port = Integer.parseInt(sosString.parseToString(arguments, "scheduler_port"));
_command = sosString.parseToString(arguments, "scheduler_message");
// abbruchbedingung
if (sosString.parseToString(_host).concat(sosString.parseToString(arguments, "scheduler_port")).concat(_command).length() == 0)
return;
if (_host == null || _host.length() == 0)
throw (new RuntimeException("Job Scheduler host name missing."));
if (_port == 0)
throw (new RuntimeException("Job Scheduler port missing."));
if (sosString.parseToString(arguments, "scheduler_job_chain").length() == 0)
arguments.put("scheduler_job_chain", "scheduler_sosftp_history");
sendSchedulerSignale = true;
}
catch (Exception e) {
throw new RuntimeException("error in checkSchedulerRequestParameter(): " + e.toString(), e);
}
}
/**
* Alle Platzhalter in der Form %{parametername} oder ${parametername} oder %parametername% werden ersetzt mir dem Wert des Parameters,
* falls dieser Parametername vorhanden sind.
*
*
*
* @param txt
* @param prop
* @return
* @throws Exception
*/
private static String normalizedFields(String txt, Properties prop, String startPrefix, String endPrefix) throws Exception {
try {
Iterator it = prop.keySet().iterator();
while (it.hasNext()) {
String key = sosString.parseToString(it.next());
if (key.length() > 0) {
int pos1 = -1;
int pos2 = -1;
boolean loop = true;
while (loop) {
pos1 = txt.indexOf(startPrefix + key + endPrefix);
if (pos1 > -1 && txt.indexOf("\\" + startPrefix + key + endPrefix) > -1
&& txt.indexOf("\\" + startPrefix + key + endPrefix) == pos1 - 1) // ist quottiert?
pos1 = -1;
pos2 = pos1 + (startPrefix + key + endPrefix).length();
if (pos1 > -1 && pos2 > pos1)
txt = txt.substring(0, pos1) + sosString.parseToString(prop, key) + txt.substring(pos2);
pos1 = txt.indexOf(startPrefix + key + endPrefix, pos2);
if (pos1 == -1)
loop = false;
}
}
}
return txt;
}
catch (Exception e) {
throw new Exception("could not substitute parameters in: " + txt + ", cause: " + e.toString());
}
}
private File getTempHistoryFile() {
return tempHistoryFile;
}
/**
* @return Returns the commandDelimiter.
*/
protected String getCommandDelimiter() {
return commandDelimiter;
}
private void readJumpSettings() throws Exception {
this.getBaseParameters();
String commandScript = "";
String commandScriptFileName = "";
try {
if (sosString.parseToString(arguments.get("jump_command_delimiter")).length() > 0) {
this.setCommandDelimiter(sosString.parseToString(arguments.get("jump_command_delimiter")));
getLogger().debug1(".. parameter [jump_command_delimiter]: " + this.getCommandDelimiter());
}
else {
this.setCommandDelimiter(DEFAULT_COMMAND_DELIMITER);
}
if (sosString.parseToString(arguments.get("jump_command_script")).length() > 0) {
commandScript = sosString.parseToString(arguments.get("jump_command_script"));
getLogger().debug1(".. parameter [jump_command_script]: " + commandScript);
}
if (sosString.parseToString(arguments.get("jump_command_script_file")).length() > 0) {
commandScriptFileName = sosString.parseToString(arguments.get("jump_command_script_file"));
getLogger().debug1(".. parameter [jump_command_script_file]: " + commandScriptFileName);
}
if (sosString.parseToString(arguments.get("jump_command")).length() > 0) {
this.setCommands(sosString.parseToString(arguments.get("jump_command")).split(this.getCommandDelimiter()));
getLogger().debug1(".. parameter [jump_command]: " + sosString.parseToString(arguments.get("jump_command")));
}
if (sosString.parseToString(arguments.get("jump_ignore_error")).length() > 0) {
if (sosString.parseToBoolean(arguments.get("jump_ignore_error"))) {
ignoreError = true;
}
else {
ignoreError = false;
}
getLogger().debug1(".. parameter [jump_ignore_error]: " + ignoreError);
}
else {
ignoreError = false;
}
if (sosString.parseToString(arguments.get("jump_ignore_signal")).length() > 0) {
if (sosString.parseToBoolean(sosString.parseToString(arguments.get("jump_ignore_signal")))) {
ignoreSignal = true;
}
else {
ignoreSignal = false;
}
getLogger().debug1(".. parameter [jump_ignore_signal]: " + ignoreSignal);
}
else {
ignoreSignal = false;
}
if (sosString.parseToString(arguments.get("jump_ignore_stderr")).length() > 0) {
if (sosString.parseToBoolean(sosString.parseToString(arguments.get("jump_ignore_stderr")))) {
ignoreStderr = true;
}
else {
ignoreStderr = false;
}
getLogger().debug1(".. parameter [jump_ignore_stderr]: " + ignoreStderr);
}
else {
ignoreStderr = false;
}
}
catch (Exception e) {
throw new Exception("error occurred processing parameters: " + e.getMessage());
}
}
protected boolean remoteIsWindowsShell(boolean withConn) throws Exception {
try {
if (withConn) {
if (getSshConnection() == null) {
readJumpSettings();
this.getBaseAuthentication();
}
}
return remoteIsWindowsShell();
}
catch (Exception e) {
throw new Exception("Failed to check if remote system has windows shell: " + e);
}
finally {
if (withConn) {
if (this.getSshConnection() != null)
try {
this.getSshConnection().close();
this.setSshConnection(null);
}
catch (Exception ex) {
} // gracefully ignore this error
}
}
}
/**
* Authentication-Processing
*
*/
protected Connection getBaseAuthentication() throws Exception {
try { // to connect and authenticate
boolean isAuthenticated = false;
this.setSshConnection(new Connection(this.host, this.port));
if (proxyHost != null && this.proxyHost.length() > 0) {
if (this.proxyUser != null && this.proxyUser.length() > 0) {
this.getSshConnection().setProxyData(new HTTPProxyData(this.proxyHost, this.proxyPort));
}
else {
this.getSshConnection().setProxyData(
new HTTPProxyData(this.proxyHost, this.proxyPort, this.proxyUser, SOSCommandline.getExternalPassword(this.proxyPassword, logger)));
}
}
this.getSshConnection().connect();
if (this.authenticationMethod.equalsIgnoreCase("publickey")) {
File authenticationFile = new File(authenticationFilename);
if (!authenticationFile.exists())
throw new Exception("authentication file does not exist: " + authenticationFile.getCanonicalPath());
if (!authenticationFile.canRead())
throw new Exception("authentication file not accessible: " + authenticationFile.getCanonicalPath());
isAuthenticated = this.getSshConnection().authenticateWithPublicKey(this.user, authenticationFile,
SOSCommandline.getExternalPassword(this.password, logger));
}
else
if (this.authenticationMethod.equalsIgnoreCase("password")) {
isAuthenticated = this.getSshConnection().authenticateWithPassword(this.user, SOSCommandline.getExternalPassword(this.password, logger));
}
if (!isAuthenticated)
throw new Exception("authentication failed [jump_host=" + this.host + ", jump_port=" + this.port + ", jump_user:" + this.user
+ ", jump_ssh_auth_method=" + this.authenticationMethod + ", jump_ssh_auth_file=" + authenticationFilename);
return this.getSshConnection();
}
catch (Exception e) {
if (this.getSshConnection() != null)
try {
this.getSshConnection().close();
this.setSshConnection(null);
}
catch (Exception ex) {
} // gracefully ignore this error
throw new Exception(e.getMessage());
}
}
/**
* Parameter-Processing
*
*/
protected void getBaseParameters() throws Exception {
try {
if (sosString.parseToString(arguments.get("jump_host")).length() > 0) {
this.host = sosString.parseToString(arguments.get("jump_host"));
getLogger().debug1(".. parameter [jump_host]: " + this.host);
}
else {
throw new Exception("no host name or ip address was specified as parameter [jump_host]");
}
if (sosString.parseToString(arguments.get("jump_port")).length() <= 0) {
arguments.put("jump_port", "22");
}
try {
this.port = Integer.parseInt(sosString.parseToString(arguments.get("jump_port")));
getLogger().debug1(".. parameter [jump_port]: " + this.port);
}
catch (Exception ex) {
throw new Exception("illegal non-numeric value for parameter [jump_port]: " + sosString.parseToString(arguments.get("jump_port")));
}
if (sosString.parseToString(arguments.get("jump_user")).length() > 0) {
this.user = (sosString.parseToString(arguments.get("jump_user")));
getLogger().debug1(".. parameter [jump_user]: " + this.user);
}
else {
throw new Exception("no user name was specified as parameter [jump_user]");
}
if (sosString.parseToString(arguments.get("jump_password")).length() > 0) {
this.password = sosString.parseToString(arguments.get("jump_password"));
getLogger().debug1(".. parameter [jump_password]: ********");
}
else {
this.password = "";
}
if (sosString.parseToString(arguments.get("jump_proxy_host")).length() > 0) {
proxyHost = sosString.parseToString(arguments.get("jump_proxy_host"));
getLogger().debug1(".. parameter [jump_proxy_host]: " + this.proxyHost);
}
else {
this.proxyHost = "";
}
if (sosString.parseToString(arguments.get("jump_proxy_port")).length() > 0) {
try {
this.proxyPort = (Integer.parseInt(sosString.parseToString(arguments.get("jump_proxy_port"))));
getLogger().debug1(".. parameter [jump_proxy_port]: " + this.proxyPort);
}
catch (Exception ex) {
throw new Exception("illegal non-numeric value for parameter [jump_proxy_port]: "
+ sosString.parseToString(arguments.get("jump_proxy_port")));
}
}
else {
this.proxyPort = 3128;
}
if (sosString.parseToString(arguments.get("jump_proxy_user")) != null && sosString.parseToString(arguments.get("jump_proxy_user")).length() > 0) {
this.proxyUser = (sosString.parseToString(arguments.get("jump_proxy_user")));
getLogger().debug1(".. parameter [jump_proxy_user]: " + this.proxyUser);
}
else {
this.proxyUser = "";
}
if (sosString.parseToString(arguments.get("jump_proxy_password")).length() > 0) {
this.proxyPassword = sosString.parseToString(arguments.get("jump_proxy_password"));
getLogger().debug1(".. parameter [jump_proxy_password]: ********");
}
else {
this.proxyPassword = "";
}
String authMeth = sosString.parseToString(arguments.get("jump_ssh_auth_method"));
if (sosString.parseToString(arguments.get("jump_auth_method")).length() > 0)
authMeth = sosString.parseToString(arguments.get("jump_auth_method"));
else
authMeth = sosString.parseToString(arguments.get("jump_ssh_auth_method"));
if (authMeth.length() > 0) {
if (authMeth.equalsIgnoreCase("publickey") || authMeth.equalsIgnoreCase("password")) {
this.authenticationMethod = authMeth;
getLogger().debug1(".. parameter [jump_ssh_auth_method]: " + this.authenticationMethod);
}
else {
throw new Exception("invalid authentication method [publickey, password] specified: " + authMeth);
}
}
else {
this.authenticationMethod = "publickey";
}
String authFile = sosString.parseToString(arguments.get("jump_ssh_auth_file"));
if (authFile.length() > 0) {
authenticationFilename = authFile;
getLogger().debug1(".. parameter [jump_ssh_auth_file]: " + authenticationFilename);
}
else {
if (this.authenticationMethod.equalsIgnoreCase("publickey"))
throw new Exception("no authentication filename was specified as parameter [jump_ssh_auth_file");
}
}
catch (Exception e) {
throw new Exception("error occurred processing parameters: " + e.getMessage());
}
}
protected boolean remoteIsWindowsShell() {
Session session = null;
try {
String checkShellCommand = "echo %ComSpec%";
getLogger().debug9("Opening ssh session...");
session = this.getSshConnection().openSession();
getLogger().debug9("Executing command " + checkShellCommand);
session.execCommand(checkShellCommand);
getLogger().debug9("output to stdout for remote command: " + checkShellCommand);
stdout = new StreamGobbler(session.getStdout());
stderr = new StreamGobbler(session.getStderr());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
String stdOut = "";
while (true) {
String line = stdoutReader.readLine();
if (line == null)
break;
getLogger().debug9(line);
stdOut += line;
}
getLogger().debug9("output to stderr for remote command: " + checkShellCommand);
// Beide StreamGobbler m�ssen hintereinander instanziiert werden
// InputStream stderr = new StreamGobbler(this.getSshSession().getStderr());
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
while (true) {
String line = stderrReader.readLine();
if (line == null)
break;
getLogger().debug1(line);
}
if (stdOut.indexOf("cmd.exe") > -1) {
getLogger().debug3("Remote shell is Windows shell.");
return true;
}
}
catch (Exception e) {
try {
getLogger().warn("Failed to check if remote system is windows shell: " + e);
}
catch (Exception es) {
System.out.println(" Failed to check if remote system is windows shell: " + e);
}
}
finally {
if (session != null)
try {
session.close();
}
catch (Exception e) {
try {
getLogger().warn("Failed to close session: " + e);
}
catch (Exception ea) {
System.out.println(" Failed to close session: " + e);
}
}
}
return false;
}
/**
* @param commandDelimiter The commandDelimiter to set.
*/
protected void setCommandDelimiter(String commandDelimiter) {
this.commandDelimiter = commandDelimiter;
}
/**
* 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;
private RemoteConsumer(StringBuffer buffer, boolean writeCurr, InputStream str) {
this.sbuf = buffer;
this.writeCurrentline = true;
this.stream = str;
}
private void addText(byte[] data, int len) {
lasttime = System.currentTimeMillis();
String outstring = new String(data).substring(0, len);
sbuf.append(outstring);
if (writeCurrentline) {
int newlineIndex = outstring.indexOf(conNewLine);
if (newlineIndex > -1) {
String stringAfterNewline = outstring.substring(newlineIndex);
currentLine = stringAfterNewline;
}
else
currentLine += outstring;
}
}
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) {
}
}
public synchronized void end() {
end = true;
}
}
protected void readSettings(boolean checkJumpArguments) throws Exception {
try {
// TODO wieso ist das auskommentiert ? kb 2010-05-18
/*try {
if(getSettingsFile() != null && getSettingsFile().length() > 0)
this.setSettings(new SOSProfileSettings( this.getSettingsFile(), this.getSettingsSection(), this.getLogger()));
} catch (Exception e) {
throw new Exception("error occurred retrieving settings: " + e.getMessage());
}*/
mergeSettings();
if (checkJumpArguments)
hasJumpArguments();
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + " , cause: " + e);
}
}
public static String getVersion() {
String version = JSVersionInfo.conVersionNumber;
// String version = major + "." + minor + "." + bugFix;
return version;
}
/**
* Different file operations within one session
* For different file sets multiple parameter sets should be used:
*
* a) Use case:
* - 3 files *.doc
* - 2 files *.csv
* - For each file set a different replacing/replacement scheme should be applied
*
* Approach:
*
* - different file_spec paramters should be used and each file set should be assigned a set of different parameters
* - changes to the initial parameters by a parameter set have local scope, i.e. a second parameter set makes use oft he initial parameters,
* and should not consider changes by a previous parameter set
*
* sosftp.sh �file_spec=[regex1]:[regex2] �transfer_mode=ascii:binary
* sosftp.sh �file_spec=[regex1] �file_spec2=[regex2]::[parameter_set2] �parameter_set2=�transfer_mode=ascii::remote_directory=/tmp�
*
*
* @param arg
* @return
* @throws Exception
*/
private static ArrayList getFileOperations(Properties arg) throws Exception {
ArrayList list = new ArrayList();
String key = "";
String value = "";
Iterator it = null;
listOfSuccessTransfer = new ArrayList();
listOfErrorTransfer = new ArrayList();
try {
arg.put("index", "0");
list.add(arg.clone());
arg.remove("index");
it = arg.keySet().iterator();
while (it.hasNext()) {
key = sosString.parseToString(it.next());
value = sosString.parseToString(arg, key);
// unterschiedlich Parametrisierung
if (key.startsWith("file_spec") && key.length() > "file_spec".length()) {// ein neues file_spec ist angegeben
String[] split = value.split("::");
Properties newArg = (Properties) arg.clone();
newArg.put("file_spec", split[0]);
noJumpParameter.add(key);// d�rfen dem jump host nicht �bergeben werden
if (split.length > 1) {
noJumpParameter.add(split[1]);// d�rfen dem jump host nicht �bergeben werden
String newParameterSet = sosString.parseToString(arg, split[1]);
String[] splitParams = newParameterSet.split("::");// Bsp.
// �parameter_set2=�transfer_mode=ascii:remote_directory=/tmp�
for (int i = 0; i < splitParams.length; i++) {
String s = sosString.parseToString(splitParams[i]);
if (s.length() > 0) {
String[] splitParam = s.split("=");
newArg.put(sosString.parseToString(splitParam[0]), splitParam.length == 1 ? "" : sosString.parseToString(splitParam[1]));
}
}
}
String index = key != null && key.length() > "file_spec".length() ? key.substring("file_spec".length()) : "";
newArg.put("index", index);// hilpsparameter, wird sp�ter wieder gel�scht
list.add(newArg);
}
else
if (key.equalsIgnoreCase("transfer_success")) {// ein neues file_spec ist angegeben
Properties newArg = (Properties) arg.clone();
String newParameterSet = sosString.parseToString(arg.get(value));
String[] splitParams = newParameterSet.split("::");// Bsp.
// �parameter_set2=�transfer_mode=ascii:remote_directory=/tmp�
for (int i = 0; i < splitParams.length; i++) {
String s = sosString.parseToString(splitParams[i]);
String[] splitParam = s.split("=");
newArg.put(sosString.parseToString(splitParam[0]), splitParam.length == 1 ? "" : sosString.parseToString(splitParam[1]));
}
listOfSuccessTransfer.add(newArg);
}
else
if (key.equalsIgnoreCase("transfer_error")) {// ein neues file_spec ist angegeben
Properties newArg = (Properties) arg.clone();
String newParameterSet = sosString.parseToString(arg.get(value));
String[] splitParams = newParameterSet.split("::");// Bsp.
// �parameter_set2=�transfer_mode=ascii:remote_directory=/tmp�
for (int i = 0; i < splitParams.length; i++) {
String s = sosString.parseToString(splitParams[i]);
String[] splitParam = s.split("=");
newArg.put(sosString.parseToString(splitParam[0]), splitParam.length == 1 ? "" : sosString.parseToString(splitParam[1]));
}
listOfErrorTransfer.add(newArg);
}
}
list = prepareInstall(list);
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + " , cause: " + e);
}
list = sortListAtFileSpecNum(list);
return list;
}
/**
* Parameter list wird sortiert nach file_spec_[num]
* @param list
* @return list
*/
private static ArrayList sortListAtFileSpecNum(ArrayList list) throws Exception {
ArrayList sort = new ArrayList();
try {
// sortiert die Arrayliste nach index
sort = sortArrayList(list, "index");
// hilfsvariable index l�schen
for (int i = 0; i < sort.size(); i++) {
Properties p = (Properties) list.get(i);
if (sosString.parseToString(p.get("index")).length() > 0) {
p.remove("index");
}
}
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + " , cause: " + e);
}
return sort;
}
public static ArrayList sortArrayList(ArrayList list, String key) throws Exception {
try {
Properties h = null;
Object[] o = null;
int pos = 0;
ArrayList newList = new ArrayList();
try {
o = new Object[list.size()];
for (int i = 0; i < list.size(); i++) {
h = (Properties) list.get(i);
o[i] = h.get(key) + "_@_" + String.valueOf(i);
}
Arrays.sort(o);
for (int i = 0; i < o.length; i++) {
pos = Integer.parseInt(o[i].toString().substring(o[i].toString().indexOf("_@_") + 3));
newList.add(list.get(pos));
}
list = newList;
}
catch (Exception e) {
throw (e);
}
return list;
}
catch (Exception e) {
throw new Exception("..error in " + SOSClassUtil.getMethodName() + " " + e);
}
}
/**
* Vorbereitung f�r operation=install. Es findet zwei installationen - entspricht zwei send Aufufe statt.
*
*
* @param list
* @return
* @throws Exception
*/
private static ArrayList prepareInstall(ArrayList list) throws Exception {
ArrayList newList = new ArrayList();
for (int i = 0; i < list.size(); i++) {
Properties p = (Properties) list.get(i);
newList.add(p);
if (p.containsKey("operation") && sosString.parseToString(p.get("operation")).equals("install")) {
Properties newp = (Properties) p.clone();
newp.put("operation", "install_doc");
newList.add(newp);
}
}
return newList;
}
/**
* @return the writeBannerHeader
*/
public boolean isWriteBannerHeader() {
return writeBannerHeader;
}
/**
* @param writeBannerHeader the writeBannerHeader to set
*/
public void setWriteBannerHeader(boolean writeBannerHeader) {
this.writeBannerHeader = writeBannerHeader;
}
private static String getUsage() {
String usage = "Usage: sos.net.SOSFTPCommand -operation= -settings= -profile= -verbose=" + conNewLine
+ " -operation =[send|receive|execute|remove|install] FTP operation" + conNewLine
+ " -settings =[file] Configuration file" + conNewLine
+ " -profile =[profile] Section/Profile for FTP settings" + conNewLine
+ " in configuration file" + conNewLine
+ " -verbose =[1..9] Verbosity level" + conNewLine
+ " -log_filename=[filename] log file name ";
return usage;
}
private static boolean transfer(ArrayList extractArguments, String operation, Properties arg, boolean rc, boolean continueOnError) throws Exception {
try {
for (int i = 0; i < extractArguments.size(); i++) {
arg = (Properties) extractArguments.get(i);
if (i > 0) {
operation = arg.getProperty("operation");
sosConfiguration.setArguments(arg);
sosConfiguration.checkConfigurationItems(REQUIRED_DEFAULT_PARAMETERS_FILENAME);
if (sosString.parseToString(arg.get("current_pid")).length() == 0 && sosString.parseToString(System.getProperty("pid")).length() > 0)
arg.put("pid", sosString.parseToString(System.getProperty("pid")));
if (banner)
logger.info("Transfer for file set no. " + i + " is being completed");
else
logger.debug1("All files have been transferred successfully. Transaction for file set no. " + i + " is being completed");
}
if (sosString.parseToBoolean(arg.get("testmode"))) {
logger.info("Test mode is active, no transfers are effected");
arg.put("skip_transfer", "yes");
arg.put("remove_files", "no");
}
if (operation.equalsIgnoreCase("send")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandSend(logger, arg);
rc = ftpCommand.send();
}
else
if (operation.equalsIgnoreCase("receive")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandReceive(logger, arg);
rc = ftpCommand.receive();
}
else
if (operation.equalsIgnoreCase("execute")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandSSH(logger, arg);
rc = ftpCommand.execute();
}
else
if (operation.equalsIgnoreCase("make_temp_directory")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandSend(logger, arg);
rc = ftpCommand.makeTempDirectory();
}
else
if (operation.equalsIgnoreCase("remove_temp_directory")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandSend(logger, arg);
rc = ftpCommand.removeTempDirectory();
}
else
if (operation.equalsIgnoreCase("delete") || operation.equalsIgnoreCase("remove")) {
if (operation.equalsIgnoreCase("delete"))
arg.put("operation", "remove");// demn�chst wird nur mit remove gearbeitet
ftpCommand = new sos.net.sosftp.SOSFTPCommandReceive(logger, arg);
rc = ftpCommand.remove();
}
else
if (operation.equalsIgnoreCase("install")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandSend(logger, arg);
rc = ftpCommand.install();
}
else
if (operation.equalsIgnoreCase("install_doc")) {
ftpCommand = new sos.net.sosftp.SOSFTPCommandSend(logger, arg);
rc = ftpCommand.install();
}
else
if (operation.equalsIgnoreCase("delete_local_files")) {
// wird intern verwendet
ftpCommand = new sos.net.sosftp.SOSFTPCommandSend(logger, arg);
rc = ftpCommand.deleteLocalFiles();
}
else
if (operation.equalsIgnoreCase("rename_local_files")) {
// wird intern verwendet
ftpCommand = new sos.net.sosftp.SOSFTPCommandReceive(logger, arg);
rc = ftpCommand.renameAtomicSuffixTransferFiles();
}
else {
System.out.println(getUsage());
throw new Exception(
"[ERROR] no valid operation was specified, use send|receive|remove|execute|install: "
+ operation);
}
if (logger.hasErrors() || logger.hasWarnings()) {
ftpCommand.getArguments().put("status", "error");
}
else {
ftpCommand.getArguments().put("status", "success");
}
if (sosString.parseToString(logger.getWarning()).length() > 0 || sosString.parseToString(logger.getError()).length() > 0) {
ftpCommand.getArguments().put("last_error", logger.getWarning() + " " + logger.getError());
}
if (ftpCommand != null) {
if (banner)
logger.info(normalizedPassword(ftpCommand.getBanner(false)));
else
logger.debug(normalizedPassword(ftpCommand.getBanner(false)));
}
if ((logger.hasErrors() || logger.hasWarnings()) && !continueOnError) {
// break;
// throw new Exception();
return false;
}
}
return rc;
}
catch (Exception e) {
e.printStackTrace();
logger.warn("error in " + SOSClassUtil.getMethodName() + " cause: " + e.toString());
return false;
}
}
private static Properties extractArguments(String[] args) throws Exception {
Properties arg = new Properties();
try {
String filename = "";
// Argumente
for (int i = 0; i < args.length; i++) {
String[] split = args[i].split("=");
String key = split[0].startsWith("-") ? split[0].substring(1) : split[0];
if (split.length == 1 && !split[0].startsWith("-")) {
if (key.trim().length() > 0)
logger.debug1("file name specified as argument: " + key);
filename = filename + key + ";";
}
else {
arg.put(key.toLowerCase(), args[i].substring(args[i].indexOf("=") + 1));
}
}
if (filename != null && filename.length() > 0) {
filename = filename.replaceAll(conRegExpBackslash, "/");
filename = filename.endsWith(";") ? filename.substring(0, filename.length() - 1) : filename;
arg.put("file_path", filename);
}
return arg;
}
catch (Exception e) {
logger.warn("[ERROR] could not process arguments, cause: " + e.getMessage());
throw e;
}
}
public static void createLoggerObject(String logFile, int logLevel) throws Exception {
if (sosString.parseToString(logFile).length() > 0)
logger = new SOSStandardLogger(logFile, logLevel);
else
logger = new SOSStandardLogger(logLevel);
}
private static boolean onlyVersion(Properties arg) throws Exception {
if (arg.containsKey("version")) {
if (!arg.containsKey("operation")) {
logger.info("sosftp version \"" + getVersion() + "\"");
return true;
}
}
return false;
}
protected boolean deleteLocalFiles() throws Exception {
ArrayList transActionalLocalFiles = new ArrayList();
String error = "";
if (arguments.containsKey("files"))
transActionalLocalFiles = (ArrayList) arguments.get("files");
for (int i = 0; i < transActionalLocalFiles.size(); i++) {
File localRemFile = null;
if (transActionalLocalFiles.get(i) instanceof File)
localRemFile = (File) transActionalLocalFiles.get(i);
else
localRemFile = new File(sosString.parseToString(transActionalLocalFiles.get(i)));
if (!localRemFile.delete()) {
error = error + localRemFile.getAbsolutePath() + ";";
}
else {
this.getLogger().debug1("removing file: " + localRemFile.getAbsolutePath());
}
if (error != null && error.length() > 0) {
getLogger().warn("..error occurred, could not remove local file: " + error);
return false;
}
}
return true;
}
public boolean renameAtomicSuffixTransferFiles() throws Exception {
try {
ArrayList transActionalLocalFiles = new ArrayList();
String atomicSuffix = sosString.parseToString(arguments.get("atomic_suffix"));
if (arguments.containsKey("files"))
transActionalLocalFiles = (ArrayList) arguments.get("files");
for (int i = 0; i < transActionalLocalFiles.size(); i++) {
String filename = sosString.parseToString(transActionalLocalFiles.get(i));
if (filename.trim().length() > 0) {
File f = new File(filename);
File nf = new File(filename.substring(0, filename.lastIndexOf(atomicSuffix)));
if (nf.exists()) {
getLogger().debug9(nf.getCanonicalPath() + " exists and will be replaced");
nf.delete();
}
getLogger().debug("..rename " + f.getCanonicalPath() + " to " + nf.getName());
if (!f.renameTo(nf))
throw new Exception("could not rename temporary file [" + f.getCanonicalPath() + "] to: " + nf.getAbsolutePath());
}
}
return true;
}
catch (Exception e) {
getLogger().warn("error in " + sos.util.SOSClassUtil.getMethodName() + " , cause: " + e);
return false;
}
}
private static boolean doPostTransactionalOnSuccess() {
try {
boolean rc = true;
banner = false;// es sollen keine banner mehr geschrieben werden
if (listOfSuccessTransfer.size() > 0) {
Properties p = (Properties) listOfSuccessTransfer.get(0);
String operation = sosString.parseToString(p.get("operation"));
rc = transfer(listOfSuccessTransfer, operation, p, true, false);
}
banner = true;
if (!rc) {
throw new Exception("All files have been transferred successfully, however, the transaction could not be completed");
}
return true;
}
catch (Exception e) {
try {
logger.warn("error in doPostTransactionalOnSuccess, cause: " + e.toString());
}
catch (Exception ex) {
}
doPostTransactionalOnError();
return false;
}
}
private static boolean doPostTransactionalOnError() {
try {
boolean rc = false;
banner = false;// es sollen keine banner mehr geschrieben werden
if (listOfErrorTransfer.size() > 0) {
Properties p = (Properties) listOfErrorTransfer.get(0);
String operation = sosString.parseToString(p.get("operation"));
transfer(listOfErrorTransfer, operation, p, rc, true);
}
}
catch (Exception e) {
try {
logger.warn("error in doPostTransactionalOnError, cause: " + e.toString());
}
catch (Exception ex) {
}
}
finally {
banner = true;
}
return false;
}
protected static String normalizedPassword(String str) {
try {
if (str == null || str.trim().length() == 0)
return "";
// alle m�glichen Passwortnamen, die gex't werden muss
ArrayList namesOfPassword = sosConfiguration.getPasswordnames();
if (!namesOfPassword.contains("password"))
namesOfPassword.add("password");
for (int i = 0; i < namesOfPassword.size(); i++) {
String pw = sosString.parseToString(namesOfPassword.get(i));
if (pw.trim().length() == 0)
continue;
int pos1 = str.indexOf(pw + "=");
if (pos1 > -1) {
int pos2 = str.indexOf(" ", pos1);
if (pos2 == -1 || pos1 > pos2)
pos2 = str.length();
str = str.substring(0, pos1) + pw + "=***** " + str.substring(pos2);
}
pos1 = str.indexOf("-ssh_auth_file=\"filecontent:");
;
if (pos1 > -1) {
int pos2 = -1;
if (pos1 == -1)
return str;
pos2 = str.indexOf("-----END DSA PRIVATE KEY-----", pos1) + "-----END DSA PRIVATE KEY-----".length() + 2;
if (pos2 == -1 || pos1 > pos2)
pos2 = str.length();
str = str.substring(0, pos1) + "-ssh_auth_file=\"filecontent:*****" + str.substring(pos2);
}
}
return str;
}
catch (Exception e) {
return "";
}
}
/**
* Ermittelt die PID.
* Der PID wird ermittelt, wenn historien Eintr�ge erw�nscht sind und
* nicht im Testmodus ist.
*
* @param GETPIDSEXE
* @param arg
* @return
* @throws Exception
*/
public String getPids() throws Exception {
String GETPIDSEXE = "";
if (sosString.parseToBoolean(sosString.parseToString(arguments.get("testmode"))))
return "";
if (System.getProperty("os.name").toLowerCase().indexOf("wind") > -1) {
if (GETPIDSEXE == null || GETPIDSEXE.length() == 0) {
if (new File("getParentId.exe").exists()) {
GETPIDSEXE = new File("getParentId.exe").getCanonicalPath();
}
else {
getLogger().debug5("creating getParentId.exe ");
// holt aus einer Bibliothek (jar File) die Datei und kopiert diese in das Verzeichnis
java.net.URL url = ClassLoader.getSystemResource("getParentId.exe");
getLogger().debug1("found url=" + url);
InputStream in = getClass().getClassLoader().getSystemResourceAsStream("getParentId.exe");// aus Klassenpfad holen
getLogger().debug9("get InputStream to create new getParentId.exe=" + in);
if (in == null) {
getLogger().debug9("try again to get InputStream to create new getParentId.exe=" + in);
in = getClass().getClassLoader().getResourceAsStream("getParentId.exe");// aus der Bibliothel holen
getLogger().debug9("InputStream is =" + in);
}
// /
if (in == null) {
// throw new Exception ("missing executable File getParentId.exe in Library sos.net.jar");
}
else {
OutputStream out = null;
byte[] buffer = new byte[1024];
try {
out = new FileOutputStream("getParentId.exe", false);
while (true) {
synchronized (buffer) {
int amountRead = in.read(buffer);
if (amountRead == -1) {
break;
}
out.write(buffer, 0, amountRead);
}
}
}
finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
return getPids();
}
}
}
}
String pid = getPID(GETPIDSEXE);
if (pid != null && pid.length() > 0) {
logger.debug1("current_pid is " + pid);
}
return pid;
}
/**
*
* Diese Methode liefert die aktuelle PID.
*
* Das Betriebssystem Windows brauch die Anwendung getpids.exe.
* getpids.exe liefert die aktuelle PID.
* Diese Anwendung kann von der Seite http://www.scheibli.com/projects/getpids/getpids-1.00.zip heruntergeladen werden.
*
* @param GETPIDEXE -> Anwendung
* @return String -> liefert die PID
* @throws IOException
* TODO: sp�ter vielleicht daraus einen statischen Method in SOS UTIL
*/
public String getPID(String GETPIDEXE) throws IOException {
String pid = "";
String cmd[];
if (System.getProperty("os.name").toLowerCase().indexOf("wind") == -1) {
cmd = new String[] { "/bin/sh", "-c", "echo $$ $PPID" };
}
else {
if (GETPIDEXE == null || GETPIDEXE.length() == 0)
throw new IOException("executables Files getpids.exe or getParentId.exe not found. Check Installation.");
cmd = new String[] { GETPIDEXE };
}
if (cmd != null) {
Process p = Runtime.getRuntime().exec(cmd);
InputStream inputstream = p.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String line;
if ((line = bufferedreader.readLine()) != null) {
StringTokenizer stok = new StringTokenizer(line);
if (System.getProperty("os.name").toLowerCase().indexOf("wind") == -1) {
stok.nextToken(); // this is pid of the process we spanned
}
pid = stok.nextToken();
}
if (pid != null)
System.setProperty("pid", pid); // NOI18N
}
return pid;
}
private static String[] mergeSchedulerParamsAndArgumenst(String[] args) throws Exception {
int index = -1;
String filename = "";
for (int i = 0; i < args.length; i++) {
String arg = args[i];
int pos0 = 1;
int pos1 = arg.indexOf("=");
if (pos1 == -1)
pos1 = arg.length();
if (!sosString.parseToString(arg).startsWith("-") && sosString.parseToString(arg).indexOf("=") == -1) {
filename = filename.length() > 0 ? filename + ";" + arg : arg;
}
else {
String key = arg.substring(pos0, pos1);
String value = arg.length() == pos1 ? "" : arg.substring(pos1 + 1);
schedulerParams.put(key, value);
}
}
if (sosString.parseToString(filename).trim().length() > 0)
schedulerParams.put("file_path", filename);
String[] retVal = new String[schedulerParams.size()];
Iterator it = schedulerParams.keySet().iterator();
while (it.hasNext()) {
Object key = it.next();
Object val = schedulerParams.get(key);
retVal[++index] = "-" + sosString.parseToString(key) + "=" + sosString.parseToString(val);
}
return retVal;
}
/**
* Konvertiert ConfigurationsItem[] zu Properties.
*
* Ber�cksichtigen der include Parametern
*
*
* @return
* @throws Exception
*/
private static Properties convertParameters() throws Exception {
try {
Properties arg_s = sosConfiguration.getParameterAsProperties();
if (sosString.parseToString(arg_s.get("settings")).length() > 0 && sosString.parseToString(arg_s.get("include")).length() > 0) {
sos.configuration.SOSConfiguration config_ = new sos.configuration.SOSConfiguration(sosString.parseToString(arg_s.get("settings")),
sosString.parseToString(arg_s.get("include")), logger);
sos.configuration.SOSConfigurationItem[] items = config_.checkConfigurationItems(REQUIRED_DEFAULT_PARAMETERS_FILENAME);
arg_s.putAll(config_.getParameterAsProperties());
}
// L�schen der Argumente, weil dieser in sos.util.configuration.Configuration ausgelesen wurden
arg_s.remove("settings");
arg_s.remove("profile");
arg_s.remove("include");
arg_s = substituteEnvironment(arg_s);
return arg_s;
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + ": cause: " + e.toString());
}
}
private static String checkOperation() throws Exception {
try {
String operation = sosConfiguration.getConfigurationItemByName("operation").getValue();
if (sosString.parseToString(operation).length() == 0) {
logger.warn(getUsage());
throw new Exception("missing command line parameter: operation");
}
return operation;
}
catch (Exception e) {
throw new Exception("error in " + sos.util.SOSClassUtil.getMethodName() + ": cause: " + e.toString());
}
}
/**
*
* @return boolean
*/
public boolean transfer() {
boolean rc = false;
String operation = "";
listOfSuccessTransfer = new ArrayList();
listOfErrorTransfer = new ArrayList();
try {
Properties env = getEnvVars(logger);// gleich am anfang, weil scheduler_params aus der Umgebungsvariable gelesen wird
env.putAll(schedulerParams);
operation = checkOperation();// operation value is given?
Properties arg_s = new Properties();
arg_s.putAll(env);
arg_s.putAll(convertParameters()); // convert ConfigurationItem[] to Properties
ArrayList extractArguments = getFileOperations(arg_s); // Different file operations within one session
try {
banner = true;
rc = transfer(extractArguments, operation, arg_s, rc, false);
if (rc) {
rc = doPostTransactionalOnSuccess();
}
else {
rc = doPostTransactionalOnError();
}
}
catch (Exception e) {
e.printStackTrace();
banner = true;
throw e;
}
}
catch (Exception e) {
try {
if (ftpCommand != null) {
if (banner)
logger.info(ftpCommand.getBanner(false));
else
logger.debug(ftpCommand.getBanner(false));
}
else {
System.out.println(e.toString());
}
}
catch (Exception x) {
System.out.println(e.toString());
}
System.exit(1);
}
finally {
try {
if (ftpCommand != null) {
ftpCommand.appendHistoryFile();
transactionalHistoryFile = null;
ftpCommand.sendTransactionalSchedulerRequestFile();
}
logger.close();
}
catch (Exception e) {
System.out.println(e.toString());
}
}
return rc;
}
/**
* Send/Receive files by FTP/SFTP and execute commands by SSH
* @see documentation sosftp.xml
*/
private static int getIntArg(Properties arg, String strKey, int pintDefault) {
int intI = pintDefault;
if (arg.containsKey(strKey)) {
String strT = arg.getProperty(strKey);
intI = Integer.valueOf(strT);
}
return intI;
}
private static String getStringArg(Properties arg, String strKey, String pstrDefault) {
String strT = pstrDefault;
if (arg.containsKey(strKey)) {
strT = arg.getProperty(strKey);
}
return strT;
}
public static void main(String[] args) {
boolean rc = false;
int logLevel = 0;
String logFile = "";
String settingsFile = "";
String settingsSection = "";
String operation = "";
listOfSuccessTransfer = new ArrayList();
listOfErrorTransfer = new ArrayList();
try {
Properties env = getEnvVars(logger); // gleich am anfang, weil scheduler_params aus der Umgebungsvariable gelesen wird
args = mergeSchedulerParamsAndArgumenst(args);
Properties arg = extractArguments(args);
arg.putAll(schedulerParams);
SOSArguments arguments = null;
try {
arguments = new SOSArguments(args, true);
operation = arguments.as_string("-operation=", "");
settingsFile = arguments.as_string("-settings=", "");
settingsSection = arguments.as_string("-profile=", "");
logLevel = arguments.as_int("-verbose=", SOSLogger.INFO);
logFile = arguments.as_string("-log_filename=", "");
}
catch (Exception e) {
e.printStackTrace(System.err);
System.err.println("[ERROR] could not init SOSArguments, cause: " + e.getMessage());
throw e;
}
createLoggerObject(logFile, logLevel);
if (onlyVersion(arg)) {
rc = true;
return;
}
try {
sosConfiguration = new sos.configuration.SOSConfiguration(arg, settingsFile, settingsSection, logger);
sos.configuration.SOSConfigurationItem[] items = sosConfiguration.checkConfigurationItems(REQUIRED_DEFAULT_PARAMETERS_FILENAME_NOREQUIRE);
}
catch (Exception e) {
System.out.println("[ERROR] could not init Configuration, cause: " + e.getMessage());
throw e;
}
operation = checkOperation(); // operation value is given?
Properties arg_s = convertParameters(); // convert ConfigurationItem[] to Properties
logLevel = getIntArg(arg_s, "verbose", (int) SOSLogger.INFO);
logFile = getStringArg(arg_s, "log_filename", "");
createLoggerObject(logFile, logLevel);
ArrayList extractArguments = getFileOperations(arg_s); // Different file operations within one session
try {
banner = true;
rc = transfer(extractArguments, operation, arg_s, rc, false);
if (rc) {
rc = doPostTransactionalOnSuccess();
}
else {
rc = doPostTransactionalOnError();
}
}
catch (Exception e) {
banner = true;
throw e;
}
}
catch (Exception e) {
try {
if (ftpCommand != null) {
if (banner)
logger.info(ftpCommand.getBanner(false));
else
logger.debug(ftpCommand.getBanner(false));
}
else {
System.out.println(e.toString());
}
}
catch (Exception x) {
System.out.println(e.toString());
}
System.exit(1);
}
finally {
try {
if (ftpCommand != null) {
ftpCommand.appendHistoryFile();
ftpCommand.sendTransactionalSchedulerRequestFile();
}
logger.close();
}
catch (Exception e) {
System.out.println(e.toString());
}
System.exit((rc ? 0 : 1));
}
}
/**
* List of transfer Files
*
* @return the filelist
*/
public Vector<String> getFilelist() throws Exception {
return filelist;
}
/**
* List of transfered Files
*
* @return the filelist
*/
public Vector<File> getTransferredFilelist() throws Exception {
if (transferFileList == null) {
transferFileList = new Vector<File>();
}
return transferFileList;
}
/**
* @return the exitStatus
*/
public Integer getExitStatus() {
if (exitStatus != null)
return exitStatus;
else
return new Integer(0);
}
protected boolean getBooleanParam(final String pstrParamName, final String pstrDefaultvalue) throws Exception {
String strResult = getParam(pstrParamName, pstrDefaultvalue);
if (strResult.toString().equalsIgnoreCase("true") || strResult.toString().equalsIgnoreCase("yes") || strResult.equals("1")) {
return true;
}
return false;
}
protected String getParam(final String pstrParamName, final String pstrDefaultvalue) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::getParam";
String strRet = "";
String strVal = "";
try {
strVal = sosString.parseToString(arguments.get(pstrParamName.toLowerCase()));
if (strVal.length() <= 0) {
String strNewParamName = pstrParamName.replaceAll("_", "");
strVal = sosString.parseToString(arguments.get(strNewParamName.toLowerCase()));
}
}
catch (Exception e) {
}
this.getLogger().debug(String.format(".. get Parameter '%1$s' with value '%2$s', default is '%3$s'", pstrParamName, strVal, pstrDefaultvalue));
if (strVal.length() > 0) {
strRet = strVal;
}
else {
strRet = pstrDefaultvalue;
}
return strRet;
} // private String getParam
protected String doEncoding(final String pstrStringToEncode, final String pstrEncoding) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::doEncoding";
// Zeichen Unicode
// ------------------------------
// �, � \u00c4, \u00e4
// �, � \u00d6, \u00f6
// �, � \u00dc, \u00fc
// � \u00df
final String conUTF8UmlU = "ü";
final String conUTF8UmlBigA = "\u00c4"; // "�\\?";
final String conUTF8UmlBigO = "\u00d6"; // "�\\?";
final String conUTF8UmlBigU = "\u00dc"; // "�\\?";
final String conUTF8UmlA = "ä";
final String conUTF8UmlO = "ö";
final String conUTF8UmlS = "\u00df";
String strEncodedString = pstrStringToEncode;
if (pstrEncoding.length() > 0) {
byte[] iso88591Data = pstrStringToEncode.getBytes(Charset.forName(pstrEncoding));
strEncodedString = new String(iso88591Data, Charset.forName(pstrEncoding));
strEncodedString = strEncodedString.replaceAll(conUTF8UmlU, "�");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlBigA, "�");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlBigU, "�");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlBigO, "�");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlA, "�");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlO, "�");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlS, "�");
getLogger().debug(String.format("Encode String '%1$s' to/in '%2$s' using '%3$s'", pstrStringToEncode, strEncodedString, pstrEncoding));
}
return strEncodedString;
} // private String doEncoding
protected String doEncodeUmlaute(final String pstrStringToEncode, final String pstrEncoding) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::doEncodeUmlaute";
// Zeichen Unicode
// ------------------------------
// �, � \u00c4, \u00e4
// �, � \u00d6, \u00f6
// �, � \u00dc, \u00fc
// � \u00df
final String conUTF8UmlU = "�";
final String conUTF8UmlBigA = "\u00c4"; // "�\\?";
final String conUTF8UmlBigO = "\u00d6"; // "�\\?";
final String conUTF8UmlBigU = "\u00dc"; // "�\\?";
final String conUTF8UmlA = "�";
final String conUTF8UmlO = "�";
final String conUTF8UmlS = "\u00df";
String strEncodedString = pstrStringToEncode;
if (pstrEncoding.length() > 0) {
byte[] iso88591Data = pstrStringToEncode.getBytes(Charset.forName(pstrEncoding));
strEncodedString = new String(iso88591Data, Charset.forName(pstrEncoding));
strEncodedString = strEncodedString.replaceAll(conUTF8UmlU, "ue");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlBigA, "Ae");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlBigU, "Ue");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlBigO, "Oe");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlA, "ae");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlO, "oe");
strEncodedString = strEncodedString.replaceAll(conUTF8UmlS, "sz");
getLogger().debug(String.format("Encode String '%1$s' to/in '%2$s' using '%3$s'", pstrStringToEncode, strEncodedString, pstrEncoding));
}
return strEncodedString;
} // private String doEncoding
protected void retrieveCommonParameters() throws Exception {
flgUsePathAndFileName4Matching = getBooleanParam(SOSFTPCommand.USE_PATH_AND_FILE_NAME_4_MATCHING, "false");
flgCheckServerFeatures = getBooleanParam(SOSFTPCommand.CHECK_SERVER_FEATURES, "");
strPreFtpCommands = getParam(PRE_FTP_COMMANDS, "");
strControlEncoding = getParam(SOSFTPCommand.CONTROL_ENCODING, "");
strFileNameEncoding = getParam(SOSFTPCommand.FILENAME_ENCODING, "");
flgConvertUmlaute = getBooleanParam(SOSFTPCommand.CONVERT_UMLAUTE, "false");
}
public void setParam(final String pstrParamName, final String pstrParamValue) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::setParam";
arguments.put(pstrParamName, pstrParamValue);
logger.debug(String.format("set param '%1$s' to value '%2$s'", pstrParamName, pstrParamValue));
} // private void setParam
protected String stripRemoteDirName(final String pstrRootPath, final String pstrPathName) throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::stripRemoteDirName";
String strResult = pstrPathName;
String strR = new File(pstrRootPath).getAbsolutePath();
String strP = new File(pstrPathName).getAbsolutePath();
if (strP.startsWith(strR) == true) {
strResult = strP.substring(strR.length());
if (strResult.contains(File.separator)) {
if (strResult.startsWith(File.separator)) {
strResult = strResult.substring(1);
}
if (strResult.contains(File.separator)) {
strResult = "." + File.separator + strResult;
}
}
// strResult = new File(strResult).getCanonicalPath();
strResult = adjustSeparator(strResult);
}
return strResult;
} // private String stripRemoteDirName
protected String adjustSeparator(final String pstrPathName) {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::";
String strRet = pstrPathName;
String[] strA = pstrPathName.split("[/\\\\]");
if (strA.length > 0) {
strRet = "";
for (String string : strA) {
if (string.length() > 0) {
strRet = strRet + string + File.separator;
}
}
strRet = strRet.substring(0, strRet.length() - 1);
}
return strRet;
} // private String adjustSeparator
}