com.sos.VirtualFileSystem.FTP.SOSVfsFtpBaseClass.java Source code

Java tutorial

Introduction

Here is the source code for com.sos.VirtualFileSystem.FTP.SOSVfsFtpBaseClass.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.FTP;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.sos.JSHelper.Basics.JSJobUtilities;
import com.sos.JSHelper.Exceptions.JobSchedulerException;
import com.sos.JSHelper.Options.SOSOptionHostName;
import com.sos.JSHelper.Options.SOSOptionPortNumber;
import com.sos.JSHelper.Options.SOSOptionTransferMode;
import com.sos.VirtualFileSystem.DataElements.SOSFileList;
import com.sos.VirtualFileSystem.DataElements.SOSFileListEntry;
import com.sos.VirtualFileSystem.DataElements.SOSFolderName;
import com.sos.VirtualFileSystem.Interfaces.ISOSAuthenticationOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSConnection;
import com.sos.VirtualFileSystem.Interfaces.ISOSConnectionOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSSession;
import com.sos.VirtualFileSystem.Interfaces.ISOSShellOptions;
import com.sos.VirtualFileSystem.Interfaces.ISOSVFSHandler;
import com.sos.VirtualFileSystem.Interfaces.ISOSVfsFileTransfer;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFile;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFileSystem;
import com.sos.VirtualFileSystem.Interfaces.ISOSVirtualFolder;
import com.sos.VirtualFileSystem.Options.SOSConnection2OptionsAlternate;
import com.sos.VirtualFileSystem.Options.SOSConnection2OptionsSuperClass;
import com.sos.VirtualFileSystem.common.SOSVfsBaseClass;
import com.sos.i18n.annotation.I18NResourceBundle;

/**
* \class SOSVfsFtpBaseClass
*
* \brief SOSVfsFtpBaseClass -
*
* \details
*
* \section SOSVfsFtpBaseClass.java_intro_sec Introduction
*
* \section SOSVfsFtpBaseClass.java_samples Some Samples
*
* \code
*   .... code goes here ...
* \endcode
*
* <p style="text-align:center">
* <br />---------------------------------------------------------------------------
* <br /> APL/Software GmbH - Berlin
* <br />##### generated by ClaviusXPress (http://www.sos-berlin.com) #########
* <br />---------------------------------------------------------------------------
* </p>
* \author KB
* \version $Id: SOSVfsFtpBaseClass.java 20723 2013-07-18 18:19:56Z kb $ 21.04.2011
* \see reference
*
* Created on 21.04.2011 19:31:35
 */
/**
 * @author KB
 *
 */
@I18NResourceBundle(baseName = "SOSVirtualFileSystem", defaultLocale = "en")
public class SOSVfsFtpBaseClass extends SOSVfsBaseClass
        implements ISOSVfsFileTransfer, ISOSVFSHandler, ISOSVirtualFileSystem, ISOSConnection {
    private final String conClassName = "SOSVfsFtpBaseClass";
    private final Logger logger = Logger.getLogger(SOSVfsFtpBaseClass.class);
    @Deprecated
    protected Vector<String> vecDirectoryListing = null;
    protected ISOSConnectionOptions objConnectionOptions = null;
    protected SOSConnection2OptionsAlternate objConnection2Options = null;
    protected String strCurrentPath = EMPTY_STRING;
    protected String strReply = EMPTY_STRING;
    protected SOSFtpClientLogger objProtocolCommandListener = null;
    protected String host = EMPTY_STRING;
    protected int port = 0;
    protected String gstrUser = EMPTY_STRING;
    protected SOSOptionHostName objHost = null;
    protected SOSOptionPortNumber objPort = null;

    protected boolean utf8Supported = false;
    protected boolean restSupported = false;
    protected boolean mlsdSupported = false;
    protected boolean modezSupported = false;
    protected boolean dataChannelEncrypted = false;

    protected SOSFtpServerReply objFTPReply = null;

    public SOSVfsFtpBaseClass() {
        super();
        //
    }

    protected final String HostID(final String pstrText) {
        return "(" + gstrUser + "@" + host + ":" + port + ") " + pstrText;
    }

    /**
     * Creates a new subdirectory on the FTP server in the current directory .
     * @param pathname The pathname of the directory to create.
     * @return True if successfully completed, false if not.
     * @throws java.lang.IOException
     */
    @Override
    public final void mkdir(final String pstrPathName) {
        final String conMethodName = conClassName + "::mkdir";

        try {
            String strPath = "";
            if (pstrPathName.startsWith("/")) {
                strPath = "/";
            }
            String[] strP = pstrPathName.split("/");
            for (String strSubFolder : strP) {
                if (strSubFolder.trim().length() > 0) {
                    strPath += strSubFolder + "/";
                    Client().makeDirectory(strPath);
                    logger.debug(HostID(SOSVfs_E_0106.params(conMethodName, strPath, getReplyString())));
                    // logger.debug(HostID("..ftp server reply [mkdir] [" + strPath + "]: " + getReplyString()));
                }
            }
            // logger.debug(HostID("..ftp server reply [mkdir] [" + pstrPathName + "]: " + getReplyString()));
        } catch (IOException e) {
            String strM = HostID(SOSVfs_E_0105.params(conMethodName));
            e.printStackTrace(System.err);
            throw new RuntimeException(strM, e);

            // throw new JobSchedulerException(HostID("makeDirectory returns an exception"), e);
        }
    }

    /**
     * Removes a directory on the FTP server (if empty).
     * @param pathname The pathname of the directory to remove.
     * @throws java.lang.IOException
     */
    @Override
    public final void rmdir(final String pstrPathName) throws IOException {
        final String conMethodName = conClassName + "::rmdir";

        try {
            String[] strP = pstrPathName.split("/");
            for (int i = strP.length; i > 0; i--) {
                String strT = "";
                for (int j = 0; j < i; j++) {
                    strT += strP[j] + "/";
                }
                logger.debug(HostID(SOSVfs_E_0106.params(conMethodName, pstrPathName, getReplyString())));

                // logger.debug(HostID("..ftp server reply [rmdir] [" + strT + "]: " + getReplyString()));
                Client().removeDirectory(strT);
            }
        } catch (Exception e) {
            String strM = HostID(SOSVfs_E_0105.params(conMethodName));
            throw new JobSchedulerException(strM, e);
        }
    }

    protected FTPClient Client() {
        return null;
    }

    @Override
    public final ISOSConnection Connect() {
        final String conMethodName = conClassName + "::Connect";

        String strH = host = objConnectionOptions.getHost().Value();
        int intP = port = objConnectionOptions.getPort().value();

        logger.debug(SOSVfs_D_0101.params(strH, intP));
        try {
            this.connect(strH, intP);
            logger.debug(SOSVfs_D_0102.params(strH, intP));
        } catch (RuntimeException e) {
            logger.info(SOSVfs_E_0107.params(host, port) + e.getMessage());
            String strAltHost = host = objConnectionOptions.getalternative_host().Value();
            int intAltPort = port = objConnectionOptions.getalternative_port().value();

            if (isNotEmpty(strAltHost) && intAltPort > 0) {
                logger.debug(SOSVfs_D_0101.params(strAltHost, intAltPort));
                this.connect(strAltHost, intAltPort);
                logger.debug(SOSVfs_D_0102.params(strAltHost, intAltPort));
            } else {
                logger.info(SOSVfs_E_0107.params(host, port, e.getMessage()));
                RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
            }
        }
        return this;
    }

    // @Override
    // public final ISOSConnection Connect() {
    // logger.debug("Try to connect ...");
    // try {
    // connect(objConnectionOptions.getHost().Value(), objConnectionOptions.getPort().value());
    // logger.info(String.format("successful connected to Host '%1$s' at port '%1$d'.", objConnectionOptions.getHost().Value(),
    // objConnectionOptions.getPort().value()));
    // }
    // catch (RuntimeException e) {
    // if (objConnectionOptions.getalternative_host().IsNotEmpty() && objConnectionOptions.getalternative_port().IsNotEmpty()) {
    // logger.info("Not possible to connect to Host. Try alternate host.");
    // this.connect(objConnectionOptions.getalternative_host().Value(), //
    // objConnectionOptions.getalternative_port().value());
    // logger.info(String.format("successful connected to Host '%1$s' at port '%1$d'.", objConnectionOptions.getalternative_host().Value(),
    // //
    // objConnectionOptions.getalternative_port().value()));
    // }
    // else {
    // throw e;
    // }
    // }
    // return this;
    // }

    // public void connect(String value, int value2) {
    // // TODO Auto-generated method stub
    //
    // }
    //
    // public final ISOSConnection Connect(SOSConnection2OptionsAlternate pobjConnectionOptions) {
    // @SuppressWarnings("unused")
    // final String conMethodName = conClassName + "::Connect";
    // objConnection2Options = pobjConnectionOptions;
    // try {
    // objHost = objConnection2Options.getHost();
    // objPort = objConnection2Options.getport();
    // this.connect(objHost.Value(), objPort.value());
    // if (Client().isConnected() == false) {
    // SOSConnection2OptionsSuperClass objAlternate = objConnection2Options.Alternatives();
    // objHost = objAlternate.host;
    // objPort = objAlternate.port;
    // logger.info(String.format("try alternate host due to connection-error", host));
    // this.connect(objHost.Value(), objPort.value());
    // if (Client().isConnected() == false) {
    // objHost = null;
    // objPort = null;
    // host = "";
    // port = -1;
    // throw new JobSchedulerException("Connection not possible");
    // }
    // }
    // // TODO find the "Microsoft FTP Server" String from the reply and set the HostType accordingly
    // // TODO respect Proxy-Server. implement handling of
    // }
    // catch (Exception e) {
    // e.printStackTrace();
    // logger.error("exception occured", e);
    // throw new JobSchedulerException("exception occured:", e);
    // }
    // return this;
    // }
    //
    // @Deprecated
    // @Override
    // public final ISOSConnection Connect(ISOSConnectionOptions pobjConnectionOptions) throws Exception {
    // objConnectionOptions = pobjConnectionOptions;
    // try {
    // String host = objConnectionOptions.getHost().Value();
    // int port = objConnectionOptions.getPort().value();
    // // TODO try alternate host, if this connection is not possible
    // this.connect(host, port);
    // // TODO find the "Microsoft FTP Server" String from the reply and set the HostType accordingly
    // }
    // catch (Exception e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // return this;
    // }
    //
    // @Override
    // public final ISOSConnection Connect(String pstrHostName, int pintPortNumber) throws Exception {
    // this.connect(pstrHostName, pintPortNumber);
    // if (objConnectionOptions != null) {
    // objConnectionOptions.getHost().Value(pstrHostName);
    // objConnectionOptions.getPort().value(pintPortNumber);
    // }
    // return this;
    // }

    /*
     * @param host the remote ftp server
     * @param port the port number of the remote server
     *
     * @throws java.net.SocketException
     * @throws java.io.IOException
     * @throws java.net.UnknownHostException
     * @see org.apache.commons.net.SocketClient#connect(java.lang.String, int)
     */
    public void connect(final String phost, final int pport) {
        final String conMethodName = conClassName + "::connect";

        try {
            host = phost;
            port = pport;
            String strM = SOSVfs_D_0101.params(host, port);
            logger.debug(strM);
            if (isConnected() == false) {
                Client().connect(host, port);
                logger.debug(SOSVfs_D_0102.params(host, port));
                LogReply();
            } else {
                logger.warn(SOSVfs_D_0102.params(host, port));

            }
        } catch (Exception e) {
            e.printStackTrace(System.err);
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
    }

    /**
     *
     * \brief Connect
     *
     * \details
     *
     * \return
     *
     * @param pobjConnectionOptions
     * @return
     */
    @Override
    public final ISOSConnection Connect(final SOSConnection2OptionsAlternate pobjConnectionOptions) {
        final String conMethodName = conClassName + "::Connect";
        objConnection2Options = pobjConnectionOptions;
        try {
            objHost = objConnection2Options.getHost();
            objPort = objConnection2Options.getport();
            this.connect(objHost.Value(), objPort.value());
            if (Client().isConnected() == false) {
                SOSConnection2OptionsSuperClass objAlternate = objConnection2Options.Alternatives();
                objHost = objAlternate.host;
                objPort = objAlternate.port;
                logger.info(SOSVfs_I_0121.params(host));
                this.connect(objHost.Value(), objPort.value());
                if (Client().isConnected() == false) {
                    objHost = null;
                    objPort = null;
                    host = "";
                    port = -1;
                    RaiseException(SOSVfs_E_204.get());
                }
            }
            // TODO find the "Microsoft FTP Server" String from the reply and set the HostType accordingly
            // TODO respect Proxy-Server. implement handling of
        } catch (Exception e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return this;
    }

    @Deprecated
    @Override
    public ISOSConnection Connect(final ISOSConnectionOptions pobjConnectionOptions) throws Exception {
        final String conMethodName = conClassName + "::Connect";

        objConnectionOptions = pobjConnectionOptions;
        try {
            host = objConnectionOptions.getHost().Value();
            port = objConnectionOptions.getPort().value();
            // TODO try alternate host, if this connection is not possible
            this.connect(host, port);
            // TODO find the "Microsoft FTP Server" String from the reply and set the HostType accordingly
        } catch (Exception e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return this;
    }

    @Override
    public ISOSConnection Connect(final String pstrHostName, final int pintPortNumber) throws Exception {
        this.connect(pstrHostName, pintPortNumber);
        if (objConnectionOptions != null) {
            objConnectionOptions.getHost().Value(pstrHostName);
            objConnectionOptions.getPort().value(pintPortNumber);
        }
        return this;
    }

    @Override
    public final void CloseSession() throws Exception {
        this.logout();
    }

    @Override
    public final ISOSSession OpenSession(final ISOSShellOptions pobjShellOptions) throws Exception {
        notImplemented();
        return null;
    }

    @Override
    public final ISOSVirtualFile TransferMode(final SOSOptionTransferMode pobjFileTransferMode) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::TransferMode";

        String strMode = pobjFileTransferMode.getDescription();
        if (pobjFileTransferMode.isAscii()) {
            this.ascii();
        } else {
            this.binary();
        }

        logger.debug(SOSVfs_D_122.params(strMode));
        logger.debug(SOSVfs_D_123.params(strMode, getReplyString()));
        return null;
    }

    /*
     * @param host the remote ftp server
     * @param port the port number of the remote server
     * @throws java.net.SocketException
     * @throws java.io.IOException
     * @throws java.net.UnknownHostException
     * @see org.apache.commons.net.SocketClient#connect(java.lang.String)
     */
    @SuppressWarnings("unused")
    private void connect(final String hostname) throws SocketException, IOException, UnknownHostException {
        if (isConnected() == false)
            Client().connect(hostname);
    }

    /**
     * turn passive transfer mode on.
     *
     * @return The reply code received from the server.
     */
    @Override
    public final int passive() {
        final String conMethodName = conClassName + "::passive";

        try {
            int i = Client().pasv();
            if (isPositiveCommandCompletion() == false) {
                throw new JobSchedulerException(HostID(SOSVfs_E_0106.params("pasv", "", getReplyString())));
            } else {
                // SOSVfs_E_0106=..Antwort des Rechners nach Kommando '%1$s' (mit Parameter '%2$s') lautet: '%3$s'.

                logger.debug(HostID(SOSVfs_E_0106.params("pasv", "", getReplyString())));
            }
            return i;
        } catch (IOException e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return 0;
    }

    /**
        * Einige wenige Methoden erfordern dieses zusaetzliche abschliessende Kommando,
        * z.B. die Methoden, welche {@link FTPClient.retrieveFileStream()} verwenden
        * (insbesondere {@link FtpFileWrapper.retrieveTextFile()}, {@link FtpFileWrapper.retrieveBinaryFile()}
        *  und {@link FtpFileWrapper.storeFile( String remoteResultFile )}).<br>
        * Siehe {@link http://commons.apache.org/net/apidocs/org/apache/commons/net/ftp/FTPClient.html#completePendingCommand()}
        */
    @Override
    public final void CompletePendingCommand() {
        final String conMethodName = conClassName + "::CompletePendingCommand";
        logger.debug("completePendingCommand");
        try {
            if (Client().completePendingCommand() == false) {
                logout();
                disconnect();
                RaiseException(HostID(SOSVfs_E_0105.params(conMethodName)));
            }
        } catch (IOException e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }

        if (isNegativeCommandCompletion()) {
            throw new JobSchedulerException(SOSVfs_E_124.params(getReplyString()));
        }

    }

    private boolean isPositiveCommandCompletion() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::isPositiveCommandCompletion";
        int x = Client().getReplyCode();
        return x <= 300;
    } // private boolean isPositiveCommandCompletion

    public boolean isNotHiddenFile(final String strFileName) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::isNotHiddenFile";
        if (strFileName.equalsIgnoreCase("..") == false && strFileName.equalsIgnoreCase(".") == false) {
            return true; // not a hidden file
        }
        return false; // it is a hidden-file
    } // private boolean isNotHiddenFile

    /*
     * @param host the remote ftp server
     * @param port the port number of the remote server
     * @throws java.net.SocketException
     * @throws java.io.IOException
     * @throws java.net.UnknownHostException
     * @see org.apache.commons.net.SocketClient#connect(java.lang.String, int)
     */

    /**
     * return a listing of the contents of a directory in short format on
     * the remote machine
     * @param pathname on remote machine
     * @return a listing of the contents of a directory on the remote machine
     *
     * @exception Exception
     * @see #dir()
     */
    @Override
    public Vector<String> nList(final String pathname) {
        return getFilenames(pathname);
    } // nList

    private Vector<String> getFilenames(final String pathname) {
        return getFilenames(pathname, false);
    }

    /**
     * return a listing of the contents of a directory in short format on
     * the remote machine (without subdirectory)
     *
     * @param pathname on remote machine
     * @return a listing of the contents of a directory on the remote machine
     * @throws IOException
     *
     * @exception Exception
     * @see #dir()
     */
    private Vector<String> getFilenames(final String pstrPathName, final boolean flgRecurseSubFolders) {
        String strCurrentDirectory = null;
        // TODO vecDirectoryListing = null; prfen, ob notwendig
        vecDirectoryListing = null;
        if (vecDirectoryListing == null) {
            vecDirectoryListing = new Vector<String>();
            String[] fileList = null;
            strCurrentDirectory = DoPWD();
            String lstrPathName = pstrPathName.trim();
            if (lstrPathName.length() <= 0) {
                lstrPathName = ".";
            }
            if (lstrPathName.equals(".")) {
                lstrPathName = strCurrentDirectory;
            }
            FTPFile[] objFTPFileList = null;
            try {
                objFTPFileList = Client().listFiles(lstrPathName);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            //         if (1 == 1) {
            //            try {
            //               fileList = listNames(lstrPathName);
            //               // fileList = listNames(pstrPathName);
            //            }
            //            catch (IOException e) {
            //               e.printStackTrace(System.err);
            //            }
            //         }
            // else {
            // FTPFile[] objFtpFiles = Client().listFiles(lstrPathName);
            // if (objFtpFiles != null) {
            // int i = 0;
            // for (FTPFile ftpFile : objFtpFiles) {
            // fileList[i++] = ftpFile.getName();
            // }
            // }
            // }
            if (objFTPFileList == null) {
                return vecDirectoryListing;
            }
            for (FTPFile ftpFile : objFTPFileList) {
                String strCurrentFile = ftpFile.getName();
                if (isNotHiddenFile(strCurrentFile)) {
                    if (flgRecurseSubFolders == false && ftpFile.isFile()) {
                        if (strCurrentFile.startsWith(strCurrentDirectory) == false)
                            strCurrentFile = strCurrentDirectory + "/" + strCurrentFile;
                        vecDirectoryListing.add(strCurrentFile);
                    } else {
                        //                  DoCD(strCurrentFile); // is this file-entry a subfolder?
                        //                  if (isNegativeCommandCompletion()) {
                        if (ftpFile.isFile()) {
                            if (strCurrentFile.startsWith(strCurrentDirectory) == false)
                                strCurrentFile = strCurrentDirectory + "/" + strCurrentFile;
                            vecDirectoryListing.add(strCurrentFile);
                        } else {
                            //                     DoCD(strCurrentDirectory);
                            if (ftpFile.isDirectory() && flgRecurseSubFolders) {
                                Vector<String> vecNames = getFilenames(strCurrentFile);
                                if (vecNames != null) {
                                    vecDirectoryListing.addAll(vecNames);
                                }
                            }
                        }
                    }
                }
            }
        }
        logger.debug(SOSVfs_I_126.params(strCurrentDirectory));
        if (strCurrentDirectory != null) {
            DoCD(strCurrentDirectory);
            DoPWD();
        }
        return vecDirectoryListing;
    } // nList

    @Override
    public void CloseConnection() throws Exception {
        if (Client().isConnected()) {
            Client().disconnect();
            logger.debug(SOSVfs_D_125.params(objConnection2Options.getHost().Value()));
            LogReply();
        }
    }

    private int DoCD(final String strFolderName) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::DoCD";
        int x = 0;
        try {
            String strT = strFolderName.replaceAll("\\\\", "/");
            logger.debug(SOSVfs_D_127.params(strT));
            x = cd(strT);
            LogReply();
        } catch (IOException e) {
        }
        return x;
    } // private int DoCD

    protected boolean LogReply() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::LogReply";
        strReply = getReplyString();
        if (strReply.startsWith("550") || strReply.startsWith("500")) {
            boolean flgError = true;
            ;
        }
        logger.trace(strReply);
        return true;
    } // private boolean LogReply

    @Override
    public boolean isNegativeCommandCompletion() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::isNegativeCommandCompletion";
        // TODO separate Routine draus machen
        // try {
        // if (Client().completePendingCommand() == false) {
        // logout();
        // disconnect();
        // RaiseException("File transfer failed. completePendingCommand() returns false");
        // }
        // }
        // catch (Exception e) {
        // // TODO Auto-generated catch block
        // e.printStackTrace();
        // }
        int x = Client().getReplyCode();
        return x > 300;
    } // private boolean isNegativeCommandCompletion

    /**
     * return a listing of the contents of a directory in short format on
     * the remote machine
     * @param pathname on remote machine
     * @return a listing of the contents of a directory on the remote machine
     *
     * @exception Exception
     * @see #dir()
     */
    @Override
    public Vector<String> nList(final String pathname, final boolean flgRecurseSubFolder) {
        try {
            return getFilenames(pathname, flgRecurseSubFolder);
        } catch (Exception e) {
            throw new JobSchedulerException(SOSVfs_E_128.params("getfilenames", "nLixt"), e);
        }
    } // nList

    /**
     * return a listing of the contents of a directory in short format on
     * the remote machine
     *
     * @return a listing of the contents of a directory on the remote machine
     *
     * @exception Exception
     * @see #nList( String )
     * @see #dir()
     * @see #dir( String )
     */
    @Override
    public Vector<String> nList() throws Exception {
        return getFilenames();
    } // nList

    /**
     * return a listing of the contents of a directory in short format on
     * the remote machine (without subdirectory)
     *
     * @return a listing of the contents of a directory on the remote machine
     *
     * @exception Exception
     * @see #nList( String )
     * @see #dir()
     * @see #dir( String )
     */
    private Vector<String> getFilenames() throws Exception {
        return getFilenames("", false);
    } // getFilenames

    private Vector<String> getFilenames(final boolean flgRecurseSubFolders) throws Exception {
        return getFilenames("", flgRecurseSubFolders);
    } // getFilenames

    /**
     * return a listing of the contents of a directory in short format on
     * the remote machine
     *
     * @return a listing of the contents of a directory on the remote machine
     *
     * @exception Exception
     * @see #nList( String )
     * @see #dir()
     * @see #dir( String )
     */
    @Override
    public Vector<String> nList(final boolean recursive) throws Exception {
        return getFilenames(recursive);
    } // nList

    /**
     * return a listing of the files in a directory in long format on
     * the remote machine
     * @param pathname on remote machine
     * @return a listing of the contents of a directory on the remote machine
     * @exception Exception
     * @see #nList()
     * @see #nList( String )
     * @see #dir()
     */
    public SOSFileList dir(final String pathname) {
        Vector<String> strList = getFilenames(pathname);
        String[] strT = strList.toArray(new String[strList.size()]);
        SOSFileList objFileList = new SOSFileList(strT);
        return objFileList;
    }

    /**
     * return a listing of a directory in long format on
     * the remote machine
     *
     * @param pathname on remote machine
     * @return a listing of the contents of a directory on the remote machine
     * @exception Exception
     * @see #nList()
     * @see #nList( String )
     * @see #dir()
     */
    @Override
    public SOSFileList dir(final String pathname, final int flag) {
        SOSFileList fileList = new SOSFileList();
        FTPFile[] listFiles;
        try {
            listFiles = Client().listFiles(pathname);
        } catch (IOException e) {
            throw new RuntimeException(SOSVfs_E_128.params("listfiles", "dir"), e);
        }
        for (FTPFile listFile : listFiles) {
            if (flag > 0 && listFile.isDirectory()) {
                fileList.addAll(this.dir(pathname + "/" + listFile.toString(), flag >= 1024 ? flag : flag + 1024));
            } else {
                if (flag >= 1024) {
                    fileList.add(pathname + "/" + listFile.toString());
                } else {
                    fileList.add(listFile.toString());
                }
            }
        }
        return fileList;
    }

    /**
     * return a listing of the files of the current directory in long format on
     * the remote machine
     * @return a listing of the contents of the current directory on the remote machine
     * @exception Exception
     * @see #nList()
     * @see #nList( String )
     * @see #dir( String )
     */
    public SOSFileList dir() {
        try {
            return dir(".");
        } catch (Exception e) {
            throw new RuntimeException(SOSVfs_E_130.params("dir"), e);
        }
    }

    /**
     * @return The entire text from the last FTP response as a String.
     */
    public String getResponse() {
        return this.getReplyString();
    }

    /**
     * return the size of remote-file on the remote machine on success, otherwise -1
     * @param remoteFile the file on remote machine
     * @return the size of remote-file on remote machine
     */
    public long size(final String remoteFile) throws Exception {
        Client().sendCommand("SIZE " + remoteFile);
        LogReply();
        if (Client().getReplyCode() == FTPReply.CODE_213)
            return Long.parseLong(trimResponseCode(this.getReplyString()));
        else
            return -1L;
    }

    /**
     * trim the response code at the beginning
     * @param response
     * @return the response string without response code
     * @throws Exception
     */
    private String trimResponseCode(final String response) throws Exception {
        if (response.length() < 5)
            return response;
        return response.substring(4).trim();
    }

    /**
     *
     * @param directory The new working directory.
     * @return The reply code received from the server.
     * @throws IOException If an I/O error occurs while either sending a
     * command to the server or receiving a reply from the server.
     */
    public int cd(final String directory) throws IOException {
        return Client().cwd(directory);
    }

    /**
     * Deletes a file on the FTP server.
     * @param The pathname of the file to be deleted.
     * @return True if successfully completed, false if not.
     * @throws IOException If an I/O error occurs while either sending a
     * command to the server or receiving a reply from the server.
     */
    @Override
    public void delete(final String pathname) throws IOException {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::delete";

        Client().deleteFile(pathname);
        logger.info(SOSVfs_I_131.params(pathname, getReplyString()));
    }

    @Override
    public void login(final String strUserName, final String strPassword) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::login";
        gstrUser = strUserName;
        try {
            logger.debug(SOSVfs_D_132.params(strUserName));
            Client().login(strUserName, strPassword);
            LogReply();
            if (objFTPReply.isSuccessCode()) {
                objProtocolCommandListener.setClientId(HostID(""));
                logger.debug(HostID(SOSVfs_D_133.params(strUserName)));
                try {
                    doPostLoginOperations();
                } catch (Exception e) {
                }
            } else {
                // SOSFTP-113
                throw new Exception(SOSVfs_E_134.params("Login"));
            }
        } catch (Exception e) {
            // avoid logger.error because there could be an alternative login
            throw new JobSchedulerException(e); // SOSFTP-113
            //         RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));              // SOSFTP-113
        }
    } // private boolean login

    @Override
    public boolean changeWorkingDirectory(final String pathname) {
        try {
            Client().cwd(pathname);
            logger.debug(SOSVfs_D_135.params(pathname, getReplyString(), "[directory exists]"));
        } catch (IOException e) {
            throw new RuntimeException(SOSVfs_E_130.params("cwd"), e);
        }
        return true;
    }

    @Override
    public void disconnect() {
        try {
            if (Client().isConnected()) {
                Client().disconnect();
            }
        } catch (IOException e) {
            logger.warn(SOSVfs_W_136.get() + e.getLocalizedMessage());
        }
    }

    @Override
    public String[] listNames(final String pathname) throws IOException {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::listNames";
        String strA[] = Client().listNames(pathname);
        for (int i = 0; i < strA.length; i++) {
            strA[i] = strA[i].replaceAll("\\\\", "/");
        }
        logger.debug(SOSVfs_D_137.params(Client().getReplyString(), Client().getReplyCode()));
        return strA;
    }

    @Override
    public void logout() {
        try {
            if (this.Client().isConnected() == true) {
                this.Client().logout();
                String strHost = host;
                if (objHost != null) {
                    strHost = objHost.Value();
                }
                logger.debug(SOSVfs_D_138.params(strHost, getReplyString()));
            } else {
                logger.info(SOSVfs_I_139.get());
            }
        } catch (IOException e) { // no error-handling needed, due to end-of session
            logger.warn(SOSVfs_W_140.get() + e.getMessage());
        }
    }

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

    protected void RaiseException(final String pstrM) {
        logger.error(pstrM);
        throw new JobSchedulerException(pstrM);
    }

    @Override
    public String getModificationTime(final String strFileName) {
        final String conMethodName = conClassName + "::getModificationTime";

        String strT = null;
        // Es gibt Probleme bei der standalone-compilation mit javac. unter eclipse luft es fehlerfrei
        try {
            /*
             * Issue the FTP MDTM command (not supported by all servers to retrieve the last modification time of a file.
             * The modification string should be in the ISO 3077 form "YYYYMMDDhhmmss(.xxx)?".
             * The timestamp represented should also be in GMT, but not all FTP servers honour this.
             */
            strT = Client().getModificationTime(strFileName);
        } catch (Exception e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return strT;
    }

    @Override
    public OutputStream getOutputStream(final String strFileName) {
        OutputStream objO = null;
        try {
            objO = Client().storeFileStream(strFileName);
            LogReply();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objO;
    }

    @Override
    public void flush() {
        // TODO Auto-generated method stub
    }

    @Override
    public int read(final byte[] bteBuffer) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public int read(final byte[] bteBuffer, final int intOffset, final int intLength) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void write(final byte[] bteBuffer, final int intOffset, final int intLength) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::write";
    }

    @Override
    public void write(final byte[] bteBuffer) {
        // TODO Auto-generated method stub
    }

    @Override
    public void openInputFile(final String pstrFileName) {
        // TODO Auto-generated method stub
    }

    @Override
    public void openOutputFile(final String pstrFileName) {
        // TODO Auto-generated method stub
    }

    @Override
    public Vector<ISOSVirtualFile> getFiles(final String string) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Vector<ISOSVirtualFile> getFiles() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void putFile(final ISOSVirtualFile objVirtualFile) {
        String strName = objVirtualFile.getName();
        // strName = new File(strName).getAbsolutePath();
        // if (strName.startsWith("c:") == true) {
        // strName = strName.substring(3);
        // }
        ISOSVirtualFile objVF = this.getFileHandle(strName);
        OutputStream objOS = objVF.getFileOutputStream();
        InputStream objFI = objVirtualFile.getFileInputStream();
        int lngBufferSize = 1024;
        byte[] buffer = new byte[lngBufferSize];
        int intBytesTransferred;
        long totalBytes = 0;
        try {
            synchronized (this) {
                while ((intBytesTransferred = objFI.read(buffer)) != -1) {
                    objOS.write(buffer, 0, intBytesTransferred);
                    totalBytes += intBytesTransferred;
                }
                objFI.close();
                objOS.flush();
                objOS.close();
            }
        } catch (Exception e) {
            throw new JobSchedulerException(SOSVfs_E_130.params("putfile"), e);
        } finally {
        }
    }

    @Override
    public void closeInput() {
        logger.debug("close input stream");
        // TODO Auto-generated method stub
    }

    @Override
    public void closeOutput() {
        final String conMethodName = conClassName + "::closeOutput";

        try {
            // this.getOutputStream(strFileName);
            // Client().completePendingCommand();
            this.CompletePendingCommand();
        } catch (Exception e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
    }

    @Override
    public void close() {
        final String conMethodName = conClassName + "::close";

        try {
            /**
             * don't do that, because if no command is pending this will lead into
             * a huge waittime and an exception.
             */
            // this.CompletePendingCommand();
            // Client().completePendingCommand();
        } catch (Exception e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
    }

    @Override
    public final boolean isDirectory(final String pstrPathName) {
        boolean flgResult = false;
        if (isNotHiddenFile(pstrPathName)) {
            if (strCurrentPath.length() <= 0) {
                strCurrentPath = getCurrentPath();
            }
            DoCD(pstrPathName); // is this file-entry a subfolder?
            if (isNegativeCommandCompletion()) {
            } else { // yes, it's a subfolder. undo the cd now
                DoCD(strCurrentPath);
                flgResult = true;
            }
        }
        return flgResult;
    }

    @Override
    public final String DoPWD() {
        final String conMethodName = conClassName + "::DoPWD";
        String lstrCurrentPath = "";
        try {
            logger.debug(SOSVfs_D_141.params("pwd"));
            lstrCurrentPath = getCurrentPath();
        } catch (Exception e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return lstrCurrentPath;
    } // private int DoPWD

    protected final String getCurrentPath() {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::getCurrentPath";

        String lstrCurrentPath = strCurrentPath;
        try {
            Client().pwd();
            lstrCurrentPath = getReplyString();
            logger.debug(HostID(SOSVfs_E_0106.params(conMethodName, "", lstrCurrentPath)));
            // Windows reply from pwd is : 257 "/kb" is current directory.
            // Unix reply from pwd is : 257 "/home/kb"
            int idx = lstrCurrentPath.indexOf('"'); // Unix?
            if (idx >= 0) {
                lstrCurrentPath = lstrCurrentPath.substring(idx + 1, lstrCurrentPath.length() - idx + 1);
                idx = lstrCurrentPath.indexOf('"');
                if (idx >= 0) {
                    lstrCurrentPath = lstrCurrentPath.substring(0, idx);
                }
            }
            LogReply();
        } catch (IOException e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return lstrCurrentPath;
    }

    protected final int DoCDUP() {
        final String conMethodName = conClassName + "::DoCDUP";

        try {
            logger.debug(SOSVfs_D_141.params("cdup"));
            Client().cdup();
            LogReply();
            DoPWD();
        } catch (IOException e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }

        return 0;
    } // private int DoCDUP

    /**
     * Retrieves a named file from the ftp server.
     *
     * @param localFile The name of the local file.
     * @param remoteFile The name of the remote file.
     * @exception Exception
     * @see #getFile( String, String )
     */
    public void get(final String remoteFile, final String localFile) {
        FileOutputStream out = null;
        boolean rc = false;
        try {
            out = new FileOutputStream(localFile);
            rc = Client().retrieveFile(remoteFile, out);
            if (rc == false) {
                throw new JobSchedulerException(SOSVfs_E_142.get());
            }
        } catch (IOException e) {
            throw new JobSchedulerException(SOSVfs_E_130.params("get"), e);
        } finally {
            closeObject(out);
        }
    } // get

    private void closeObject(OutputStream objO) {
        try {
            if (objO != null) {
                objO.flush();
                objO.close();
                objO = null;
                logger.debug("OutputStream closed");
            }
        } catch (Exception e) {
        }
    }

    private void closeInput(InputStream objO) {
        try {
            if (objO != null) {
                objO.close();
                objO = null;
                logger.debug("InputStream closed");
            }
        } catch (IOException e) {
        }
    }

    /**
     * Retrieves a named file from the ftp server.
     *
     * @param localFile The name of the local file.
     * @param remoteFile The name of the remote file.
     * @return  The total number of bytes retrieved.
     * @see #get( String, String )
     * @exception Exception
     */
    @Override
    public long getFile(final String remoteFile, final String localFile) {
        final boolean flgAppendLocalFile = false;
        return this.getFile(remoteFile, localFile, flgAppendLocalFile);
    }

    /**
     * Retrieves a named file from the ftp server.
     *
     * @param localFile The name of the local file.
     * @param remoteFile The name of the remote file.
     * @param append Appends the remote file to the local file.
     * @return  The total number of bytes retrieved.
     * @see #get( String, String )
     * @exception Exception
     */
    @Override
    public long getFile(final String remoteFile, final String localFile, final boolean append) {
        InputStream in = null;
        OutputStream out = null;
        long totalBytes = 0;
        try {
            // TODO get filesize and report as a message
            in = Client().retrieveFileStream(remoteFile);
            if (in == null) {
                throw new JobSchedulerException(SOSVfs_E_143.params(remoteFile, getReplyString()));
            }
            if (isPositiveCommandCompletion() == false) {
                throw new JobSchedulerException(SOSVfs_E_144.params("getFile()", remoteFile, getReplyString()));
            }
            // TODO Buffersize must be an Option
            byte[] buffer = new byte[4096];
            out = new FileOutputStream(new File(localFile), append);
            // TODO get progress info
            int bytes_read = 0;
            synchronized (this) {
                while ((bytes_read = in.read(buffer)) != -1) {
                    // TODO create progress message
                    out.write(buffer, 0, bytes_read);
                    out.flush();
                    totalBytes += bytes_read;
                }
            }
            closeInput(in);
            closeObject(out);
            if (Client().completePendingCommand() == false) {
                logout();
                disconnect();
                throw new JobSchedulerException(SOSVfs_E_134.params("File transfer"));
            }
            if (isNegativeCommandCompletion()) {
                throw new JobSchedulerException(SOSVfs_E_144.params("getFile()", remoteFile, getReplyString()));
            }
            // TODO create completed Message
            if (totalBytes > 0)
                return totalBytes;
            else
                return -1L;
        } catch (IOException e) {
            RaiseException(e, SOSVfs_E_130.params("getFile"));
        } finally {
            closeInput(in);
            closeObject(out);
        }
        return totalBytes;
    }

    /**
     * Stores a file on the server using the given name.
     * @param localFile The name of the local file.
     * @param remoteFile The name of the remote file.
     * @return True if successfully completed, false if not.
     * @exception Exception
     * @see #putFile( String, String )
     */
    @Override
    public void put(final String localFile, final String remoteFile) {
        FileInputStream in = null;
        boolean rc = false;
        try {
            in = new FileInputStream(localFile);
            // TODO get progress info
            rc = Client().storeFile(remoteFile, in);
            if (rc == false) {
                RaiseException(SOSVfs_E_142.params("put"));
            }
        } catch (Exception e) {
            RaiseException(e, SOSVfs_E_130.params("put"));
        } finally {
            closeInput(in);
        }
    }

    /**
     * Stores a file on the server using the given name.
     *
     * @param localFile The name of the local file.
     * @param remoteFile The name of the remote file.
     * @return The total number of bytes written.
     *
     * @exception Exception
     * @see #put( String, String )
     */
    @Override
    // ISOSVfsFileTransfer
    public long putFile(final String localFile, final String remoteFile) throws Exception {
        OutputStream outputStream = Client().storeFileStream(remoteFile);
        if (isNegativeCommandCompletion()) {
            RaiseException(SOSVfs_E_144.params("storeFileStream()", remoteFile, getReplyString()));
        }
        long i = putFile(localFile, outputStream);
        logger.debug(SOSVfs_D_146.params(localFile, remoteFile));
        return i;
    } // putFile

    /**
     * written to store a file on the server using the given name.
     *
     * @param localfile The name of the local file.
     * @param an OutputStream through which data can be
     * @return The total number of bytes written.
     * @exception Exception
     */
    @SuppressWarnings("null")
    @Override
    public long putFile(final String localFile, final OutputStream out) {
        if (out == null)
            RaiseException(SOSVfs_E_147.get());
        FileInputStream in = null;
        long lngTotalBytesWritten = 0;
        try {
            // TODO Buffersize must be an Option
            byte[] buffer = new byte[4096];
            in = new FileInputStream(new File(localFile));
            // TODO get progress info
            int bytesWritten;
            synchronized (this) {
                while ((bytesWritten = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesWritten);
                    lngTotalBytesWritten += bytesWritten;
                }
            }
            closeInput(in);
            closeObject(out);
            if (Client().completePendingCommand() == false) {
                logout();
                disconnect();
                RaiseException(SOSVfs_E_134.params("File transfer") + SOSVfs_E_148.get());
            }
            if (isNegativeCommandCompletion()) {
                RaiseException(SOSVfs_E_144.params("getFile()", localFile, getReplyString()));
            }
            return lngTotalBytesWritten;
        } catch (Exception e) {
            RaiseException(e, SOSVfs_E_130.params("putfile"));
        } finally {
            closeInput(in);
            closeObject(out);
        }
        return lngTotalBytesWritten;
    } // putFile

    /**
     * append a local file to the remote one on the server
     *
     * @param localFile The name of the local file.
     * @param remoteFile The name of the remote file.
     *
     * @return The total number of bytes appended.
     *
     * @exception Exception
     * @see #put( String, String )
     * @see #putFile( String, String )
     */
    @Override
    public long appendFile(final String localFile, final String remoteFile) {
        long i;
        try {
            i = putFile(localFile, Client().appendFileStream(remoteFile));
            logger.info("bytes appended : " + i);
        } catch (IOException e) {
            throw new RuntimeException(SOSVfs_E_130.params("appendFileStream", e));
        }
        return i;
    } // appendFile

    /**
     * Using ASCII mode for file transfers
     * @return True if successfully completed, false if not.
     * @throws IOException If an I/O error occurs while either sending a
     * command to the server or receiving a reply from the server.
     */
    @Override
    public void ascii() {
        try {
            boolean flgResult = Client().setFileType(FTP.ASCII_FILE_TYPE);
            if (flgResult == false) {
                throw new JobSchedulerException(SOSVfs_E_149.params(getReplyString()));
            }
        } catch (IOException e) {
            throw new JobSchedulerException(SOSVfs_E_130.params("ascii", e));
        }
    }

    /**
     * Using Binary mode for file transfers
     * @return True if successfully completed, false if not.
     * @throws IOException If an I/O error occurs while either sending a
     * command to the server or receiving a reply from the server.
     */
    @Override
    public void binary() {
        try {
            boolean flgResult = Client().setFileType(FTP.BINARY_FILE_TYPE);
            if (flgResult == false) {
                throw new JobSchedulerException(SOSVfs_E_149.params(getReplyString()));
            }
        } catch (IOException e) {
            throw new JobSchedulerException(SOSVfs_E_130.params("setFileType to binary"), e);
        }
    }

    @Override
    public void rename(final String from, final String to) {
        try {
            this.Client().rename(from, to);
        } catch (IOException e) {
            e.printStackTrace();
            RaiseException(e, SOSVfs_E_134.params("rename"));
        }
        logger.info(String.format(SOSVfs_I_150.params(from, to)));
    }

    @Override
    public ISOSVFSHandler getHandler() {
        return this;
    }

    @Override
    public void ExecuteCommand(final String strCmd) throws Exception {
        Client().sendCommand(strCmd);
        logger.debug(SOSVfs_D_151.params(strCmd, getReplyString()));
    }

    @Override
    public String createScriptFile(final String pstrContent) throws Exception {
        notImplemented();
        return null;
    }

    @Override
    public Integer getExitCode() {
        notImplemented();
        return null;
    }

    @Override
    public String getExitSignal() {
        notImplemented();
        return null;
    }

    @SuppressWarnings("unused")
    private ISOSAuthenticationOptions objAO = null;

    @Override
    public final ISOSConnection Authenticate(final ISOSAuthenticationOptions pobjAO) throws Exception {
        String user = pobjAO.getUser().Value();
        String Passwd = pobjAO.getPassword().Value();
        this.login(user, Passwd);
        objAO = pobjAO;
        return this;
    }

    public SOSFileListEntry getNewVirtualFile(final String pstrFileName) {
        SOSFileListEntry objF = new SOSFileListEntry(pstrFileName);
        objF.VfsHandler(this);
        return objF;
    }

    @Override
    public ISOSVirtualFolder mkdir(final SOSFolderName pobjFolderName) {
        this.mkdir(pobjFolderName.Value());
        return null;
    }

    @Override
    public boolean rmdir(final SOSFolderName pobjFolderName) throws IOException {
        this.rmdir(pobjFolderName.Value());
        return true;
    }

    @Override
    public ISOSConnection getConnection() {
        return this;
    }

    @Override
    public ISOSSession getSession() {
        return null;
    }

    @Override
    public SOSFileList dir(final SOSFolderName pobjFolderName) {
        this.dir(pobjFolderName.Value());
        return null;
    }

    @Override
    public StringBuffer getStdErr() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public StringBuffer getStdOut() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean remoteIsWindowsShell() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void setJSJobUtilites(final JSJobUtilities pobjJSJobUtilities) {
        // TODO Auto-generated method stub
    }

    @Override
    public ISOSVirtualFile getFileHandle(final String pstrFilename) {
        final String conMethodName = conClassName + "::getFileHandle";
        ISOSVirtualFile objFtpFile = new SOSVfsFtpFile(pstrFilename);
        logger.debug(SOSVfs_D_152.params(pstrFilename, conMethodName));
        objFtpFile.setHandler(this);
        return objFtpFile;
    }

    @Override
    public String[] getFilelist(final String folder, final String regexp, final int flag,
            final boolean withSubFolder) {
        // TODO vecDirectoryListing = null; prfen, ob notwendig
        vecDirectoryListing = null;
        if (vecDirectoryListing == null) {
            vecDirectoryListing = nList(folder, withSubFolder);
        }
        Vector<String> strB = new Vector<String>();
        Pattern pattern = Pattern.compile(regexp, 0);
        for (String strFile : vecDirectoryListing) {
            /**
             * the file_spec has to be compared to the filename only ... excluding the path
             */
            String strFileName = new File(strFile).getName();
            Matcher matcher = pattern.matcher(strFileName);
            if (matcher.find() == true) {
                strB.add(strFile);
            }
        }
        return strB.toArray(new String[strB.size()]);
    }

    @Override
    public String[] getFolderlist(final String folder, final String regexp, final int flag,
            final boolean withSubFolder) {
        // TODO vecDirectoryListing = null; prfen, ob notwendig
        vecDirectoryListing = null;
        if (vecDirectoryListing == null) {
            vecDirectoryListing = nList(folder, withSubFolder);
        }
        Vector<String> strB = new Vector<String>();
        Pattern pattern = Pattern.compile(regexp, 0);
        for (String strFile : vecDirectoryListing) {
            /**
             * the file_spec has to be compared to the filename only ... excluding the path
             */
            String strFileName = new File(strFile).getName();
            Matcher matcher = pattern.matcher(strFileName);
            if (matcher.find() == true) {
                strB.add(strFile);
            }
        }
        return strB.toArray(new String[strB.size()]);
    }

    @Override
    /* ISOSVfsFiletransfer */
    public void ControlEncoding(final String pstrControlEncoding) {
        @SuppressWarnings("unused")
        final String conMethodName = conClassName + "::ControlEncoding";

        if (pstrControlEncoding.length() > 0) {
            Client().setControlEncoding(pstrControlEncoding);
            LogReply();
        }
    }

    @Override
    public OutputStream getAppendFileStream(final String strFileName) {
        final String conMethodName = conClassName + "::getAppendFileStream";
        OutputStream objO = null;
        try {
            objO = Client().appendFileStream(strFileName);
        } catch (IOException e) {
            RaiseException(e, HostID(SOSVfs_E_0105.params(conMethodName)));
        }
        return objO;
    }

    @Override
    public long getFileSize(final String strFileName) {
        final String conMethodName = conClassName + "::getFileSize";
        long lngFileSize = 0;
        try {
            lngFileSize = this.size(strFileName);
        } catch (Exception e) {
            e.printStackTrace();
            RaiseException(SOSVfs_E_153.params(conMethodName, e));
        }
        return lngFileSize;
    }

    @Override
    public InputStream getInputStream(String strFileName) {
        final String conMethodName = conClassName + "::getInputStream";
        InputStream objI = null;
        try {
            if (modezSupported == true) {
            }
            strFileName = strFileName.replaceAll("\\\\", "/");
            objI = Client().retrieveFileStream(strFileName);
            if (objI == null) {
                // TODO i18n
                throw new JobSchedulerException(
                        String.format("unable to get inputstream for file '%1$s'", strFileName));
            }
        } catch (IOException e) {
            throw new JobSchedulerException(HostID(SOSVfs_E_0105.params(conMethodName)), e);
        } finally {
            LogReply();
        }
        return objI;
    }

    /**
     * Performs some post-login operations, such trying to detect server support
     * for utf8.
     *
     */
    @Override
    public void doPostLoginOperations() {
        // synchronized (lock) {

        if (objOptions.CheckServerFeatures.value() == true) { // JIRA SOSFTP-92
            sendCommand("FEAT");
            if (objFTPReply.getCode() == FTPReply.SYSTEM_STATUS) {
                String[] lines = objFTPReply.getMessages();
                for (int i = 1; i < lines.length - 1; i++) {
                    String feat = lines[i].trim().toUpperCase();
                    // REST STREAM supported?
                    if ("REST STREAM".equalsIgnoreCase(feat)) {
                        restSupported = true;
                        continue;
                    }
                    // UTF8 supported?
                    if ("UTF8".equalsIgnoreCase(feat)) {
                        utf8Supported = true;
                        Client().setControlEncoding("UTF-8");
                        continue;
                    }
                    // MLSD supported?
                    if ("MLSD".equalsIgnoreCase(feat)) {
                        mlsdSupported = true;
                        continue;
                    }
                    // MODE Z supported?
                    if ("MODE Z".equalsIgnoreCase(feat) || feat.startsWith("MODE Z ")) {
                        modezSupported = true;
                        continue;
                    }
                }
            } else {
                logger.info("no valid response for FEAT command received: " + objFTPReply.toString());
            }
            // Turn UTF 8 on (if supported).
            if (utf8Supported) {
                sendCommand("OPTS UTF8 ON");
            }
            // Data channel security.
            // if (security == SECURITY_FTPS || security == SECURITY_FTPES) {
            // Client().sendCommand("PBSZ 0");
            // LogReply();
            // Client().sendCommand("PROT P");
            // LogReply();
            //
            // if (objFTPReply.isSuccessCode()) {
            // dataChannelEncrypted = true;
            // }
            // }

            sendCommand("NOOP"); // to clear the reply string
        }
    }

    private void sendCommand(final String pstrCommand) {
        try {
            Client().sendCommand(pstrCommand);
        } catch (IOException e) {
            throw new JobSchedulerException("command failed: " + pstrCommand, e);
        }
        LogReply();
    }

    @Override
    public final String getReplyString() {
        String strT = Client().getReplyString();
        objFTPReply = new SOSFtpServerReply(strT);
        return strT;
    }

    @Override
    public boolean isConnected() {
        return Client().isConnected();
        //      Client().setSoTimeout(1200);
        //      Client().setDefaultTimeout(1200);
        //      Client().setDataTimeout(1200);
    }

    @Override
    public ISOSConnection Connect(final SOSConnection2OptionsSuperClass pobjConnectionOptions) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public OutputStream getFileOutputStream() {
        return null;
    }

    @Override
    public OutputStream getOutputStream() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public InputStream getInputStream() {
        // TODO Auto-generated method stub
        return null;
    }

}