com.sos.VirtualFileSystem.DataElements.SOSFileListEntry.java Source code

Java tutorial

Introduction

Here is the source code for com.sos.VirtualFileSystem.DataElements.SOSFileListEntry.java

Source

/**
 * Copyright (C) 2014 BigLoupe http://bigloupe.github.io/SoS-JobScheduler/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */
/********************************************************* begin of preamble
**
** Copyright (C) 2003-2012 Software- und Organisations-Service GmbH. 
** All rights reserved.
**
** This file may be used under the terms of either the 
**
**   GNU General Public License version 2.0 (GPL)
**
**   as published by the Free Software Foundation
**   http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
**   LICENSE.GPL included in the packaging of this file. 
**
** or the
**  
**   Agreement for Purchase and Licensing
**
**   as offered by Software- und Organisations-Service GmbH
**   in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package com.sos.VirtualFileSystem.DataElements;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Properties;
import java.util.UUID;

import org.apache.commons.net.util.Base64;
import org.apache.log4j.Logger;

import com.sos.JSHelper.Exceptions.JobSchedulerException;
import com.sos.JSHelper.Options.SOSOptionString;
import com.sos.JSHelper.Options.SOSOptionTime;
import com.sos.JSHelper.io.Files.JSTextFile;
import com.sos.VirtualFileSystem.FTP.SOSFTPOptions;
import com.sos.VirtualFileSystem.Factory.VFSFactory;
import com.sos.VirtualFileSystem.Interfaces.IJadeTransferDetailHistoryData;
import com.sos.VirtualFileSystem.Interfaces.ISOSFtpOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSVFSHandler;
import com.sos.VirtualFileSystem.Interfaces.ISOSVfsFileTransfer;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFile;
import com.sos.VirtualFileSystem.Options.SOSConnection2OptionsAlternate;
import com.sos.VirtualFileSystem.common.SOSVfsConstants;
import com.sos.VirtualFileSystem.common.SOSVfsMessageCodes;
import com.sos.VirtualFileSystem.zip.SOSVfsZip;
import com.sos.i18n.annotation.I18NResourceBundle;
import com.sos.scheduler.model.SchedulerObjectFactory;
import com.sos.scheduler.model.commands.JSCmdAddOrder;
import com.sos.scheduler.model.objects.Params;
import com.sos.scheduler.model.objects.Spooler;

/**
* <p style="text-align:center">
* <br />---------------------------------------------------------------------------
APL/Software GmbH - Berlin
##### generated by ClaviusXPress (http://www.sos-berlin.com) #########
Montag, 15. Oktober 2007, Klaus.Buettner@sos-berlin.com (KB)
* <br />---------------------------------------------------------------------------
* </p>
* SOSFileListEntry - Datenstruktur fr Dateiverarbeitung
* <p>
* Diese Klasse reprsentiert eine Datenstruktur fr die Dateiverarbeitung
* von lokalen und remote Dateien.
* </p>
* <p>
* Verwendung findet diese Struktur beim download von Dateien, deren Name
* ber einen (regulren) Ausdruck definiert ist und dabei dann mehr als
* eine Datei relevant ist.
* </p>
* @author Klaus.Buettner@sos-berlin.com
* @version $Id: SOSFileListEntry.java 20078 2013-05-06 00:30:05Z oh $ 0.9
* @see reference
* @exception classname description
*
*/
@I18NResourceBundle(baseName = "SOSVirtualFileSystem", defaultLocale = "en")
public class SOSFileListEntry extends SOSVfsMessageCodes
        implements Runnable, IJadeTransferDetailHistoryData /* , ISOSVirtualFile */ {
    private static String conClassName = "SOSFileListEntry";
    private final Logger logger = Logger.getLogger(SOSFileListEntry.class);
    private static Logger objJadeReportLogger = Logger.getLogger(VFSFactory.getLoggerName());
    @SuppressWarnings("unused")
    private final String conSVNVersion = "$Id: SOSFileListEntry.java 20078 2013-05-06 00:30:05Z oh $";

    private static boolean flgNoDataSent = false;
    private ISOSVirtualFile fleSourceTransferFile = null;
    private ISOSVirtualFile fleSourceFile = null;
    private ISOSVirtualFile fleTargetFile = null;
    private String strSourceFileName = null;
    private String strSourceTransferName = null;
    private String strTargetTransferName = null;
    private String strTargetFileName = null;
    private long lngNoOfBytesTransferred = 0;
    private long lngFileSize = -1L;
    private long lngFileModDate = -1L;
    private final String strZipFileName = "";
    private long lngTransferProgress = 0;
    private boolean flgTransactionalRemoteFile = false;
    private boolean flgTransactionalLocalFile = false;
    public long zeroByteCount = 0;
    private long lngOriginalFileSize = 0;
    @SuppressWarnings("unused")
    private final boolean flgTransferSkipped = false;
    private SOSFTPOptions objOptions = null;
    private String strAtomicFileName = EMPTY_STRING;
    private enuTransferStatus eTransferStatus = enuTransferStatus.transferUndefined;

    public enum enuTransferStatus {
        transferUndefined, waiting4transfer, transferring, transferInProgress, transferred, transfer_skipped, transfer_has_errors, transfer_aborted, compressed, notOverwritten, deleted, renamed, IgnoredDueToZerobyteConstraint, setBack, polling
    }

    private ISOSVfsFileTransfer objDataSourceClient = null;
    private ISOSVfsFileTransfer objDataTargetClient = null;
    private ISOSVirtualFile objTargetTransferFile = null;
    private ISOSVirtualFile objSourceTransferFile = null;
    private SOSFileList objParent = null;
    private boolean flgFileExists = false;
    private String strMD5Hash = "n.a.";
    private Date dteStartTransfer = null;
    private Date dteEndTransfer = null;
    @SuppressWarnings("unused")
    private ISOSVfsFileTransfer objVfsHandler = null;
    // Hier bereits zuweisen, damit in der CSV-Datei und in der Order eine identische GUID verwendet wird.
    private final String guid = UUID.randomUUID().toString();
    private boolean flgSteadyFlag = false;
    private boolean flgTransferHistoryAlreadySent = false;

    public boolean flgIsHashFile = false;

    /**
     * \brief getobjDataSourceClient
     *
     * \details
     * getter
     *
     * @return the objDataSourceClient
     */
    public ISOSVfsFileTransfer getDataSourceClient() {
        return objDataSourceClient;
    }

    /**
     * \brief setobjDataSourceClient -
     *
     * \details
     * setter
     *
     * @param objDataSourceClient the value for objDataSourceClient to set
     */
    public void setDataSourceClient(final ISOSVfsFileTransfer pobjDataSourceClient) {
        objDataSourceClient = pobjDataSourceClient;
        lngFileModDate = -1;
        if (objDataSourceClient != null) {
            ISOSVirtualFile objFileHandle = objDataSourceClient.getFileHandle(strSourceFileName);
            if (objFileHandle != null) {
                lngFileModDate = objFileHandle.getModificationDateTime();
            } else {
            }
        }
    }

    /**
     * \brief getobjDataTargetClient
     *
     * \details
     * getter
     *
     * @return the objDataTargetClient
     */
    public ISOSVfsFileTransfer getDataTargetClient() {
        return objDataTargetClient;
    }

    /**
     * \brief setobjDataTargetClient -
     *
     * \details
     * setter
     *
     * @param pobjDataTargetClient1 the value for objDataTargetClient to set
     */
    public void setDataTargetClient(final ISOSVfsFileTransfer pobjDataTargetClient1) {
        objDataTargetClient = pobjDataTargetClient1;
    }

    public void VfsHandler(final ISOSVfsFileTransfer pobjVfs) {
        objVfsHandler = pobjVfs;
    }

    public SOSFileListEntry() {
        super(SOSVfsConstants.strBundleBaseName);
    }

    public void setParent(final SOSFileList objFileList) {
        objParent = objFileList;
        objDataSourceClient = objParent.objDataSourceClient;
        objDataTargetClient = objParent.objDataTargetClient;
        if (objDataSourceClient != null) {
            lngOriginalFileSize = objDataSourceClient.getFileHandle(strSourceFileName).getFileSize();
            lngFileSize = lngOriginalFileSize;
            lngFileModDate = objDataSourceClient.getFileHandle(strSourceFileName).getModificationDateTime();
        }
    }

    public String SourceTransferName() {
        return strSourceTransferName;
    }

    public String TargetTransferName() {
        return strTargetTransferName;
    }

    public String getZipFileName() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::getZipFileName";
        return strZipFileName;
    } // private String getZipFileName

    public enuTransferStatus getTransferStatus() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::getTransferStatus";
        return eTransferStatus;
    } // private enuTransferStatus getTransferStatus

    public void TransferStatus(final enuTransferStatus peTransferStatus) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::TransferStatus";
        this.setStatus(peTransferStatus);
    } // private void TransferStatus

    public void setTransferSkipped() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::setTransferSkipped";
        eTransferStatus = enuTransferStatus.transfer_skipped;
        String strM = SOSVfs_D_0110.params(strSourceFileName);
        logger.debug(strM);
        objJadeReportLogger.info(strM);
    } // private void TransferStatus

    public void setNotOverwritten() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::setNotOverwritten";
        eTransferStatus = enuTransferStatus.notOverwritten;
        logger.debug(SOSVfs_D_0111.params(strSourceFileName));
    } // private void TransferStatus

    public String TargetFileName() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::TargetFileName";
        return strTargetFileName;
    } // private String TargetFileName

    public void NoOfBytesTransferred(final long plngNoOfBytesTransferred) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::NoOfBytesTransferred";
        lngNoOfBytesTransferred = plngNoOfBytesTransferred;
        String strM = SOSVfs_D_0112.params(plngNoOfBytesTransferred);
        logger.info(strM);
    } // private void NoOfBytesTransferred

    public void setTransactionalRemoteFile() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::setTransactionalRemoteFile";
        flgTransactionalRemoteFile = true;
    } // private void setTransactionalRemoteFile

    public boolean getTransactionalLocalFile() {
        return flgTransactionalLocalFile;
    }

    public void setTransactionalLocalFile() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::setTransactionalRemoteFile";
        flgTransactionalLocalFile = true;
    } // private void setTransactionalRemoteFile

    public ISOSVirtualFile getTargetFile(final ISOSFtpOptions objO) {
        fleSourceTransferFile = null;
        fleSourceFile = objDataSourceClient.getFileHandle(strSourceFileName);
        fleTargetFile = null;
        // first assumption: localfilename and localTransferfileName are identical
        strSourceTransferName = fleSourceFile.getName();
        // second assumption: localfilename and TargetFileName are equal (until it changed)
        strTargetFileName = fleSourceFile.getName();
        boolean flgIncludeSubdirectories = objOptions.recursive.value();

        if (objO.getcompress_files().value() == true) { // compress file before sending
            strSourceTransferName = fleSourceFile.MakeZIPFile(objO.getcompressed_file_extension().Value());
            strTargetFileName = strTargetFileName + objO.getcompressed_file_extension().Value();
        }
        if (objOptions.CumulateFiles.isTrue()) {
            strTargetFileName = objOptions.CumulativeFileName.Value();
            strTargetTransferName = strTargetFileName;
            objOptions.append_files.value(true);
            //         if (objOptions.CumulativeFileDelete.isTrue()) {
            //         }
        } else {
            strTargetFileName = getFileNameWithoutPath(strTargetFileName);
            strTargetTransferName = strTargetFileName;
            // replacing has to be taken from general or target_ options for the target replacing  SOSFTP-151
            if (objO.getreplacing().IsNotEmpty()) {
                try {
                    strTargetFileName = objO.getreplacing().doReplace(strTargetFileName,
                            objO.getreplacement().Value());
                } catch (Exception e) {
                    String strM = SOSVfs_E_0150.get();
                    logger.error(e.getLocalizedMessage(), new JobSchedulerException(strM, e));
                }
            }
        }
        // Atomic-Suffix and/or atomic-prefix for cumulative_file was not used
        // http://www.sos-berlin.com/jira/browse/SOSFTP-142

        if (objOptions.isAtomicTransfer() || objOptions.TransactionMode.isTrue()) {
            setTransactionalRemoteFile();
            strTargetTransferName = MakeAtomicFileName(objOptions);
        }

        if (flgIncludeSubdirectories == true) {
            String strSourceDir = getPathWithoutFileName(fleSourceFile.getName());
            String strOrigSourceDir = objO.SourceDir().Value();
            if (strSourceDir.equals(strOrigSourceDir) == false) {
                if (strSourceDir.length() > strOrigSourceDir.length()) {
                    String strSubFolder = strSourceDir.substring(strOrigSourceDir.length());
                    strSubFolder = adjustFileSeparator(strSubFolder);
                    strTargetFileName = strSubFolder + strTargetFileName;
                    strTargetTransferName = strSubFolder + strTargetTransferName;

                    try {
                        if (objParent.add2SubFolders(strSubFolder) == true) {
                            objDataTargetClient.mkdir(addFileSeparator(objO.TargetDir().Value()) + strSubFolder);
                            logger.debug(String.format("create subdirectory '%1$s' in folder '%2$s'", strSubFolder,
                                    objO.TargetDir().Value()));
                        }
                    } catch (IOException e) {
                        throw new JobSchedulerException(e);
                    }
                }
            }
        }
        return null;
    }

    private String MakeFileNameReplacing(final String pstrFileName) {
        String strR = adjustFileSeparator(pstrFileName);
        String strReplaceWith = objOptions.getreplacement().Value();
        try {
            strR = objOptions.getreplacing().doReplace(strR, strReplaceWith);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage(), new JobSchedulerException(SOSVfs_E_0150.get(), e));
        }
        return strR;
    }

    private String getFileNameWithoutPath(final String pstrTargetFileName) {
        String strT = adjustFileSeparator(pstrTargetFileName);
        File fleT = new File(strT);
        strT = fleT.getName();
        return strT;
    }

    private String getPathWithoutFileName(final String pstrTargetFileName) {
        String strT = adjustFileSeparator(pstrTargetFileName);
        File fleT = new File(strT);
        strT = fleT.getParent();

        return addFileSeparator(adjustFileSeparator(strT));
    }

    protected String normalized(String str) {
        str = adjustFileSeparator(str);
        str = addFileSeparator(str);
        return str;
    }

    /**
     *
     * \brief MakeAtomicFileName
     *
     * \details
     * This Method creates an intermediate File-Name, which is used on the target as the first filename
     * After successfull completion of the whole transfer, this name will be renamed to the
     * final targetFileName.
     *
     * An intermediate filename is mostly used to avoid that a file-trigger on the target-host
     * will react to early on the transfer.
     *
     * \return the intermediate filename (without foldername) on the target-host
     *
     * @param ISOSFtpOptions.objO
     * @return intermediate TargetTransferFileName
     */
    public String MakeAtomicFileName(final ISOSFtpOptions objO) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::MakeAtomicFileName";

        String strAtomicSuffix = objO.getatomic_suffix().Value();
        String strAtomicPrefix = objO.getatomic_prefix().Value();
        strTargetTransferName = strTargetFileName + strAtomicSuffix.trim();
        strTargetTransferName = strAtomicPrefix + strTargetTransferName;
        strAtomicFileName = strTargetTransferName;

        return strTargetTransferName.trim();
    } // private String MakeAtomicFileName

    public void DeleteSourceFile() {
        // SOSFTP-152: allow source file deletion even if the filename is changed by (replace/replacing)
        String strFile2Delete = strSourceFileName;
        if (strRenamedSourceFileName != null) {
            strFile2Delete = strRenamedSourceFileName;
        }
        objDataSourceClient.getFileHandle(strFile2Delete).delete();
        String strM = SOSVfs_I_0113.params(strFile2Delete);
        logger.info(strM);
        objJadeReportLogger.info(strM);
    }

    public void setStatus(final enuTransferStatus peTransferStatus) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::setStatus";

        String strM = "";
        eTransferStatus = peTransferStatus;
        switch (peTransferStatus) {
        case transferInProgress:
            strM = SOSVfs_I_0114.get();
            break;
        case waiting4transfer:
            strM = SOSVfs_I_0115.get();
            // TODO Message senden
            break;
        case transfer_skipped:
            dteEndTransfer = Now();
            strM = SOSVfs_I_0116.get();
            // TODO Message senden
            break;
        case transferring:
            strM = SOSVfs_I_0117.get();
            dteStartTransfer = Now();
            // TODO Message senden
            break;
        case transferred:
            strM = SOSVfs_I_0118.get();
            dteEndTransfer = Now();
            // TODO Message senden
            break;
        case transfer_aborted:
            strM = SOSVfs_I_0119.get();
            dteEndTransfer = Now();
            // TODO Message senden
            break;
        default:
            break;
        }
        if (isNotEmpty(strM)) {
            // TODO send not only transferred - messages. make it customizable
            //         if (objOptions.SendTransferHistory.value() == true) {
            //            if (objOptions.transactional.value() == false && peTransferStatus == enuTransferStatus.transferred) {
            //               sendTransferHistory();
            //            }
            //         }
            switch (peTransferStatus) {
            case transferInProgress:
                // logger.debug(String.format("%1$s for file %2$s, actual %3$,d bytes", strM, strSourceFileName, lngTransferProgress));
                break;
            default:
                strM = SOSVfs_I_0120.params(strM, strSourceFileName);
                break;
            }
        }
    } // private void TransferStatus

    public void Log4Debug() {
        logger.debug(SOSVfs_D_218.params(this.SourceFileName()));
        logger.debug(SOSVfs_D_219.params(this.SourceTransferName()));
        logger.debug(SOSVfs_D_220.params(this.TargetTransferName()));
        logger.debug(SOSVfs_D_221.params(this.TargetFileName()));
    }

    public SOSFileListEntry(final String pstrLocalFileName) {
        this("", pstrLocalFileName, 0);
    }

    public SOSFileListEntry(final String pstrRemoteFileName, final String pstrLocalFileName,
            final long plngNoOfBytesTransferred) {
        super(SOSVfsConstants.strBundleBaseName);

        strTargetFileName = pstrRemoteFileName;
        strSourceFileName = pstrLocalFileName;
        lngNoOfBytesTransferred = plngNoOfBytesTransferred;
        // this.setStatus(enuTransfesrStatus.waiting4transfer);
    }

    @Override
    public String toString() {
        String strT = SOSVfs_D_214.params(this.getTargetFileNameAndPath(), this.SourceFileName(),
                this.NoOfBytesTransferred(), objOptions.operation.Value());
        return strT;
    }

    private String strCSVRec = new String();

    private void addCSv(final String... pstrVal) {
        for (String string : pstrVal) {
            if (strCSVRec.length() > 0) {
                strCSVRec += ";";
            }
            strCSVRec += string;
        }
    }

    //   private final 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";

    public String toCsv() {

        addCSv(guid, objOptions.mandator.Value(), SOSOptionTime.getCurrentTimeAsString());

        /**
         * this hack is tested for SUN-JVM only. No guarantee is made for other JVMs
         */
        String pid = ManagementFactory.getRuntimeMXBean().getName();
        String strA[] = pid.split("@");
        pid = strA[0];
        String ppid = System.getProperty("ppid", "0");

        addCSv(pid, ppid, objOptions.operation.Value());

        SOSConnection2OptionsAlternate objS = objOptions.getConnectionOptions().Source();

        addCSv(objS.host.Value(), objS.host.getHostAdress(), System.getProperty("user.name"));
        SOSConnection2OptionsAlternate objT = objOptions.getConnectionOptions().Target();

        addCSv(objT.host.Value(), objT.host.getHostAdress());

        String remote_user = "";
        if (objT.AlternateOptionsUsed.value() == true) {
            remote_user = "(alternative) " + objT.Alternatives().user.Value();
        } else {
            remote_user = objT.user.Value();
        }

        addCSv(remote_user, objT.protocol.Value(), objT.port.Value(), objOptions.local_dir.Value(),
                objOptions.TargetDir.Value(), strSourceFileName);
        String remote_filename = strTargetFileName;
        if (isEmpty(remote_filename)) {
            remote_filename = "n.a.";
        }

        addCSv(remote_filename, String.valueOf(lngFileSize), strMD5Hash, eTransferStatus.name());
        String last_error_message = "";
        // 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));
        addCSv(last_error_message, objOptions.log_filename.Value(), objOptions.jump_host.Value(),
                objOptions.jump_host.getHostAdress(), objOptions.jump_port.Value(),
                objOptions.jump_protocol.Value(), objOptions.jump_user.Value());

        SOSOptionTime objModTime = new SOSOptionTime(null, null, null, "", "", false);
        objModTime.value(lngFileModDate);
        addCSv(objModTime.getTimeAsString(lngFileModDate));
        return strCSVRec;
    }

    public String getTargetFileNameAndPath() {

        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::getTargetFileNameAndPath";

        String strT = objOptions.TargetDir.Value() + strTargetFileName;
        return strT;

        //   return String;
    } // private String getTargetFileNameAndPath

    @Deprecated
    // use getTargetfileNameAndPath
    public String RemoteFileName() {
        return strTargetFileName;
    }

    public void setRemoteFileName(final String pstrRemoteFileName) {
        strTargetFileName = pstrRemoteFileName;
    }

    public String SourceFileName() {
        return strSourceFileName;
    }

    public void setSourceFileName(final String pstrLocalFileName) {
        strSourceFileName = pstrLocalFileName;
    }

    public long NoOfBytesTransferred() {
        return lngNoOfBytesTransferred;
    }

    /**
     *
     * \brief setNoOfBytesTransferred
     *
     * \details
     * This Method must be called only at the end of the transfer.
     * Otherwise a call would result in a "FileSize"-Exception.
     *
     * \return void
     *
     * @param plngNoOfBytesTransferred
     */
    public void setNoOfBytesTransferred(final long plngNoOfBytesTransferred) {
        lngNoOfBytesTransferred = plngNoOfBytesTransferred;
        if (lngFileSize <= 0) { // if the file is compressed, then the original filesize may be to big
            lngFileSize = objDataSourceClient.getFileHandle(strSourceFileName).getFileSize();
            lngOriginalFileSize = lngFileSize;
        }
        if (lngFileSize != plngNoOfBytesTransferred) {
            logger.error(SOSVfs_E_216.params(plngNoOfBytesTransferred, lngFileSize, strSourceFileName));
            this.setStatus(enuTransferStatus.transfer_aborted);
            throw new JobSchedulerException(SOSVfs_E_271.get());
        }
        if (lngOriginalFileSize != plngNoOfBytesTransferred) {
            logger.error(SOSVfs_E_216.params(plngNoOfBytesTransferred, lngOriginalFileSize, strSourceFileName));
            this.setStatus(enuTransferStatus.transfer_aborted);
            throw new JobSchedulerException(SOSVfs_E_270.get());
        }
        this.setStatus(enuTransferStatus.transferred);
        // TODO Message "transferCompleted absetzen"
    }

    /**
     * \brief setlngTransferProgress -
     *
     * \details
     * setter
     *
     * @param lngTransferProgress the value for lngTransferProgress to set
     */
    public void setTransferProgress(final long plngTransferProgress) {
        lngTransferProgress = plngTransferProgress;
        this.setStatus(enuTransferStatus.transferInProgress);
        String lstrTargetFileName = strTargetFileName;
        if (objDataTargetClient.getHandler() instanceof SOSVfsZip) {
            lstrTargetFileName = SOSVfs_D_217.params(objOptions.remote_dir.Value(), strTargetFileName);
        }
        // logger.info(String.format("%1$,d bytes for file '%2$s' transferred to '%3$s'", lngTransferProgress, strSourceFileName,
        // lstrTargetFileName));
    }

    /**
     * \brief getlngTransferProgress
     *
     * \details
     * getter
     *
     * @return the lngTransferProgress
     */
    public long getTransferProgress() {
        return lngTransferProgress;
    }

    public void setStatusStartTransfer() {
        this.setStatus(enuTransferStatus.transferring);
    }

    public void setStatusEndTransfer(final long plngNoOfBytesTransferred) {
        this.setNoOfBytesTransferred(plngNoOfBytesTransferred);
        this.setStatusEndTransfer();
    }

    public void setStatusEndTransfer() {
        this.setStatus(enuTransferStatus.transferred);
    }

    public void Options(final SOSFTPOptions pobjOptions) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::Options";
        objOptions = pobjOptions;
    } // private void Options

    // TODO polling ber die File-Gre

    /**
     * Diese Routine prft *nur* auf dem lokalen fileSystem und ist aus der "Send"-Klasse kopiert.
     * hier hat sie nichts zu suchen, da das polling fr dateien in der Engine erfolgen muss,
     * unabhngig davon, wo die Dateien liegen. Es mu *immer* die Datasource gepollt werden.
     *
     * Auf alle Flle mu hier ber das Vfs auf die Datei(en) zugegriffen werden.
     */
    public boolean CheckFileSizeIsChanging() throws Exception {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::polling";
        String lastmd5file = "";
        String message = "";

        try {
            // TODO eigentlich ist das hier "check_steady_state"
            String fileName = strSourceFileName;
            //         if (objOptions.poll_timeout.value() > 0 && isNotEmpty(fileName)) {
            //            setStatus(enuTransferStatus.polling);
            //            double delay = objOptions.poll_interval.value();
            //            double nrOfTries = (objOptions.poll_timeout.value() * 60) / delay;
            //            int tries = 0;
            //            boolean found = true;
            //            logger.info(SOSVfs_I_222.params(fileName));
            //            // TODO in die Implementation des ISOSVirtualFile verschieben
            //            File fleFile = new File(fileName);
            //            // TODO ber Option auf FileSize ausweichen, da MD5 bei groen dateien eine ziemliche Last erzeugt
            //            lastmd5file = sos.util.SOSCrypt.MD5encrypt(fleFile);
            //            Thread.sleep((long) delay * 1000);
            //            for (int i = 0; i < nrOfTries; i++) {
            //               tries++;
            //               String newMD5File = sos.util.SOSCrypt.MD5encrypt(fleFile);
            //               logger.debug(SOSVfs_D_223.params(i, newMD5File));
            //               if (!lastmd5file.equals(newMD5File)) {
            //                  lastmd5file = newMD5File;
            //                  logger.info(SOSVfs_I_222.params(fileName));
            //                  Thread.sleep((long) delay * 1000);
            //                  if (i + 1 == nrOfTries) {
            //                     found = false;
            //                     message = message + " " + fileName;
            //                  }
            //               }
            //               else {
            //                  break;
            //               }
            //            }
            //            if (found == false) {
            //               message = SOSVfs_E_224.params(objOptions.poll_timeout.value(), message);
            //               if (objOptions.force_files.value() == true) {
            //                  logger.error(message);
            //                  throw new JobSchedulerException(message);
            //               }
            //               else {
            //                  logger.info(message);
            //                  return false;
            //               }
            //            }
            //         }
            return true;
        } catch (Exception e) {
            throw new JobSchedulerException(SOSVfs_E_225.params(conMethodName, e));
        }
    }

    // Runnable
    @Override
    public void run() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::run";
        boolean flgNewConnectionUsed = false;
        try {
            //         logger.debug(SOSVfs_D_272.get());
            ISOSVFSHandler objVFS4Source = null;
            ISOSVFSHandler objVFS4Target = null;
            if (objDataSourceClient == null) {
                flgNewConnectionUsed = true;
                objVFS4Source = VFSFactory.getHandler(objOptions.getDataSourceType());
                objVFS4Source.setSource();
                objVFS4Source.Connect(objOptions.getConnectionOptions().Source());
                objVFS4Source.Authenticate(objOptions);
                objDataSourceClient = (ISOSVfsFileTransfer) objVFS4Source;
                objVFS4Source.setSource();
                objVFS4Source.Options(objOptions);
            }
            if (objDataTargetClient == null & objOptions.NeedTargetClient() == true) {
                flgNewConnectionUsed = true;
                objVFS4Target = VFSFactory.getHandler(objOptions.getDataTargetType());
                objVFS4Target.setTarget();
                objVFS4Target.Connect(objOptions.getConnectionOptions().Target());
                objVFS4Target.Authenticate(objOptions);
                objDataTargetClient = (ISOSVfsFileTransfer) objVFS4Target;
                objVFS4Target.setTarget();
                objVFS4Target.Options(objOptions);
            }

            ISOSVirtualFile objSourceFile = objDataSourceClient.getFileHandle(strSourceFileName);
            if (objSourceFile.notExists() == true) {
                throw new JobSchedulerException(SOSVfs_E_226.params(strSourceFileName));
            }
            /**
             * hier nicht verwenden, weil es zu spt kommt.
             */
            // if (CheckFileSizeIsChanging() == false) {
            // // TODO Exception auslsen
            // return;
            // }

            //         // improve zeroByteFile handling in transactional mode
            //         if (objOptions.TransferZeroByteFiles() == false && objSourceFile.isEmptyFile()) {
            //            this.TransferStatus(enuTransferStatus.transfer_skipped);
            //            return;
            //         }
            //
            File subParent = null;
            String subPath = "";
            String strTargetFolderName = objOptions.TargetDir.Value();
            String localDir = objOptions.SourceDir.Value();
            boolean flgIncludeSubdirectories = objOptions.recursive.value();
            if (flgIncludeSubdirectories == true) {
                // TODO Das Erstellen des Verzeichnis mu eine separate Methode werden
                // berprfen, ob das Verzeichnis auf den Target (-Server) existiert, wenn nicht dann soll das gleiche Verzeichnis generiert
                // werden
                if (objSourceFile.getParentVfs() != null && objSourceFile.getParentVfsFile().isDirectory()) {
                    subPath = strSourceFileName.substring(localDir.length()); // Unterverzeichnisse sind alle Verzeichnisse unterhalb
                    // der localDir
                    subParent = new File(subPath).getParentFile();
                    if (subParent != null) {
                        subPath = adjustFileSeparator(subPath);
                        subPath = subPath.substring(0,
                                subPath.length() - new File(strSourceFileName.toString()).getName().length() - 1);
                        // logger.debug(SOSVfs_D_227.params(subPath));
                        // TODO nur feststellen, ob es den schon gibt. Neue Methode einfhren, evtl. FileExists/Folderexists
                        // String[] ftpFiles = objDataTargetClient.listNames(strTargetFolderName + "/" + subPath);
                        // if (ftpFiles == null || ftpFiles.length == 0) {

                        // File.separator fhrte zu Unterverzeichnissen mit fhrendem Backslash
                        //objDataTargetClient.mkdir(strTargetFolderName + File.separator + subPath);
                        objDataTargetClient.mkdir(strTargetFolderName + "/" + subPath);
                        // }
                    } else {
                        subPath = "";
                    }
                }
            }

            this.getTargetFile(objOptions); // TODO Namen ndern

            if (objOptions.transactional.value() == true) {
                this.setTransactionalLocalFile();
            }

            switch (objOptions.operation.value()) {
            case delete:
                // TODO operation delete is not transactional
                objSourceFile.delete();
                logger.debug(SOSVfs_I_0113.params(strSourceFileName));
                this.setStatus(enuTransferStatus.deleted);
                return;

            case rename:
                // TODO operation rename is not transactional
                File fleT = new File(strSourceFileName);
                String strParent = changeBackslashes(normalized(fleT.getParent()));
                String strNewFileName = MakeFileNameReplacing(fleT.getName());
                strNewFileName = changeBackslashes(addFileSeparator(strParent) + strNewFileName);
                logger.debug(SOSVfs_I_150.params(strSourceFileName, strNewFileName));
                strTargetFileName = strNewFileName;
                objSourceFile.rename(strNewFileName);
                this.setStatus(enuTransferStatus.renamed);
                return;

            default:
                break;
            }

            ISOSVirtualFile objTargetFile = objDataTargetClient
                    .getFileHandle(MakeFullPathName(objOptions.TargetDir.Value(), strTargetFileName));
            if (objOptions.CumulateFiles.isTrue()) {
                if (objOptions.CumulativeFileDelete.isTrue() && objOptions.flgCumulativeTargetDeleted == false) {
                    objTargetFile.delete();
                    objOptions.flgCumulativeTargetDeleted = true;
                    logger.debug(String.format("cumulative file '%1$s' deleted.", strTargetFileName));
                }
            }

            objTargetFile.setModeAppend(objOptions.append_files.value());
            objTargetFile.setModeRestart(objOptions.ResumeTransfer.value());
            if (strTargetFileName.equalsIgnoreCase(strTargetTransferName) == false) {
                objTargetTransferFile = objDataTargetClient
                        .getFileHandle(MakeFullPathName(objOptions.TargetDir.Value(), strTargetTransferName));
            } else {
                objTargetTransferFile = objTargetFile;
            }

            if (objOptions.CumulateFiles.isTrue()) {
                objTargetTransferFile.setModeAppend(objOptions.append_files.value());
                objTargetTransferFile.setModeRestart(objOptions.ResumeTransfer.value());
            }

            if (objOptions.compress_files.value() == true) {
                objSourceTransferFile = objDataSourceClient.getFileHandle(strSourceTransferName);
                lngFileSize = objSourceTransferFile.getFileSize();
                lngOriginalFileSize = lngFileSize;
            } else {
                strSourceTransferName = getFileNameWithoutPath(strSourceTransferName);
                String strT = "";
                objSourceTransferFile = objDataSourceClient.getFileHandle(
                        MakeFullPathName(getPathWithoutFileName(strSourceFileName) + strT, strSourceTransferName));
            }

            if (objOptions.DoNotOverwrite() == true) { // kb 2012-06-29: check setting first, then file - existence
                flgFileExists = objTargetFile.FileExists();
                if (flgFileExists == true) {
                    logger.debug(SOSVfs_E_228.params(strTargetFileName));
                    this.setNotOverwritten();
                    return;
                }
            }

            this.doTransfer(objSourceTransferFile, objTargetTransferFile);

            if (objOptions.KeepModificationDate.isTrue()) {
                long pdteDateTime = objSourceFile.getModificationDateTime();
                if (pdteDateTime != -1) {
                    objTargetFile.setModificationDateTime(pdteDateTime);
                }
            }

            if (objOptions.isAtomicTransfer() || objOptions.isReplaceReplacingInEffect()) {
                if (objOptions.transactional.value() == false) {
                    flgFileExists = objTargetFile.FileExists();
                    if (objOptions.overwrite_files.value() == true & flgFileExists == true) {
                        // hier werden Dateien gelscht, vor dem umbenennen.
                        // TODO Besser: auch erstmal umbenennen und dann erst lschen
                        objTargetFile.delete();
                    }
                    RenameTargetFile(MakeFullPathName(objOptions.TargetDir.Value(), this.TargetFileName()));
                }
            }

            RenameSourceFile(objSourceFile);

            if (flgNewConnectionUsed == true) {
                objDataSourceClient.logout();
                objDataSourceClient.disconnect();
                objDataTargetClient.logout();
                objDataTargetClient.disconnect();
            }
        } catch (Exception e) {
            String strT = SOSVfs_E_229.params(e);
            // TODO rollback?
            logger.error(strT);
            throw new JobSchedulerException(strT, e);
        }
    }

    private String strRenamedSourceFileName = null;

    private void RenameSourceFile(final ISOSVirtualFile pobjSourceFile) {
        SOSConnection2OptionsAlternate objSO = objOptions.Source();
        if (objSO.ReplaceWhat.isDirty()) {
            String strReplaceWith = objSO.getreplacement().Value();
            try {
                File fleT = new File(strSourceFileName);
                String strParent = changeBackslashes(normalized(fleT.getParent()));
                String strSourceFileName1 = fleT.getName();
                strSourceFileName1 = changeBackslashes(strSourceFileName1); // Problems on windows: the path separator disapers
                String strNewSourceFileName = objSO.ReplaceWhat.doReplace(strSourceFileName1, strReplaceWith);
                if (strReplaceWith.startsWith("/") == false) {
                    strNewSourceFileName = changeBackslashes(addFileSeparator(strParent) + strNewSourceFileName);
                }
                pobjSourceFile.rename(strNewSourceFileName);
                strRenamedSourceFileName = strNewSourceFileName;
            } catch (Exception e) {
                logger.error(e.getLocalizedMessage(), new JobSchedulerException(SOSVfs_E_0150.get(), e));
            }
        }
    }

    private String changeBackslashes(final String pstrV) {
        return pstrV.replaceAll("\\\\", "/");
    }

    private void RenameTargetFile(final String pstrTargetFileName) {
        if (pstrTargetFileName.equals(objTargetTransferFile.getName()) == false) {
            objTargetTransferFile.rename(pstrTargetFileName);
        }
    }

    private void RaiseException(final String pstrM) {
        this.TransferStatus(enuTransferStatus.transfer_aborted);
        logger.error(pstrM);
        throw new JobSchedulerException(pstrM);
    }

    private long doTransfer(final ISOSVirtualFile objInput, final ISOSVirtualFile objOutput) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::doTransfer";
        boolean flgClosingDone = false;
        if (objOutput == null) {
            RaiseException(SOSVfs_E_273.params("Target"));
        }
        if (objInput == null) {
            RaiseException(SOSVfs_E_273.params("Source"));
        }
        boolean flgCreateSecurityHash = objOptions.CreateSecurityHash.value() && flgIsHashFile == false;
        MessageDigest md = null;
        if (flgCreateSecurityHash) {
            try {
                // TODO implement in value-method of securityhashtype
                md = MessageDigest.getInstance(objOptions.SecurityHashType.Value());
            } catch (NoSuchAlgorithmException e1) {
                e1.printStackTrace();
                flgCreateSecurityHash = false;
            }
        }

        executePreCommands();

        long lngTotalBytesTransferred = 0;
        Base64 objBase64 = null;
        this.setStatus(enuTransferStatus.transferring);
        try {
            int intCumulativeFileSeperatorLength = 0;
            int lngBufferSize = objOptions.BufferSize.value();
            byte[] buffer = new byte[lngBufferSize];
            int intBytesTransferred;
            int intOffset = 0;
            boolean flgBase64EncodingOnOutput = false;
            boolean flgBase64EncodingOnInput = false;
            if (flgBase64EncodingOnOutput) {
                objBase64 = new Base64();
            }
            synchronized (this) {
                if (objOptions.CumulateFiles.isTrue() && objOptions.CumulativeFileSeparator.IsNotEmpty()) {
                    String strFS = objOptions.CumulativeFileSeparator.Value();
                    strFS = this.replaceVariables(strFS) + System.getProperty("line.separator");
                    byte[] bteB = strFS.getBytes();
                    intCumulativeFileSeperatorLength = bteB.length;
                    objOutput.write(bteB);
                }
                if (objInput.getFileSize() <= 0) {
                    objOutput.write(buffer, 0, 0);
                } else {
                    while ((intBytesTransferred = objInput.read(buffer)) != -1) {
                        try {
                            int intBytes2Write = intBytesTransferred;
                            if (flgBase64EncodingOnOutput) {
                                byte[] bteIn = new byte[intBytesTransferred];
                                byte[] bteOut = objBase64.encode(bteIn);
                                intBytes2Write = bteOut.length;
                                buffer = bteOut;
                            }

                            objOutput.write(buffer, 0, intBytes2Write);
                        } catch (JobSchedulerException e) {
                            e.printStackTrace(System.err);
                            break;
                        }
                        // TODO in case of wrong outputbuffer the handling of the error must be improved
                        lngTotalBytesTransferred += intBytesTransferred;
                        // intOffset += lngTotalBytesTransferred;
                        setTransferProgress(lngTotalBytesTransferred);
                        if (flgCreateSecurityHash) {
                            md.update(buffer, 0, intBytesTransferred);
                        }
                    }
                }
            }
            objInput.closeInput();
            objOutput.closeOutput();
            flgClosingDone = true;
            if (flgCreateSecurityHash) {
                strMD5Hash = toHexString(md.digest());
                logger.info(SOSVfs_I_274.params(strMD5Hash, strSourceTransferName,
                        objOptions.SecurityHashType.Value()));
                if (objOptions.CreateSecurityHashFile.isTrue()) {
                    JSTextFile objF = new JSTextFile(strSourceFileName + "." + objOptions.SecurityHashType.Value());
                    objF.WriteLine(strMD5Hash);
                    objF.close();
                    objF.deleteOnExit();
                }
            }
            // objDataTargetClient.CompletePendingCommand();
            if (objDataTargetClient.isNegativeCommandCompletion()) {
                RaiseException(
                        SOSVfs_E_175.params(objTargetTransferFile.getName(), objDataTargetClient.getReplyString()));
            }

            this.setNoOfBytesTransferred(lngTotalBytesTransferred);
            lngTotalBytesTransferred += intCumulativeFileSeperatorLength;

            executePostCommands();
            return lngTotalBytesTransferred;
        } catch (Exception e) {
            RaiseException(e, SOSVfs_E_266.get());
        } finally {
            if (flgClosingDone == false) {
                objInput.closeInput();
                objOutput.closeOutput();
                flgClosingDone = true;
            }
        }
        return lngTotalBytesTransferred;
    } // putFile

    private void RaiseException(final Exception e, final String pstrM) {
        logger.error(pstrM);
        e.printStackTrace(System.err);
        throw new JobSchedulerException(pstrM, e);
    }

    private void executePostCommands() {

        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::executePostCommands";

        executeCommands(objDataTargetClient, objOptions.Post_Command);
        executeCommands(objDataSourceClient, objOptions.getConnectionOptions().Source().Post_Command);
        executeCommands(objDataTargetClient, objOptions.getConnectionOptions().Target().Post_Command);

    } // private void executePostCommands

    private void executePreCommands() {

        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::executePreCommands";

        executeCommands(objDataTargetClient, objOptions.Pre_Command);
        executeCommands(objDataSourceClient, objOptions.getConnectionOptions().Source().Pre_Command);
        executeCommands(objDataTargetClient, objOptions.getConnectionOptions().Target().Pre_Command);

    } // private void executePreCommands

    public String getAtomicFileName() {
        return strAtomicFileName;
    }

    public void setAtomicFileName(final String pstrValue) {
        strAtomicFileName = pstrValue;
    }

    public boolean FileExists() {
        ISOSVirtualFile objTargetFile = objDataTargetClient
                .getFileHandle(MakeFullPathName(objOptions.TargetDir.Value(), strTargetFileName));
        try {
            flgFileExists = objTargetFile.FileExists();
        } catch (Exception e) {
            flgFileExists = false;
        }
        return flgFileExists;
    }

    /**
     *
        *
        * \brief SourceFileExists
        *
        * \details
        * Check, wether a source file exists.
        *
        * \return boolean
        *
     */
    public boolean SourceFileExists() {
        boolean flgT = false;
        try {
            flgT = objDataSourceClient.getFileHandle(strSourceFileName).FileExists();
        } catch (Exception e) {
        }

        return flgT;
    }

    private String toHexString(final byte[] b) {
        char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        int length = b.length * 2;
        StringBuffer sb = new StringBuffer(length);
        for (byte element : b) {
            // oberer Byteanteil
            sb.append(hexChar[(element & 0xf0) >>> 4]);
            // unterer Byteanteil
            sb.append(hexChar[element & 0x0f]);
        }
        return sb.toString();
    }

    /**
     *
     * \brief sendTransferHistory
     *
     * \details
     * This methods sends for each file the needed informations about the transfer history
     * to the background service (JobScheduler).
     *
     * \return void
     *
     */
    public boolean sendTransferHistory() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::sendTransferHistory";
        boolean flgRet = false;

        if (flgTransferHistoryAlreadySent == true) {
            return flgRet;
        }
        flgTransferHistoryAlreadySent = true;

        if (objOptions.SendTransferHistory.isFalse()) {
            if (flgNoDataSent == false) {
                flgNoDataSent = true;
            }
            return flgRet;
        }

        String strBackgroundServiceHostName = objOptions.scheduler_host.Value();
        if (isEmpty(strBackgroundServiceHostName)) {
            if (flgNoDataSent == false) {
                flgNoDataSent = true;
                logger.debug(Messages.getMsg("No data sent to the background service due to missing host name"));
            }
            return flgRet;
        }

        String mandator = objOptions.mandator.Value(); // 0-
        String transfer_timestamp = EMPTY_STRING;
        try {
            transfer_timestamp = sos.util.SOSDate.getCurrentTimeAsString();
        } catch (Exception e) {
        } // 1- timestamp: Zeitstempel im ISO-Format
        /**
         * this hack is tested for SUN-JVM only. No guarantee is made for other JVMs
         */
        // TODO create a getPID method in shell class
        String pid = ManagementFactory.getRuntimeMXBean().getName();
        String strA[] = pid.split("@");
        pid = strA[0];
        String ppid = System.getProperty("ppid", "0");
        String operation = objOptions.operation.Value(); // 4- operation: send|receive
        SOSConnection2OptionsAlternate objS = objOptions.getConnectionOptions().Source();
        String localhost = objS.host.Value(); // 5- local host
        String localhost_ip = objS.host.getHostAdress(); // 5-1- local host IP adresse
        String local_user = System.getProperty("user.name"); // 6- local user
        SOSConnection2OptionsAlternate objT = objOptions.getConnectionOptions().Target();
        String remote_host = objT.host.Value(); // 7- remote host
        String remote_host_ip = objT.host.getHostAdress(); // 7- remote host IP

        String remote_user = "";
        if (objT.AlternateOptionsUsed.value() == true) {
            remote_user = "(alternative) " + objT.Alternatives().user.Value(); // 8- remote host user
        } else {
            remote_user = objT.user.Value(); // 8- remote host user
        }
        String protocol = objT.protocol.Value(); // 9- protocol
        String port = objT.port.Value(); // 10- port
        String local_dir = objOptions.local_dir.Value();
        // String remote_dir = new File(this.strTargetFileName).getAbsolutePath();
        String remote_dir = objOptions.TargetDir.Value();
        String local_filename = strSourceFileName; // 13- file name
        String remote_filename = strTargetFileName; // 14- name
        if (isEmpty(remote_filename)) {
            remote_filename = "n.a.";
        }
        String fileSize = String.valueOf(lngFileSize);
        String md5 = strMD5Hash;
        String last_error_message = "";
        // 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));
        String log_filename = objOptions.log_filename.Value();
        String jump_host = objOptions.jump_host.Value();
        String jump_host_ip = objOptions.jump_host.getHostAdress();
        String jump_port = objOptions.jump_port.Value();
        String jump_protocol = objOptions.jump_protocol.Value();
        String jump_user = objOptions.jump_user.Value();

        Properties objSchedulerOrderParameterSet = new Properties();
        objSchedulerOrderParameterSet.put("guid", 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 fr Windows
        objSchedulerOrderParameterSet.put("ppid", ppid); // 5- ppid= Environment PPID | 0 fr 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

        String status = eTransferStatus.name();
        if (status.equalsIgnoreCase("transferred")) {
            status = "success";
        }
        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
        // TODO custom-fields einbauen
        /**
         * bei SOSFTP ist es mglich "custom" Felder zu definieren, die in der Transfer History als Auftragsparameter mitgeschickt werden.
         * Damit man diese Felder identifizieren kann, werden hier Parameter defininiert, die beim Auftrag dabei sind, aber keine
         * "custom" Felder sind
         *
         * ? alternativ Metadaten der Tabelle lesen (Spalten) und mit den Auftragsparameter vergleichen
         */

        SchedulerObjectFactory objFactory = objParent.objFactory;
        if (objFactory == null) {
            objFactory = new SchedulerObjectFactory(objOptions.scheduler_host.Value(),
                    objOptions.scheduler_port.value());
            objFactory.initMarshaller(Spooler.class);
            objParent.objFactory = objFactory;
            objFactory.Options().TransferMethod.Value(objOptions.Scheduler_Transfer_Method.Value());
            objFactory.Options().PortNumber.Value(objOptions.scheduler_port.Value());
            objFactory.Options().ServerName.Value(objOptions.scheduler_host.Value());
        }
        JSCmdAddOrder objOrder = objFactory.createAddOrder();
        objOrder.setJobChain(objOptions.scheduler_job_chain.Value() /* "scheduler_sosftp_history" */);
        objOrder.setTitle(SOSVfs_Title_276.get());
        Params objParams = objFactory.setParams(objSchedulerOrderParameterSet);
        objOrder.setParams(objParams);
        //      logger.debug(objOrder.toXMLString());
        objOrder.run();

        flgRet = true;
        return flgRet;
    } // private void sendTransferHistory

    private void executeCommands(final ISOSVfsFileTransfer pobjDataClient,
            final SOSOptionString pstrCommandString) {

        final String conMethodName = conClassName + "::executeCommands";

        if (pstrCommandString.IsNotEmpty()) {
            String strT = pstrCommandString.Value();
            strT = replaceVariables(strT);
            String strM = SOSVfs_D_0151.params(strT);
            logger.debug(strM);
            String[] strA = strT.split(";");
            for (String strCmd : strA) {
                try {
                    pobjDataClient.getHandler().ExecuteCommand(strCmd);
                } catch (Exception e) {
                    e.printStackTrace(System.err);
                    throw new JobSchedulerException(conMethodName, e);
                }
            }
        }
    } // private void executeCommands

    private String replaceVariables(final String pstrReplaceIn) {

        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::replaceVariables";

        String strT = pstrReplaceIn;
        strT = strT.replace("$TargetFileName", MakeFullPathName(objOptions.TargetDir.Value(), strTargetFileName));
        strT = strT.replace("$TargetTransferFileName",
                MakeFullPathName(objOptions.TargetDir.Value(), strTargetTransferName));
        strT = strT.replace("$SourceFileName", MakeFullPathName(objOptions.SourceDir.Value(), strSourceFileName));
        strT = strT.replace("$SourceTransferFileName",
                MakeFullPathName(objOptions.SourceDir.Value(), strSourceTransferName));

        Properties objProp = objOptions.getTextProperties();

        objProp.put("TargetFileName", strTargetFileName);
        objProp.put("TargetTransferFileName", strTargetTransferName);
        objProp.put("SourceFileName", strSourceFileName);
        objProp.put("SourceTransferFileName", strSourceTransferName);

        strT = objOptions.replaceVars(strT);

        // TODO other patterns, like [date:] or others should replaced as well
        return strT;
    } // private String replaceVariables

    @Override
    public Integer getTransferDetailsId() {
        return null;
    }

    @Override
    public Integer getTransferId() {
        return null;
    }

    @Override
    public Long getFileSize() {
        return lngFileSize;
    }

    @Override
    public Integer getCommandType() {
        return 0;
    }

    @Override
    public String getCommand() {
        return EMPTY_STRING;
    }

    @Override
    public String getPid() {
        return objOptions.getPid();
    }

    @Override
    public String getLastErrorMessage() {
        return EMPTY_STRING;
    }

    @Override
    public String getTargetFilename() {
        return strTargetFileName;
    }

    @Override
    public String getSourceFilename() {
        return strSourceFileName;
    }

    @Override
    public String getMd5() {
        return strMD5Hash;
    }

    @Override
    public Integer getStatus() {
        return new Integer(eTransferStatus.ordinal());
    }

    @Override
    public Date getStartTime() {
        return dteStartTransfer;
    }

    @Override
    public Date getEndTime() {
        return dteEndTransfer;
    }

    @Override
    public String getModifiedBy() {
        return EMPTY_STRING;
    }

    @Override
    public String getCreatedBy() {
        return EMPTY_STRING;
    }

    @Override
    public Date getCreated() {
        return null;
    }

    @Override
    public Date getModified() {
        return null;
    }

    @Override
    public String getStatusText() {
        return eTransferStatus.name();
    }

    @Override
    public String getSizeValue() {
        return "";
    }

    public void setSteady(final boolean pflgSteadyFlag) {
        flgSteadyFlag = pflgSteadyFlag;

    }

    public boolean isSteady() {

        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::isSteady";

        return flgSteadyFlag;

    } // private boolean isSteady

    public String SecurityHash() {
        return strMD5Hash;
    }
}