/**
 * Execute transported batch statements on the server
 *
 * @author Nicolas de Pomereu
 */
public class ServerBatchStatementExecutorNew {
  private static boolean DEBUG = FrameworkDebug.isSet(ServerBatchStatementExecutorNew.class);

  // When executing a non-query (Prepared) Statement
  public static final String STATEMENT_NORMAL_EXECUTED = "0";

  private HttpServletRequest request = null;
  private OutputStream out = null;

  private CommonsConfigurator commonsConfigurator = null;
  private FileConfigurator fileConfigurator = null;
  private SqlConfigurator sqlConfigurator = null;

  /**
   * Constructor
   *
   * @param request the servlet http request
   * @param out the servlet output stream
   * @param fileConfigurator the FILE Configurator
   * @param commonsConfigurator the Commons Configurator
   * @param sqlConfigurator the SQL Configurator
   */
  public ServerBatchStatementExecutorNew(
      HttpServletRequest request,
      OutputStream out,
      CommonsConfigurator commonsConfigurator,
      FileConfigurator fileConfigurator,
      SqlConfigurator sqlConfigurator) {
    this.request = request;
    this.out = out;

    this.commonsConfigurator = commonsConfigurator;
    this.fileConfigurator = fileConfigurator;
    this.sqlConfigurator = sqlConfigurator;
  }

  /** Execute the Sql Action */
  public void execute() throws IOException, SQLException, IllegalArgumentException {
    String username = request.getParameter(Parameter.USERNAME);
    String connectionId = request.getParameter(ConnectionParms.CONNECTION_ID);

    String conHolderParam = request.getParameter(SqlAction.CONNECTION_HOLDER);
    String statementHolderParam = request.getParameter(SqlAction.STATEMENT_HOLDER);

    debug("SqlAction.CONNECTION_HOLDER: " + conHolderParam);
    debug("SqlAction.STATEMENT_HOLDER : " + statementHolderParam);

    Connection connection = null;

    if (connectionId.equals("0")) {
      try {
        connection = commonsConfigurator.getConnection();

        ServerSqlUtil.setConnectionProperties(conHolderParam, connection);

        if (statementHolderParam.startsWith(TransportConverter.KAWANFW_BYTES_STREAM_FILE)) {
          String fileName =
              StringUtils.substringAfter(
                  statementHolderParam, TransportConverter.KAWANFW_BYTES_STREAM_FILE);
          // Param contains only the file to read from the statements
          executeStatementsFromFile(username, fileName, connection);
        } else {
          // All statements are in single param
          executeStatementsFromList(username, statementHolderParam, connection);
        }

        if (!connection.getAutoCommit()) {
          connection.commit();
        }
      } catch (IOException e) {
        if (!connection.getAutoCommit()) {
          connection.rollback();
        }

        throw e;
      } catch (SQLException e) {
        if (!connection.getAutoCommit()) {
          connection.rollback();
        }

        throw e;
      } finally {
        // Release the connection
        ConnectionCloser.freeConnection(connection, sqlConfigurator);
      }
    } else {

      ConnectionStore connectionStore = new ConnectionStore(username, connectionId);
      connection = connectionStore.get();

      if (connection == null) {
        // out.println(TransferStatus.SEND_OK);
        // out.println(SqlReturnCode.SESSION_INVALIDATED);
        ServerSqlManager.writeLine(out, TransferStatus.SEND_OK);
        ServerSqlManager.writeLine(out, SqlReturnCode.SESSION_INVALIDATED);
        return;
      }

      if (statementHolderParam.startsWith(TransportConverter.KAWANFW_BYTES_STREAM_FILE)) {
        String fileName =
            StringUtils.substringAfter(
                statementHolderParam, TransportConverter.KAWANFW_BYTES_STREAM_FILE);
        // Param contains only the file to read from the statements
        executeStatementsFromFile(username, fileName, connection);
      } else {
        // All statements are in single param
        executeStatementsFromList(username, statementHolderParam, connection);
      }
    }
  }

  /**
   * Execute the statements from file name passed in parameter
   *
   * @param username the user username
   * @param fileName the filename containing all the statements in json format, one perline
   * @param connection the JDBC Connection
   * @throws SQLException
   * @throws IOException
   */
  private void executeStatementsFromFile(String username, String fileName, Connection connection)
      throws SQLException, IOException {

    fileName = HttpConfigurationUtil.addRootPath(fileConfigurator, username, fileName);

    File file = new File(fileName);

    if (!file.exists()) {
      throw new IOException(
          Tag.PRODUCT_PRODUCT_FAIL
              + "The file corresponding to a list of Statements does not exist on remote Server: "
              + fileName);
    }

    StatementHolder statementHolder = null;

    ServerBatchStatement serverBatchStatement =
        new ServerBatchStatement(request, out, sqlConfigurator, connection, username);

    StatementHolderListReader statementHolderListReader = null;

    try {
      statementHolderListReader = new StatementHolderListReader(file, commonsConfigurator);

      while ((statementHolder = statementHolderListReader.readLine()) != null) {
        String sqlOrder = statementHolder.getSqlOrder();
        serverBatchStatement.addBatch(sqlOrder);
      }

      serverBatchStatement.executeBatchAndClose();
    } finally {
      if (statementHolderListReader != null) {
        statementHolderListReader.close();
        statementHolderListReader = null;
      }

      serverBatchStatement = null;
    }
  }

  /**
   * Execute the statements from the parameter that contains the list of StatementHolder in JSon
   * format
   *
   * @param username the user username
   * @param statementHolderParam the statement request parameter
   * @param connection the JDBC Connection
   * @throws SQLException
   * @throws IOException
   */
  private void executeStatementsFromList(
      String username, String statementHolderParam, Connection connection)
      throws SQLException, IOException {

    List<StatementHolder> statementHolderList =
        StatementHolderListDecryptor.decryptFromJson(statementHolderParam, commonsConfigurator);

    ServerBatchStatement serverBatchStatement =
        new ServerBatchStatement(request, out, sqlConfigurator, connection, username);

    for (StatementHolder statementHolder : statementHolderList) {
      String sqlOrder = statementHolder.getSqlOrder();
      serverBatchStatement.addBatch(sqlOrder);
    }

    serverBatchStatement.executeBatchAndClose();
  }

  /**
   * Method called by children Servlest for debug purpose Println is done only if class name name is
   * in kawansoft-debug.ini
   */
  public static void debug(String s) {
    if (DEBUG) {
      ServerLogger.getLogger().log(Level.WARNING, s);
    }
  }
}
/**
 * Calls File.listFiles() or File.listFiles(FileFilter)
 *
 * @author Nicolas de Pomereu
 * @since 1.0
 */
public class FileListFilesAction {
  private static boolean DEBUG = FrameworkDebug.isSet(FileListFilesAction.class);

  /** Constructor. */
  public FileListFilesAction() {}

  /**
   * Calls File.listFiles() or File.listFiles(FileFilter) File.listFiles(FilenameFilter) remote
   * method from the client side. <br>
   *
   * @param request the http request
   * @param commonsConfigurator the commons configurator defined by the user
   * @param fileConfigurator the file configurator defined by the user
   * @param out the servlet output stream
   * @param username the client login (for security check)
   * @param filename the filename to call
   * @throws Exception
   */
  public void listFiles(
      HttpServletRequest request,
      CommonsConfigurator commonsConfigurator,
      FileConfigurator fileConfigurator,
      OutputStream out,
      String username,
      String filename)
      throws Exception {

    debug("in listFiles()");

    FileFilter fileFilter = null;
    FilenameFilter filenameFilter = null;

    fileFilter = ServerFilterUtil.buidFileFilter(request, fileConfigurator, username);
    filenameFilter = ServerFilterUtil.buildFilenameFilter(request, fileConfigurator, username);

    debug("After ServerFilterUtil.buidFileFilter");

    filename = HttpConfigurationUtil.addRootPath(fileConfigurator, username, filename);

    File file = new File(filename);
    File[] files = null;

    try {
      if (fileFilter == null && filenameFilter == null) {
        files = file.listFiles();
      } else if (fileFilter != null) {
        files = file.listFiles(fileFilter);
      } else if (filenameFilter != null) {
        files = file.listFiles(filenameFilter);
      } else {
        // Can not happen
        throw new IllegalArgumentException(
            Tag.PRODUCT_PRODUCT_FAIL + " Impossible else condition.");
      }
    } catch (IllegalArgumentException e) {
      // Necessary because Reloader wich extends ClassLoader can nor throw ClassNotFoundException
      if (e.getCause() != null && e.getCause() instanceof ClassNotFoundException) {
        throw new ClassNotFoundException(e.getCause().getMessage());
      }
    }

    if (files == null) {
      writeLine(out, TransferStatus.SEND_OK);
      writeLine(out, null);
      return;
    }

    if (files.length == 0) {
      writeLine(out, TransferStatus.SEND_OK);
      writeLine(out, "[]");
      return;
    }

    writeLine(out, TransferStatus.SEND_OK);

    for (File theFile : files) {
      String fileStr = theFile.toString();

      fileStr = ReturnFileFormatter.format(fileConfigurator, username, fileStr);

      fileStr = HtmlConverter.toHtml(fileStr);
      writeLine(out, fileStr);
    }
  }

  /**
   * Write a line of string on the servlet output stream. Will add the necessary CR_LF
   *
   * @param out the servlet output stream
   * @param s the string to write
   * @throws IOException
   */
  private void writeLine(OutputStream out, String s) throws IOException {
    out.write((s + StringUtil.CR_LF).getBytes());
  }

  private void debug(String s) {
    if (DEBUG) {
      ServerLogger.getLogger().log(Level.WARNING, s);
    }
  }
}