/********************************************************* begin of preamble
**
** Copyright (C) 2003-2010 Software- und Organisations-Service GmbH.
** All rights reserved.
**
** This file may be used under the terms of either the
**
** GNU General Public License version 2.0 (GPL)
**
** as published by the Free Software Foundation
** http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
** LICENSE.GPL included in the packaging of this file.
**
** or the
**
** Agreement for Purchase and Licensing
**
** as offered by Software- und Organisations-Service GmbH
** in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package com.sos.DataExchange;
import java.io.IOException;
import java.util.HashMap;
import java.util.Properties;
import java.util.Vector;
import org.apache.log4j.Logger;
import com.sos.JSHelper.Basics.JSJobUtilities;
import com.sos.JSHelper.Basics.JSVersionInfo;
import com.sos.JSHelper.Exceptions.JobSchedulerException;
import com.sos.VirtualFileSystem.DataElements.SOSFileList;
import com.sos.VirtualFileSystem.DataElements.SOSFileListEntry;
import com.sos.VirtualFileSystem.FTP.SOSFTPOptions;
import com.sos.VirtualFileSystem.Factory.VFSFactory;
import com.sos.VirtualFileSystem.Interfaces.ISOSVFSHandler;
import com.sos.VirtualFileSystem.Interfaces.ISOSVfsFileTransfer;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFile;
import com.sos.i18n.I18NBase;
import com.sos.i18n.annotation.I18NMessage;
import com.sos.i18n.annotation.I18NMessages;
import com.sos.i18n.annotation.I18NResourceBundle;
@I18NResourceBundle(baseName = "SOSDataExchange", defaultLocale = "en")
public class SOSDataExchangeEngine extends I18NBase implements JSJobUtilities {
private final String conClassName = "SOSDataExchangeEngine";
private Logger logger = Logger.getLogger(SOSDataExchangeEngine.class);
private ISOSVFSHandler objVFS4Target = null;
private ISOSVFSHandler objVFS4Source = null;
public ISOSVfsFileTransfer objDataTargetClient = null;
public ISOSVfsFileTransfer objDataSourceClient = null;
private SOSFTPOptions objOptions = null;
private SOSFileList objSourceFileList = null;
private boolean jump = false; // TODO tempor�r
private boolean makeDirs = false;
/** This parameter specifies whether zero byte files should be transferred and processed by subsequent jobs. The following settings are available */
private boolean zeroByteFiles = true;
private boolean zeroByteFilesStrict = false;
private boolean zeroByteFilesRelaxed = false;
/** notification by e-mail in case of transfer of empty files. */
private String fileNotificationTo = "";
private String fileNotificationCC = "";
private String fileNotificationBCC = "";
private String fileNotificationSubject = "";
private String fileNotificationBody = "";
private String fileZeroByteNotificationTo = "";
private String fileZeroByteNotificationCC = "";
private String fileZeroByteNotificationBCC = "";
private String fileZeroByteNotificationSubject = "";
private String fileZeroByteNotificationBody = "";
private JSJobUtilities objJSJobUtilities = this;
// private boolean sameConnection = false;
// private int count = 0;
private int zeroByteCount = 0; // tempor�r
// private boolean isFilePath = false;
private String state = "";
/**
* Resource filenames for operation = install
*/
@SuppressWarnings("unused")
private boolean testmode = false;
@I18NMessages(value = { @I18NMessage("%1$s: Exception raised, reason is: %2$s"), //
@I18NMessage(value = "%1$s: Exception raised, reason is: %2$s", locale = "en_UK", //
explanation = "%1$s: Exception raised, cause: %2$s" //
), //
@I18NMessage(value = "%1$s: Ausnahmefehler aufgetreten, Ursache ist vermutlich: %2$s", locale = "de", //
explanation = "%1$s: Eine Java-Exception mit dem Grund: %2$s ist aufgetreten." //
) //
}, msgnum = "SOS-E-1001", msgurl = "")
/*!
* \var EXCEPTION_RAISED
* \brief %1$s: Exception raised, cause: %2$s
*/
final String EXCEPTION_RAISED = conClassName + ".EXCEPTION_RAISED";
@I18NMessages(value = { @I18NMessage("could not complete transaction, cause: {0}"), //
@I18NMessage(value = "could not complete transaction, cause: {0}", locale = "en_UK", //
explanation = "could not complete transaction, cause: {0}" //
), //
@I18NMessage(value = "Transaktion wurde fehlerhaft abgebrochen, Ursache: {0}", locale = "de", //
explanation = "Die Transaktion wurde abgebrochen und alle Aktionen r�ckg�ngig gemacht." //
) //
}, msgnum = "SOSDX-E-0002", msgurl = "")
/*!
* \var TRANSACTION_ABORTED
* \brief could not complete transaction, cause: %1$s
*/
final String TRANSACTION_ABORTED = "SOSDataExchangeEngine.TRANSACTION_ABORTED";
public SOSDataExchangeEngine() throws Exception {
super("SOSDataExchange");
init();
}
private void init() {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::init";
logger.info(conClassName + " --- " + JSVersionInfo.getVersionString());
} // private void init
/**
* @param settingsFile
* @param settingsSection
* @param logger
* @param arguments_
*/
public SOSDataExchangeEngine(Properties pobjProperties) throws Exception {
super();
this.Options();
// TODO Properties in die OptionsClasse weiterreichen
// objOptions.setAllOptions(pobjProperties);
}
public SOSDataExchangeEngine(SOSFTPOptions pobjOptions) throws Exception {
super();
this.objOptions = pobjOptions;
}
public SOSDataExchangeEngine(HashMap<String, String> pobjJSSettings) throws Exception {
super();
this.Options();
objOptions.setAllOptions(pobjJSSettings);
}
@SuppressWarnings("unused")
private ISOSVFSHandler getVFS() throws Exception {
if (objVFS4Target == null) {
objVFS4Target = VFSFactory.getHandler(objOptions.getDataTargetType());
}
return objVFS4Target;
}
public SOSFTPOptions Options() {
if (objOptions == null) {
objOptions = new SOSFTPOptions();
}
return objOptions;
}
public boolean Run() throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::Run";
return this.transfer();
}
public boolean Execute() throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::execute";
return this.transfer();
}
public ISOSVfsFileTransfer DataSourceClient() {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::DataSourceClient";
if (objDataSourceClient == null) {
try {
objVFS4Source = VFSFactory.getHandler(objOptions.getDataSourceType());
objVFS4Source.Connect(objOptions.getConnectionOptions().Source());
objVFS4Source.Authenticate(objOptions.getConnectionOptions().Source());
objVFS4Source.setSource();
objVFS4Source.Options(objOptions);
}
catch (Exception e) {
throw new JobSchedulerException("Problems creating/connecting DataSourceClient", e);
}
}
return objDataSourceClient;
} // private ISOSVfsFileTransfer DataSourceClient
/**
*
* \brief DataTargetClient
* Returns an instance of the TargetClient
*
* \details
*
* \return ISOSVfsFileTransfer
*
* @return
* @throws Exception
*/
public ISOSVfsFileTransfer DataTargetClient() throws Exception {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::DataTarget";
if (objDataTargetClient == null) {
objOptions.CheckMandatory();
objVFS4Target = VFSFactory.getHandler(objOptions.getDataTargetType());
objVFS4Target.Connect(objOptions.getConnectionOptions().Target());
objVFS4Target.Authenticate(objOptions.getConnectionOptions().Target());
objDataTargetClient = (ISOSVfsFileTransfer) objVFS4Target;
objVFS4Target.setTarget();
objVFS4Target.Options(objOptions);
}
return objDataTargetClient;
} // private ISOSVfsFileTransfer DataTarget
/**
* Send files by FTP/SFTP to a target
*
* @return boolean
* @throws Exception
*/
public boolean transfer() throws Exception {
boolean rc = false;
try { // to connect, authenticate and execute commands
Options().CheckMandatory();
// logger.debug(Options().toString());
objSourceFileList = new SOSFileList(objVFS4Target);
objSourceFileList.Options(objOptions);
objSourceFileList.StartTransaction();
DataSourceClient();
DataTargetClient();
try {
// objDataTargetClient = (ISOSVfsFileTransfer) objVFS4Target;
objDataSourceClient = (ISOSVfsFileTransfer) objVFS4Source;
objSourceFileList.objDataSourceClient = objDataSourceClient;
objSourceFileList.objDataTargetClient = objDataTargetClient;
if (objOptions.passive_mode.value()) {
objDataTargetClient.passive();
objDataSourceClient.passive();
}
objDataTargetClient.TransferMode(objOptions.transfer_mode);
objDataSourceClient.TransferMode(objOptions.transfer_mode);
objDataTargetClient.ControlEncoding(objOptions.ControlEncoding.Value());
objDataSourceClient.ControlEncoding(objOptions.ControlEncoding.Value());
if (objOptions.PreFtpCommands.IsNotEmpty()) {
String[] strA = objOptions.PreFtpCommands.Value().split(";");
for (String strCmd : strA) {
objDataTargetClient.getHandler().ExecuteCommand(strCmd);
}
}
makeDirs();
String strSourceDir = objOptions.SourceDir.Value();
String strRemoteDir = objOptions.TargetDir.Value();
boolean flgRecurseFolders = objOptions.recursive.value();
if (objOptions.OneOrMoreSingleFilesSpecified()) {
objSourceFileList.add(getSingleFileNames(), strSourceDir);
}
else {
String fileSpec = objOptions.file_spec.Value();
objDataSourceClient.changeWorkingDirectory(strSourceDir);
ISOSVirtualFile objLocFile = objDataSourceClient.getFileHandle(strSourceDir);
String strM = "source directory/file: " + strSourceDir + ", target directory: " + strRemoteDir + ", file regexp: " + fileSpec;
logger.debug(strM);
if (objLocFile.isDirectory() == true) {
String[] strFileList = objDataSourceClient.getFilelist(strSourceDir, fileSpec, 0, flgRecurseFolders);
objSourceFileList.add(strFileList, strSourceDir);
}
else {
objSourceFileList.add(strSourceDir);
}
}
// TODO implement polling for files
// TODO in Options setzen anhand der Values in der Liste.
if (zeroByteFiles == false) {
// TODO in die SOSFileList einbauen (SkipZeroByteFiles)
for (SOSFileListEntry objEntry : objSourceFileList.List()) {
String strSourceFileName = objEntry.SourceFileName();
ISOSVirtualFile objVF = objDataSourceClient.getFileHandle(strSourceFileName);
if (objVF.FileExists()) {
if (objVF.isEmptyFile()) {
objEntry.setTransferSkipped();
if (objOptions.remove_files.value()) {
objVF.delete();
objEntry.zeroByteCount++;
}
}
}
else {
// TODO Datei (nicht mehr) da? Fehler ausl�sen, weil in Liste enthalten.
}
}
} // (zeroByteFiles == false)
try {
sendFiles(objSourceFileList);
objDataSourceClient.close();
objDataTargetClient.close();
objSourceFileList.renameAtomicTransferFiles();
objSourceFileList.DeleteSourceFiles();
}
catch (JobSchedulerException e) {
e.printStackTrace(System.err);
String strM = getMsg(TRANSACTION_ABORTED, e.toString());
if (objOptions.transactional.value()) {
logger.error(strM, e);
}
else {
logger.error(strM, e);
}
objSourceFileList.Rollback();
throw new JobSchedulerException(strM, e);
}
finally {
objSourceFileList.EndTransaction();
}
objSourceFileList.sendMails();
// TODO in die Klasse SOSFileList oder SOSFtpCommand
rc = printState(rc);
// }
// TODO das mu� beim JobScheduler-Job in die Parameter zur�ck, aber nur da
// siehe hierzu das Interface ...
// arguments.put("successful_transfers", String.valueOf(count));
// return the number of transferred files
// arguments.put("status", "success");
return rc;
}
catch (Exception e) {
// arguments.put("status", "error");
// failed_transfer++;
// arguments.put("failed_transfers", String.valueOf(failed_transfer));
rc = false;
e.printStackTrace(System.err);
throw (new JobSchedulerException("could not process file transfer: " + e.getMessage()));
}
finally {
if (jump) { // jump host ist angegeben, hier m�ssen z.B. tempor�r generierte Verzeichnisse auf Remote host gel�scht werden
rc = doPostCommands(rc, objSourceFileList);
}
}
}
catch (Exception e) {
e.printStackTrace(System.err);
logger.error("data transfer failed: ", e);
// if (sosString.parseToString(logger.getWarning()).length() > 0 || sosString.parseToString(logger.getError()).length() > 0) {
// //TODO in die Order/Job-Parameter
// getArguments().put("last_error", logger.getWarning() + " " + logger.getError());
// }
// TODO das mu� in die SOSFileList geschoben werden bzw in die SOSFTPCommand
// writeHistory(localFile != null ? localFile.getAbsolutePath() : "", "");
throw new JobSchedulerException("processing aborted.", e);
}
}
public void Logout() {
try {
if (objDataTargetClient != null) {
objDataTargetClient.logout();
objDataTargetClient.disconnect();
objDataTargetClient = null;
}
if (objDataSourceClient != null) {
objDataSourceClient.logout();
objDataSourceClient.disconnect();
objDataSourceClient = null;
}
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// TODO Keep_connection ist nicht dokumentiert. deshalb nicht in der Options-Klasse
/**
* Parameter auslesen
* @throws Exception
*/
// if (sosString.parseToString(arguments.get("keep_connection")).length() > 0) {
// String keep = sosString.parseToString(arguments.get("keep_connection"));
// if (keep.equalsIgnoreCase("true") || keep.equalsIgnoreCase("1")) {
// keepConnection = true;
// }
// else {
// keepConnection = false;
// }
// }
// else {
// keepConnection = false;
// }
//
// if (keepConnection) {
// sameConnection = ftpClient != null && ftpClient.isConnected() && lastHost.equalsIgnoreCase(host) && lastPort == port
// && lastUser.equalsIgnoreCase(user) && lastAccount.equalsIgnoreCase(account);
// }
// if (ftpClient != null && ftpClient.isConnected() && !sameConnection) {
// try {
// if (isLoggedIn)
// ftpClient.logout();
// ftpClient.disconnect();
// }
// catch (Exception e) {
// }
// }
// if (sosString.parseToString(arguments.get("file_zero_byte_transfer")).length() > 0) {
// if (sosString.parseToString(arguments.get("file_zero_byte_transfer")).equals("1")
// || sosString.parseToString(arguments.get("file_zero_byte_transfer")).equalsIgnoreCase("true")
// || sosString.parseToString(arguments.get("file_zero_byte_transfer")).equalsIgnoreCase("yes")) {
// zeroByteFiles = true;
// zeroByteFilesStrict = false;
// }
// else
// if (sosString.parseToString(arguments.get("file_zero_byte_transfer")).equalsIgnoreCase("strict")) {
// zeroByteFiles = false;
// zeroByteFilesStrict = true;
// }
// else
// if (sosString.parseToString(arguments.get("file_zero_byte_transfer")).equalsIgnoreCase("relaxed")) {
// zeroByteFiles = false;
// zeroByteFilesStrict = false;
// zeroByteFilesRelaxed = true;
// }
// else {
// zeroByteFiles = false;
// zeroByteFilesStrict = false;
// }
// }
// TODO die notifications sind wohl all enicht dokumentiert mu� nachgeholt werden
// if (sosString.parseToString(arguments.get("file_notification_to")).length() > 0) {
// fileNotificationTo = sosString.parseToString(arguments.get("file_notification_to"));
// }
//
// if (sosString.parseToString(arguments.get("file_notification_cc")).length() > 0) {
// fileNotificationCC = sosString.parseToString(arguments.get("file_notification_cc"));
// }
//
// if (sosString.parseToString(arguments.get("file_notification_bcc")).length() > 0) {
// fileNotificationBCC = sosString.parseToString(arguments.get("file_notification_bcc"));
// }
//
// if (sosString.parseToString(arguments.get("file_notification_subject")).length() > 0) {
// fileNotificationSubject = sosString.parseToString(arguments.get("file_notification_subject"));
// }
//
// if (sosString.parseToString(arguments.get("file_notification_body")).length() > 0) {
// fileNotificationBody = sosString.parseToString(arguments.get("file_notification_body"));
// }
//
// if (sosString.parseToString(arguments.get("file_zero_byte_notification_to")).length() > 0) {
// fileZeroByteNotificationTo = sosString.parseToString(arguments.get("file_zero_byte_notification_to"));
// }
//
// if (sosString.parseToString(arguments.get("file_zero_byte_notification_cc")).length() > 0) {
// fileZeroByteNotificationCC = sosString.parseToString(arguments.get("file_zero_byte_notification_cc"));
// }
//
// if (sosString.parseToString(arguments.get("file_zero_byte_notification_bcc")).length() > 0) {
// fileZeroByteNotificationBCC = sosString.parseToString(arguments.get("file_zero_byte_notification_bcc"));
// }
//
// if (sosString.parseToString(arguments.get("file_zero_byte_notification_subject")).length() > 0) {
// fileZeroByteNotificationSubject = sosString.parseToString(arguments.get("file_zero_byte_notification_subject"));
// }
//
// if (sosString.parseToString(arguments.get("file_zero_byte_notification_body")).length() > 0) {
// fileZeroByteNotificationBody = sosString.parseToString(arguments.get("file_zero_byte_notification_body"));
// }
// TODO testmode nicht dokumentiert, deshalb nicht in OptionsKlasse
// testmode = sosString.parseToBoolean(arguments.get("testmode"));
// TODO die Mail-Options sind nicht dokumentiert.
// if (sosString.parseToString(arguments.get("mail_smtp")).length() > 0)
// mailSMTP = (sosString.parseToString(arguments.get("mail_smtp")));
//
// if (sosString.parseToString(arguments.get("mail_from")).length() > 0)
// mailFrom = (sosString.parseToString(arguments.get("mail_from")));
//
// if (sosString.parseToString(arguments.get("mail_queue_dir")).length() > 0)
// mailQueueDir = (sosString.parseToString(arguments.get("mail_queue_dir")));
// TODO als Default zu den einzelnen Optionen einstellen ....
// private void getFileNotificationParameter() throws Exception {
// try {
// if (fileNotificationTo != null && fileNotificationTo.length() > 0) {
// if (fileNotificationSubject == null || fileNotificationSubject.length() == 0) {
// fileNotificationSubject = "[debug1] SOSFTPCommand";
// }
//
// if (fileNotificationBody == null || fileNotificationBody.length() == 0) {
// fileNotificationBody = "The following files have been sent:\n\n";
// }
// }
//
// if (fileZeroByteNotificationTo != null && fileZeroByteNotificationTo.length() > 0) {
// if (fileZeroByteNotificationSubject == null || fileZeroByteNotificationSubject.length() == 0) {
// fileZeroByteNotificationSubject = "[warning] SOSFTPCommand";
// }
//
// if (fileZeroByteNotificationBody == null || fileZeroByteNotificationBody.length() == 0) {
// fileZeroByteNotificationBody = "The following files have not been sent and were removed due to zero byte constraints:\n\n";
// }
// }
// }
// catch (Exception e) {
// throw new JobSchedulerException("error in " + sos.util.SOSClassUtil.getMethodName() + " , cause: " + e);
// }
// }
/**
* Verzeichnis generieren
* @throws Exception
*/
private void makeDirs() {
try {
boolean cd = true;
// TODO make_dirs ist nicht dokumentiert.
// boolean flgMakeDirs = objOptions.make_dirs.Value();
boolean flgMakeDirs = makeDirs;
String strTargetDir = objOptions.TargetDir.Value();
if (flgMakeDirs) {
if (objDataTargetClient.changeWorkingDirectory(strTargetDir)) {
cd = true;
}
else {
objDataTargetClient.mkdir(strTargetDir);
cd = objDataTargetClient.changeWorkingDirectory(strTargetDir);
}
}
else
if (strTargetDir != null && strTargetDir.length() > 0) {
cd = objDataTargetClient.changeWorkingDirectory(strTargetDir);
}
// TODO alternative_remote_dir, wozu und wie gehen wir damit um?
if (cd == false && objOptions.alternative_remote_dir.IsNotEmpty()) {// alternative Parameter
String alternativeRemoteDir = objOptions.alternative_remote_dir.Value();
logger.debug("..try with alternative parameter [remoteDir=" + alternativeRemoteDir + "]");
cd = objDataTargetClient.changeWorkingDirectory(alternativeRemoteDir);
objOptions.TargetDir.Value(alternativeRemoteDir);
}
}
catch (Exception e) {
throw new JobSchedulerException("..error in makeDirs, cause: " + e);
}
} // private void makeDirs()
// TODO pr�fen, ob eine Verlagerung in SOSFileList die bessere L�sung ist. Stichwort: Multithreading
private void sendFiles(final SOSFileList pobjFileList) {
@SuppressWarnings("unused")
final String conMethodName = conClassName + "::sendFiles";
int intMaxParallelTransfers = 0;
if (objOptions.ConcurrentTransfer.value() == true) {
intMaxParallelTransfers = objOptions.MaxConcurrentTransfers.value();
}
Vector<Thread> objThreads = new Vector<Thread>();
try {
/**
* if "sendTransferHistory" is activated due to not thread-safe xml-parser
* the parallel transfer is omitted.
*/
if (intMaxParallelTransfers <= 0 || objOptions.SendTransferHistory.value() == true) {
for (SOSFileListEntry objSourceFile : pobjFileList.List()) {
objSourceFile.Options(objOptions);
objSourceFile.run();
}
}
else {
int intThreadsRunning = 0;
for (SOSFileListEntry objListItem : pobjFileList.List()) {
objListItem.Options(objOptions);
objListItem.setDataSourceClient(null); // force a new connection
objListItem.setDataTargetClient(null);
Thread objT = new Thread(objListItem);
objT.start();
synchronized (objThreads) {
objThreads.add(objT);
}
boolean flgThreadsActive = true;
intThreadsRunning = 0;
while (flgThreadsActive) {
flgThreadsActive = false;
synchronized (objThreads) {
for (Thread thread : objThreads) {
if (thread.isAlive()) {
flgThreadsActive = true;
intThreadsRunning++;
}
}
}
try {
if (flgThreadsActive == true && intThreadsRunning >= intMaxParallelTransfers) {
Thread.sleep(500); // TODO this should be an option
}
if (intThreadsRunning < intMaxParallelTransfers) {
break;
}
}
catch (InterruptedException e) {
e.printStackTrace();
throw new JobSchedulerException("thread processing interrupted", e);
}
catch (Exception e) {
e.printStackTrace();
throw new JobSchedulerException("thread processing interrupted", e);
}
}
}
}
}
catch (JobSchedulerException e) {
throw e;
}
}
// @SuppressWarnings("unused")
// private void sendFiles2(final SOSFileList pobjFileList) {
// try {
// for (SOSFileListEntry objSourceFile : pobjFileList.List()) {
// File localFile = objSourceFile.getFile();
// if (localFile == null)
// continue;
//
// String strSourceFileName = objSourceFile.getAbsolutePath();
// if (objSourceFile.notExists()) {
// throw new JobSchedulerException(".. file [" + strSourceFileName + "] does not exist ");
// }
//
// if (objSourceFile.polling() == false)
// continue;
//
// File subParent = null;
// String subPath = "";
// String strTargetFolderName = objOptions.TargetDir.Value();
// String localDir = objOptions.SourceDir.Value();
// boolean recursive = objOptions.recursive.value();
// if (recursive && objOptions.isFilePath() == false) {
// // TODO Das Erstellen des Verzeichnis mu� eine separate Methode werden
// // �berpr�fen, ob das Verzeichnis auf den FTP Server existiert, wenn nicht dann soll das gleiche Verzeichnis generiert
// // werden
// if (localFile.getParent() != null && localFile.getParentFile().isDirectory()) { // es existieren Vaterknoten
// subPath = strSourceFileName.toString().substring((localDir.length() + 1)); // Unterverzeichnisse sind alle
// // Verzeichnisse unterhalb der localDir
// subParent = new File(subPath).getParentFile();
//
// if (subParent != null) {
// subPath = subPath.replaceAll("\\\\", "/");
// subPath = subPath.substring(0, subPath.length() - new File(strSourceFileName.toString()).getName().length() - 1);
// logger.debug(".. creating sub-directory on remote host: " + subPath);
// String[] ftpFiles = objDataTargetClient.listNames(strTargetFolderName + "/" + subPath);
// if (ftpFiles == null || ftpFiles.length == 0) {
// objDataTargetClient.mkdir(strTargetFolderName + "/" + subPath);
// }
// }
// }
// }
//
// if (zeroByteFiles == false && objSourceFile.isEmptyFile())
// continue;
//
// objSourceFile.getTargetFile(objOptions);
//
// if (subParent != null && recursive) {
// // fleTransferFile = new File((subParent != null ? subParent.getName() + "/" : "") + fleTransferFile.getName());
// // strTransferFilename = (subParent != null ? subPath + "/" : "") + fleTransferFile.getName();
// }
//
// long bytesSend = 0;
// String strTargetFileName = objSourceFile.TargetFileName();
// Vector<String> vecTargetFileNamesList = objDataTargetClient.nList(strTargetFileName);
// logger.debug("target-server reply [filename exists] [" + strTargetFileName + "]: " + objDataTargetClient.getReplyString());
//
// if (objOptions.transactional.value() == true) {
// objSourceFile.setTransactionalLocalFile();
// }
//
// if (objOptions.DoNotOverwrite()) {
// if (vecTargetFileNamesList.isEmpty() == false) {
// objSourceFile.setNotOverwritten();
// continue;
// }
// }
//
// if (objOptions.isAtomicTransfer()) {
// objSourceFile.setStatus(enuTransferStatus.transferring);
// bytesSend = objDataTargetClient.putFile(objSourceFile.SourceTransferName(), objSourceFile.TargetTransferName());
//
// if (objOptions.overwrite_files.value() == true) {
// // hier werden Dateien gel�scht, vor dem umbenennen.
// // Besser: auch erstmal umbenennen und dann erst l�schen
// if (vecTargetFileNamesList.isEmpty() == false && vecTargetFileNamesList.contains(strTargetFileName)) {
// objDataTargetClient.delete(strTargetFileName);
// }
// }
//
// // TODO Warum schon hier umbenennen, und nicht erst dann, wenn alle Dateien �bertragen sind? In FileListentry ist das zu
// // finden
// if (objOptions.transactional.value() == false) {
// objDataTargetClient.rename(objSourceFile.TargetTransferName(), objSourceFile.TargetFileName());
// }
// }
// else {
// objSourceFile.setStatus(enuTransferStatus.transferring);
// if (objOptions.append_files.value() == true) {
// bytesSend = objDataTargetClient.appendFile(objSourceFile.SourceTransferName(), objSourceFile.TargetTransferName());
// }
// else {
// bytesSend = objDataTargetClient.putFile(objSourceFile.SourceTransferName(), objSourceFile.TargetTransferName());
// }
// }
// objSourceFile.setNoOfBytesTransferred(bytesSend);
// objSourceFile.TransferStatus(enuTransferStatus.transferred);
// // TODO das mu� in die FileEntry-Klasse
// // writeHistory(fleSourceFile.getAbsolutePath(), fleTransferFile.getAbsolutePath());
//
// // TODO das ist eine merkw�rdige Art zu pr�fen
// // if (objOptions.check_size.value() == true && objSourceFile.length() > 0 && objSourceFile.length() !=
// // objSourceFile.NoOfBytesTransferred()) {
// // throw new JobSchedulerException("..error occurred sending file, target file size [" + objSourceFile.length()
// // + "] does not match number of bytes transferred [" + objSourceFile.NoOfBytesTransferred() + "]");
// // }
//
// if (objOptions.remove_files.value() == true) {
// objSourceFile.getFile().delete();
// }
// }
//
// }
// catch (Exception e) {
// String strT = "error. unable to send files, cause: " + e;
// // TODO rollback?
// logger.error(strT);
// throw new JobSchedulerException(strT, e);
// }
// }
/**
* Es wurde ein Jump Host angegeben.
*
* Alle tempor�ren Verzeichnisse auf dem Remote Host sollen gel�scht werden.
*
* @param rc
* @param filelist
* @return
* @throws Exception
*/
private boolean doPostCommands(boolean rc, SOSFileList filelist) throws Exception {
final String conMethodName = conClassName + "::doPostCommands";
try {
// logger.debug("enter " + sos.util.SOSClassUtil.getMethodName());
// arguments.put("xx_make_temp_directory_xx", "ok"); //hilfsvariable, wenn dieser key existiert, dann gilt im execute diese
// Parameter
// if (!logger.hasWarnings()) {//fehler beim transferieren, also vom jump_host nicht weitersenden
// if (sosString.parseToString(postCommands).length() > 0) {
// this.setCommands(postCommands.split(getCommandDelimiter()));
// if (!execute())
// throw new JobSchedulerException("error occurred processing command:" + normalizedPassword(postCommands));
// }
// }
// //Auf jeden fall soll das Tempor�re Verzeichnis gel�scht werden
// //jump_command nicht ausgelesen //
// String com = sosString.parseToString(arguments.get("jump_command")) + " -operation=remove_temp_directory -input=\"" +
// tempJumpRemoteDir + "\"";
// this.setCommands(com.split(getCommandDelimiter()));
// if (!execute()) {
// arguments.remove("xx_make_temp_directory_xx");
// logger.warn("error occurred processing command:" + tempJumpRemoteDir);
// }
// arguments.remove("xx_make_temp_directory_xx");
//
// if (rc) {
// //jump_host hat erfolgreich alle Dateien an target_host weitergegeben. Jetzt
// //k�nnen die lokalen Dateien gel�scht werden, wenn der Parameter remove_files=yes angegeben ist
// if (!objOptions.transactional.value() && sosString.parseToBoolean(arguments.get("remove_after_jump_transfer"))) {
// for (int i = 0; i < filelist.List().size(); i++) {
// File f = new File(sosString.parseToString(filelist.List().get(i)));
// if (!f.delete()) {
// throw new JobSchedulerException("..error occurred, could not remove local file: " + f.getAbsolutePath());
// }
// else {
// logger.ebug("removing localfile: " + f.getAbsolutePath());
// }
// }
// arguments.remove("remove_after_jump_transfer");
// }
// else {
// rc = false;
// }
// }
return rc;
}
catch (Exception e) {
throw new JobSchedulerException(String.format(getMsg(EXCEPTION_RAISED), conMethodName, e));
}
}
/**
* senden von Mails
* @throws Exception
*/
/**
* Statt ein Verzeichnis k�nnen ein oder mehrere - mit semikolen getrennt - dateien zum transferieren angegeben wrden
* @return
*/
private String[] getSingleFileNames() {
final String conMethodName = conClassName + "::getSingleFileNames";
String filePath = objOptions.file_path.Value();
// String strPS = System.getProperty("file.separator");
String strPS = "/"; // standard on FTP/SFTP
logger.debug("single file(s) specified : " + filePath);
Vector<String> filelist = new Vector<String>();
try {
String localDir = objOptions.SourceDir.Value().trim();
// TODO separator-char variable as Option
String[] split = filePath.split(";");
for (String strT : split) {
strT = strT.trim();
if (strT.length() > 0) {
if (localDir.trim().length() > 0) {
if (strT.contains("\\") == false && strT.contains("/") == false) {
/**
* Problem with folders, when pgs run on Windows, but has to
* create a path for unix-systems.
*/
// strT = new File(localDir, strT).getAbsolutePath();
strT = AddFileSeparator(localDir) + strT;
}
}
filelist.add(strT);
}
}
}
catch (Exception e) {
String strM = String.format("error in %1$s", conMethodName);
logger.error(strM + e);
throw new JobSchedulerException(strM, e);
}
String[] strA = { "" };
if (filelist.size() > 0) {
strA = (String[]) filelist.toArray(new String[filelist.size()]);
}
return strA;
}
private String AddFileSeparator(final String pstrPathName) {
String strT = pstrPathName;
int intL = strT.length();
if (intL > 0) {
String strL = strT.substring(intL - 1, intL);
if (strL.equals("\\") || strL.equals("/")) {
}
else {
// strT += File.separator;
strT += "/";
}
}
return strT;
}
/**
* Zustand ausgeben. Erst ab log_level 1
* @param rc
* @return
* @throws Exception
*/
private boolean printState(boolean rc) throws Exception {
final String conMethodName = conClassName + "::printState";
try {
state = "processing successful ended";
int count = (int) objSourceFileList.SuccessfulTransfers();
switch (count) {
case 0:
if (zeroByteCount > 0 && zeroByteFilesRelaxed) {
state = "no matching files found, " + zeroByteCount + " zero byte files skipped";
}
else
if (zeroByteCount > 0 && zeroByteFilesStrict) {
throw new JobSchedulerException("zero byte file(s) found");
}
else
if (objOptions.force_files.value() == true) {
if (objSourceFileList.List().size() <= 0) {
throw new JobSchedulerException("no (matching) files found");
}
}
else {
state = "no matching files found";
}
rc = (objOptions.force_files.value() == false ? true : !zeroByteFilesRelaxed);
break;
case 1:
String strM = "";
if (zeroByteCount > 0) {
strM = String.format("%1$d files skipped due to zero byte constraint", zeroByteCount);
}
state = "1 file transferred. " + strM;
rc = true;
break;
default:
state = count + " files transferred" + ((zeroByteCount > 0) ? ", " + zeroByteCount + " files skipped due to zero byte constraint" : "");
rc = true;
break;
}
logger.info(state);
return rc;
}
catch (Exception e) {
throw new JobSchedulerException(String.format(EXCEPTION_RAISED, conMethodName, e));
}
}
// TODO install in eine separate Klasse verpacken weil es mit FTP nicht so viel zu tun hat. Vielleicht kann sie ja auch in einem anderen
// Zusammenhang eingesetzt werden.
/**
* @return the state
*/
public String getState() {
return state;
}
public SOSFileList getFileList() {
return objSourceFileList;
}
/**
*
* \brief setJSJobUtilites
*
* \details
* The JobUtilities are a set of methods used by the SSH-Job or can be used be other, similar, job-
* implementations.
*
* \return void
*
* @param pobjJSJobUtilities
*/
public void setJSJobUtilites(JSJobUtilities pobjJSJobUtilities) {
if (pobjJSJobUtilities == null) {
objJSJobUtilities = this;
}
else {
objJSJobUtilities = pobjJSJobUtilities;
// objVFS.setJSJobUtilites(pobjJSJobUtilities);
}
logger.debug("objJSJobUtilities = " + objJSJobUtilities.getClass().getName());
}
/**
*
* \brief replaceSchedulerVars
*
* \details
* Dummy-Method to make sure, that there is always a valid Instance for the JSJobUtilities.
* \return
*
* @param isWindows
* @param pstrString2Modify
* @return
*/
@Override
public String replaceSchedulerVars(boolean isWindows, String pstrString2Modify) {
final String conMethodName = conClassName + "::replaceSchedulerVars";
logger.debug(conMethodName + " as Dummy-call executed. No Instance of JobUtilites specified.");
return pstrString2Modify;
}
/**
*
* \brief setJSParam
*
* \details
* Dummy-Method to make shure, that there is always a valid Instance for the JSJobUtilities.
* \return
*
* @param pstrKey
* @param pstrValue
*/
@Override
public void setJSParam(String pstrKey, String pstrValue) {
final String conMethodName = conClassName + "::setJSParam";
logger.debug(conMethodName + " as Dummy-call executed. No Instance of JobUtilites specified.");
}
@Override
public void setJSParam(String pstrKey, StringBuffer pstrValue) {
final String conMethodName = conClassName + "::setJSParam";
logger.debug(conMethodName + " as Dummy-call executed. No Instance of JobUtilites specified.");
}
@Override
public String myReplaceAll(String pstrSourceString, String pstrReplaceWhat, String pstrReplaceWith) {
String newReplacement = pstrReplaceWith.replaceAll("\\$", "\\\\\\$");
return pstrSourceString.replaceAll("(?m)" + pstrReplaceWhat, newReplacement);
}
@Override
public String getCurrentNodeName() {
return "";
}
}