package sos.scheduler.ftp;
 

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import sos.net.SOSFTP;
import sos.net.SOSFTPS;
import sos.net.SOSFileTransfer;
import sos.net.SOSMail;
import sos.net.SOSSFTP;
import sos.scheduler.job.JobSchedulerJob;
import sos.spooler.Order;
import sos.spooler.Variable_set;
import sos.util.SOSFileOperations;
import sos.util.SOSSchedulerLogger;
import sos.util.SOSString;

/**
 * FTP File Transfer
 *
 @author Andreas P�schel 
 @author M�r�vet �ks�z
 */

public class JobSchedulerFTPReceive extends JobSchedulerJob {
  
  /** The FTP server will always reply the ftp error codes, 
   * see http://www.the-eggman.com/seminars/ftp_error_codes.html */
  public  static final int ERROR_CODE              = 300
  
  private SOSString        sosString               = new SOSString();
  
    
  public boolean spooler_process() {
    
    boolean      rc                              = false;    
    SOSFileTransfer  ftpClient                       = null;        
    
    
    String      protocol                         = "ftp";
    boolean     sshBasedProtocol                 = false;
    
    String       host                            = "";
    int          port                            = 21;
    
    String       user                            = "anonymous";
    String       password                        = "";
    String       account                         = "";
    
    String       transferMode                    = "binary";
    boolean      passiveMode                     = false;
    
    String       remoteDir                       = "./";
    String       localDir                        = ".";
    String       fileSpec                        = ".*";
    String       atomicSuffix                    = "";
    boolean      checkSize                       = true;
    long         checkInterval                   = 60;
    long         checkRetry                      = 0;
    boolean      overwriteFiles                  = true;
    boolean      appendFiles                     = false;
    boolean      removeFiles                     = false;
    boolean      skipTransfer                    = false;
    boolean      forceFiles                      = true;
        
    boolean      zeroByteFiles                   = true;
    boolean      zeroByteFilesStrict             = false
    boolean      zeroByteFilesRelaxed            = false;
    
    String       fileNotificationTo              = "";
    String       fileNotificationCC              = "";
    String       fileNotificationBCC             = "";
    String       fileNotificationSubject         = "";
    String       fileNotificationBody            = "";
    
    String       fileZeroByteNotificationTo      = "";
    String       fileZeroByteNotificationCC      = "";
    String       fileZeroByteNotificationBCC     = "";
    String       fileZeroByteNotificationSubject = "";
    String       fileZeroByteNotificationBody    = "";
    
    boolean      isLoggedIn                      = false;
    Vector       transferFileList                = new Vector();
    HashMap      checkFileList                   = new HashMap();
    Variable_set params                          = null;
    
    String       replacing                       = null;
    String       replacement                     = null;  
    
    boolean      recursive                       = false;
    
    int          pollTimeout                     = 0;
    int          pollIntervall                   = 60;
    int          pollMinFiles                    = 1;
    String       pollFilesErrorState            = "";
    
    String       filePath                        = "";
    boolean      isFilePath                      = false;
    
    // alternative parameters
    String       alternativeHost                 = "";
    int          alternativePort                 = 0;
    String       alternativeUser                 = ""
    String       alternativePassword             = "";
    String       alternativeAccount              = "";
    String       alternativeRemoteDir            = "";
    boolean      alternativePassiveMode          = false;
    String       alternativeTransferMode         = "binary";
    
    // Parallel File Transfer
    boolean      parallelTransfer                = false;
        String       parallelTransferCheckSetback    = "00:00:60";
    int          parallelTransferCheckRetry      = 60
    
    // Hilfsvariable: wenn gesetzt, dann handelt es sich um einen Wiederholungsauftrag. Also keine Dateien abfrufen 
    boolean      checkParallel              = false;    
    boolean      orderSelfDestruct          = false;
    
    // Variablen f�r ssh-basierte Transferprotokolle
      /** optional proxy configuration */
      String proxyHost                  = "";      
      int proxyPort                     = 0;      
      String proxyUser                  = "";
      String proxyPassword              = "";
      /** authentication method: publickey, password */
      String authenticationMethod       = "publickey";
      /** key file: ~/.ssh/id_rsa or ~/.ssh/id_dsa */
      String authenticationFilename     = "";
      
      
    
    try {   
      this.setLogger(new SOSSchedulerLogger(spooler_log));
      int iSetbackCount = 1;
      try // to get the job parameters and order parameters
        params = spooler.create_variable_set();
        if (spooler_task.params() != nullparams.merge(spooler_task.params());
        if (spooler_job.order_queue() != null && spooler_task.order().params() != null) {
          params.merge(spooler_task.order().params());
          // initialize setback counter for possible polling
          Variable_set orderParams = spooler_task.order().params();
          String setbackCount = orderParams.value("setback_count");
          getLogger().debug9("setback_count read: "+setbackCount);
          
          if (setbackCount!=null && setbackCount.length()>0){
            iSetbackCount = Integer.parseInt(setbackCount);
            iSetbackCount++;
          }          
          orderParams.set_var("setback_count"""+iSetbackCount);
        }
        
        if (params.var("ftp_protocol"!= null && params.var("ftp_protocol").length() 0
          protocol = params.var("ftp_protocol");
        if (protocol.equalsIgnoreCase("sftp")){
          sshBasedProtocol = true;
          //use other defaults
          port = 22;
        }
        
        if (params.var("ftp_host"!= null && params.var("ftp_host").length() 0)
          host = params.var("ftp_host");
        
        if (params.var("ftp_port"!= null && params.var("ftp_port").length() 0) {
          try {
            port = Integer.parseInt(params.var("ftp_port"));
          catch (Exception e) {
            throw new Exception("illegal value for parameter [ftp_port]: " + params.var("ftp_port"));
          }
        }
        
        if (params.var("ftp_user"!= null && params.var("ftp_user").length() 0)
          user = params.var("ftp_user");
        if (params.var("ftp_password"!= null && params.var("ftp_password").length() 0)
          password = params.var("ftp_password");
        if (params.var("ftp_account"!= null && params.var("ftp_account").length() 0)
          account = params.var("ftp_account");
        
        if (params.var("ftp_transfer_mode"!= null && params.var("ftp_transfer_mode").length() 0)
          transferMode = params.var("ftp_transfer_mode");
        
        if (params.var("ftp_passive_mode"!= null && params.var("ftp_passive_mode").length() 0)
          passiveMode = (params.var("ftp_passive_mode").equals("1"||
              params.var("ftp_passive_mode").equalsIgnoreCase("true"||
              params.var("ftp_passive_mode").equalsIgnoreCase("yes")true false);
        
        if (params.var("ftp_remote_dir"!= null && params.var("ftp_remote_dir").length() 0)
          remoteDir = params.var("ftp_remote_dir");
        
        if (params.var("ftp_local_dir"!= null && params.var("ftp_local_dir").length() 0)
          localDir = params.var("ftp_local_dir");
        
        if (params.var("ftp_file_spec"!= null && params.var("ftp_file_spec").length() 0)
          fileSpec = params.var("ftp_file_spec");
        
        if (params.var("ftp_atomic_suffix"!= null && params.var("ftp_atomic_suffix").length() 0)
          atomicSuffix = params.var("ftp_atomic_suffix");
        
        
        if (params.var("ftp_check_size"!= null && params.var("ftp_check_size").length() 0)
          checkSize = (!params.var("ftp_check_size").equals("1"
              && !params.var("ftp_check_size").equalsIgnoreCase("true"
              && !params.var("ftp_check_size").equalsIgnoreCase("yes"false true);
        
        if (params.var("ftp_check_interval"!= null && params.var("ftp_check_interval").length() 0) {
          try {
            checkInterval = Long.parseLong(params.var("ftp_check_interval"));
          catch (Exception e) {
            throw new Exception("illegal value for parameter [ftp_check_interval]: " + params.var("ftp_check_interval"));
          }
        }
        
        if (params.var("ftp_check_retry"!= null && params.var("ftp_check_retry").length() 0) {
          try {
            checkRetry = Long.parseLong(params.var("ftp_check_retry"));
          catch (Exception e) {
            throw new Exception("illegal value for parameter [ftp_check_retry]: " + params.var("ftp_check_retry"));
          }
        }
        
        if (params.var("ftp_overwrite_files"!= null && params.var("ftp_overwrite_files").length() 0)
          overwriteFiles = (!params.var("ftp_overwrite_files").equals("1"
              && !params.var("ftp_overwrite_files").equalsIgnoreCase("true"
              && !params.var("ftp_overwrite_files").equalsIgnoreCase("yes"false true);
        
        if (params.var("ftp_append_files"!= null && params.var("ftp_append_files").length() 0)
          appendFiles = (params.var("ftp_append_files").equals("1"
              || params.var("ftp_append_files").equalsIgnoreCase("true"
              || params.var("ftp_append_files").equalsIgnoreCase("yes"true false);
        
        if (params.var("ftp_remove_files"!= null && params.var("ftp_remove_files").length() 0)
          removeFiles = (params.var("ftp_remove_files").equals("1"
              || params.var("ftp_remove_files").equalsIgnoreCase("true"
              || params.var("ftp_remove_files").equalsIgnoreCase("yes"true false);
        
        if (params.var("ftp_skip_transfer"!= null && params.var("ftp_skip_transfer").length() 0)
          skipTransfer = (params.var("ftp_skip_transfer").equals("1"
              || params.var("ftp_skip_transfer").equalsIgnoreCase("true"
              || params.var("ftp_skip_transfer").equalsIgnoreCase("yes"true false);
        
        if (params.var("ftp_force_files"!= null && params.var("ftp_force_files").length() 0)
          forceFiles = (!params.var("ftp_force_files").equals("1"
              && !params.var("ftp_force_files").equalsIgnoreCase("true"
              && !params.var("ftp_force_files").equalsIgnoreCase("yes"false true);
        
                
        if (params.var("ftp_file_zero_byte_transfer"!= null && params.var("ftp_file_zero_byte_transfer").length() 0) {
          if (params.var("ftp_file_zero_byte_transfer").equals("1"
              || params.var("ftp_file_zero_byte_transfer").equalsIgnoreCase("true"
              || params.var("ftp_file_zero_byte_transfer").equalsIgnoreCase("yes")) {
            zeroByteFiles = true;
            zeroByteFilesStrict = false;
          else if (params.var("ftp_file_zero_byte_transfer").equalsIgnoreCase("strict")) {
            zeroByteFiles = false;
            zeroByteFilesStrict = true;
          else if (params.var("ftp_file_zero_byte_transfer").equalsIgnoreCase("relaxed")) {
            zeroByteFiles = false;
            zeroByteFilesStrict = false;
            zeroByteFilesRelaxed = true;
          else {
            zeroByteFiles = false;
            zeroByteFilesStrict = false;
          }
        }
        
        if (params.var("ftp_file_notification_to"!= null && params.var("ftp_file_notification_to").length() 0) {
          fileNotificationTo = params.var("ftp_file_notification_to");
        }
        
        if (params.var("ftp_file_notification_cc"!= null && params.var("ftp_file_notification_cc").length() 0) {
          fileNotificationCC = params.var("ftp_file_notification_cc");
        }
        
        if (params.var("ftp_file_notification_bcc"!= null && params.var("ftp_file_notification_bcc").length() 0) {
          fileNotificationBCC = params.var("ftp_file_notification_bcc");
        }
        
        if (params.var("ftp_file_notification_subject"!= null && params.var("ftp_file_notification_subject").length() 0) {
          fileNotificationSubject = params.var("ftp_file_notification_subject");
        }
        
        if (params.var("ftp_file_notification_body"!= null && params.var("ftp_file_notification_body").length() 0) {
          fileNotificationBody = params.var("ftp_file_notification_body");
        }
        
        
        if (params.var("ftp_file_zero_byte_notification_to"!= null && params.var("ftp_file_zero_byte_notification_to").length() 0) {
          fileZeroByteNotificationTo = params.var("ftp_file_zero_byte_notification_to");
        }
        
        if (params.var("ftp_file_zero_byte_notification_cc"!= null && params.var("ftp_file_zero_byte_notification_cc").length() 0) {
          fileZeroByteNotificationCC = params.var("ftp_file_zero_byte_notification_cc");
        }
        
        if (params.var("ftp_file_zero_byte_notification_bcc"!= null && params.var("ftp_file_zero_byte_notification_bcc").length() 0) {
          fileZeroByteNotificationBCC = params.var("ftp_file_zero_byte_notification_bcc");
        }
        
        if (params.var("ftp_file_zero_byte_notification_subject"!= null && params.var("ftp_file_zero_byte_notification_subject").length() 0) {
          fileZeroByteNotificationSubject = params.var("ftp_file_zero_byte_notification_subject");
        }
        
        if (params.var("ftp_file_zero_byte_notification_body"!= null && params.var("ftp_file_zero_byte_notification_body").length() 0) {
          fileZeroByteNotificationBody = params.var("ftp_file_zero_byte_notification_body");
        }
        
        if params.value("replacing")!=null && params.value("replacing").length()>) {        
          replacing = params.value("replacing");            
        }
        
        if params.value("replacement")!=null && params.value("replacement").length()>) {        
          replacement = params.value("replacement");            
        }    
        
        if params.value("ftp_recursive")!=null && params.value("ftp_recursive").length()>) {  
          String sRecursive = "";
          sRecursive = params.value("ftp_recursive");
          recursive = sosString.parseToBoolean(sRecursive);
        }  
        
        if replacing != null && replacement == null ) {
          throw new Exception("job parameter is missing for specified parameter [replacing]: [replacement]");
        }
        
        if replacing == null && replacement != null ) {
          throw new Exception("job parameter is missing for specified parameter [replacement]: [replacing]");
        }
        
        if params.value("ftp_poll_timeout")!=null && params.value("ftp_poll_timeout").length()>) {        
          pollTimeout = Integer.parseInt(params.value("ftp_poll_timeout"));            
        }
        
        if params.value("ftp_poll_interval")!=null && params.value("ftp_poll_interval").length()>) {        
          pollIntervall = Integer.parseInt(params.value("ftp_poll_interval"));            
        }
        
        if params.value("ftp_poll_minfiles")!=null && params.value("ftp_poll_minfiles").length()>) {        
          pollMinFiles = Integer.parseInt(params.value("ftp_poll_minfiles"));            
        }
        
        if (params.var("ftp_poll_error_state"!= null && params.var("ftp_poll_error_state").length() 0)
          pollFilesErrorState = params.var("ftp_poll_error_state");
        
        // alternative parameters
        if (params.var("ftp_alternative_host"!= null && params.var("ftp_alternative_host").length() 0
          alternativeHost = params.var("ftp_alternative_host");              
        
        if (params.var("ftp_alternative_port"!= null && params.var("ftp_alternative_port").length() 0)
          alternativePort = Integer.parseInt(params.var("ftp_alternative_port"));
        
        if (params.var("ftp_alternative_password"!= null && params.var("ftp_alternative_password").length() 0)
          alternativePassword = params.var("ftp_alternative_password");
        
        if (params.var("ftp_alternative_user"!= null && params.var("ftp_alternative_user").length() 0)
          alternativeUser = params.var("ftp_alternative_user");
        
        if (params.var("ftp_alternative_account"!= null && params.var("ftp_alternative_account").length() 0)
          alternativeAccount = params.var("ftp_alternative_account");
        
        if (params.var("ftp_alternative_remote_dir"!= null && params.var("ftp_alternative_remote_dir").length() 0)
          alternativeRemoteDir = params.var("ftp_alternative_remote_dir");
        
        if (params.var("ftp_alternative_passive_mode"!= null && params.var("ftp_alternative_passive_mode").length() 0)
          alternativePassiveMode = (params.var("ftp_alternative_passive_mode").equals("1"true false);
        
        if (params.var("ftp_alternative_transfer_mode"!= null && params.var("ftp_alternative_transfer_mode").length() 0)
          alternativeTransferMode = params.var("ftp_alternative_transfer_mode");
        
                // parameters for parallel transfer
        if (params.var("ftp_parallel"!= null && params.var("ftp_parallel").length() 0)
          parallelTransfer = sosString.parseToBoolean(sosString.parseToString(params.var("ftp_parallel")));
                
                if (params.var("ftp_parallel_check_setback"!= null && params.var("ftp_parallel_check_setback").length() 0)
                    parallelTransferCheckSetback = params.var("ftp_parallel_check_setback");

                if (params.var("ftp_parallel_check_retry"!= null && params.var("ftp_parallel_check_retry").length() 0) {
                    try {
                        parallelTransferCheckRetry = Integer.parseInt(params.var("ftp_parallel_check_retry"));
                    catch (Exception e) {
                        throw new Exception("illegal value for parameter [ftp_parallel_check_retry]: " + params.var("ftp_parallel_check_retry"));
                    }
                }
        
                // implicit parameters
        if(params.var("ftp_check_parallel"!= null && params.var("ftp_check_parallel").length() 0)
          checkParallel = sosString.parseToBoolean(sosString.parseToString(params.var("ftp_check_parallel")));
      
        if(params.var("ftp_order_self_destruct"!= null && params.var("ftp_order_self_destruct").length() 0)
          orderSelfDestruct = sosString.parseToBoolean(sosString.parseToString(params.var("ftp_order_self_destruct")));
          
        if (sshBasedProtocol){
          // parameters for ssh-based protocols
          if (params.value("ssh_proxy_host"!= null && params.value("ssh_proxy_host").toString().length() 0) {
            proxyHost=params.value("ssh_proxy_host");                  
          

          if (params.value("ssh_proxy_port"!= null && params.value("ssh_proxy_port").length() 0) {
            try {
              proxyPort=(Integer.parseInt(params.value("ssh_proxy_port")));                     
            catch (Exception ex) {
              throw new Exception("illegal non-numeric value for parameter [ssh_proxy_port]: " + params.value("ssh_proxy_port"));
            }
          else {
            proxyPort=3128;
          }

          if (params.value("ssh_proxy_user"!= null && params.value("ssh_proxy_user").length() 0) {
            proxyUser=(params.value("ssh_proxy_user"));                 
          

          if (params.value("ssh_proxy_password"!= null && params.value("ssh_proxy_password").length()