All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.cp4waiops.connectors.sdk.EDBPostgresHelper Maven / Gradle / Ivy

The newest version!
package com.ibm.cp4waiops.connectors.sdk;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;

public class EDBPostgresHelper {

    static final Logger logger = LogManager.getLogger(EDBPostgresHelper.class.getName());

    private String EDB_DRIVER_CLASS_NAME = "org.postgresql.Driver";
    private int EDB_INITIALSIZE_DB = 1;
    private int EDB_MAXTOTAL_DB = 5;
    private BasicDataSource EDBBasicDS;
    private String edbpostgresHost = "";
    private String edbpostgresPort = "";
    private String edbpostgresUsername = "";
    private String edbpostgresPassword = "";
    private String edbpostgresDbname = "";
    private Boolean foundEDBPostgresEnv = false;

    public static final String DEFAULT_CONNECTIONS_TABLE_NAME = "checkpointtable";
    public static final String DEFAULT_QUERY_KEY = "connection_id";

    public Boolean setEDBPostgresConnection() {
        Boolean success = false;
        // Read EDB Postgres env vars
        if (readEDBPostgtresSecret().booleanValue()) {
            // Setting EDB postgres configuration
            if (!this.edbpostgresHost.isEmpty() && !this.edbpostgresPort.isEmpty()
                    && !this.edbpostgresUsername.isEmpty() && !this.edbpostgresPassword.isEmpty()
                    && !this.edbpostgresDbname.isEmpty()) {
                String URL_EDB_DB = "jdbc:postgresql://" + this.edbpostgresHost + ":" + this.edbpostgresPort + "/"
                        + this.edbpostgresDbname;
                logger.info("URL_EDB_DB - " + URL_EDB_DB);

                EDBBasicDS = new BasicDataSource();
                EDBBasicDS.setDriverClassName(EDB_DRIVER_CLASS_NAME);
                EDBBasicDS.setUrl(URL_EDB_DB);
                EDBBasicDS.setUsername(this.edbpostgresUsername);
                EDBBasicDS.setPassword(this.edbpostgresPassword);
                EDBBasicDS.setDefaultQueryTimeout(300); // 5 min timeout
                // The initial number of connections that are created when the pool is started.
                EDBBasicDS.setInitialSize(EDB_INITIALSIZE_DB);
                // The maximum number of active connections that can be allocated from this pool
                // at the same time
                EDBBasicDS.setMaxTotal(EDB_MAXTOTAL_DB);
                success = true;
            } else {
                logger.error("Something is wrong with Postgres secret as URL_EDB_DB has some credentials missing");
            }
        } else {
            logger.error("Something is wrong with EDB Postgres environment has some credentials missing");
        }
        return success;
    }

    private Boolean readEDBPostgtresSecret() {

        Boolean success = false;

        logger.info("Reading EDB postgres secret....");

        if (System.getenv("EDB_POSTGRES_SECRET_PATH") != null && !System.getenv("EDB_POSTGRES_SECRET_PATH").isEmpty()) {

            String edbSecretPath = System.getenv("EDB_POSTGRES_SECRET_PATH");

            logger.info("EDB postgres secret path is " + edbSecretPath);

            String edbPostgresHost = readSecret(edbSecretPath + "/host");
            String edbPostgresPort = readSecret(edbSecretPath + "/port");
            String edbPostgresUsername = readSecret(edbSecretPath + "/username");
            String edbPostgresPassword = readSecret(edbSecretPath + "/password");
            String edbPostgresDbName = readSecret(edbSecretPath + "/dbname");

            setEDBPostgresHost(new String(edbPostgresHost));

            setEDBPostgresPort(new String(edbPostgresPort));

            setEDBPostgresUsername(new String(edbPostgresUsername));

            setEDBPostgresPassword(new String(edbPostgresPassword));

            setEDBPostgresDbname(new String(edbPostgresDbName));

            setFoundEDBPostgresEnv(true);
            success = true;
        } else {
            logger.error("Failed to get the EDB Postgres DB environments: EDB_POSTGRES_SECRET_PATH");
            throw new EDBPostgresException("Failed to get the EDB Postgres DB environments: EDB_POSTGRES_SECRET_PATH");
        }

        return success;
    }

    public Boolean createInitialTable(String sqlTable, String sqlCreateStatement) {
        Boolean success = false;
        Connection edb_connection = null;

        logger.info("Creating sql table : " + sqlTable + " if not exist...");

        PreparedStatement prepStmt = null;

        try {
            DataSource edb_ds = this.EDBBasicDS;
            edb_connection = edb_ds.getConnection();

            logger.info("edb_ds - " + edb_ds);
            logger.info("edb_connection - " + edb_connection);

            prepStmt = edb_connection.prepareStatement(sqlCreateStatement);

            if (!prepStmt.execute()) {
                success = true;
                logger.info("Successfully created checkPointTable");
            } else {
                return false;
            }
        } catch (Exception e) {
            logger.error("Error while creating " + sqlTable + " for EDB Postgres");
            logger.error(e.getClass().getName() + ": " + e.getMessage());
            throw new EDBPostgresException("Failed to create a " + sqlTable + " table - " + e.getMessage());
        } finally {
            if (edb_connection != null) {
                try {
                    prepStmt.close();
                    edb_connection.close();
                } catch (SQLException e) {
                    logger.error("Failed to close db connection ", e);
                }
            }
        }

        return success;
    }

    /**
     * Deletes the connection row from the specified sqlTable using {@code 'WHERE connectionKey = connectionUID'} as the
     * query condition.
     * 
     * @param sqlTable
     * @param connectionKey
     * @param connectionUID
     * 
     * @return True if deletion executed successfully.
     */
    public Boolean deleteConnectionFromEDBPostgres(String sqlTable, String connectionKey, String connectionUID) {
        Boolean success = false;
        Connection edb_connection = null;
        PreparedStatement prepStmt = null;

        String deleteSQL = String.format("DELETE FROM public.\"%s\" WHERE %s = ?", sqlTable, connectionKey);

        try {
            DataSource edb_ds = this.EDBBasicDS;
            edb_connection = edb_ds.getConnection();
            prepStmt = edb_connection.prepareStatement(deleteSQL);
            prepStmt.setString(1, connectionUID);
            int rowsUpdated = prepStmt.executeUpdate();

            if (rowsUpdated > 0) {

                logger.info("Connection has been removed successfully! connection_id - " + connectionUID + " from "
                        + sqlTable + " table");

                success = true;
            } else {

                logger.error("Failed to remove connection! connection_id - " + connectionUID + " from " + sqlTable
                        + " table");
            }

        } catch (SQLException e) {
            logger.error("Failed to delete connection from SQL query ", e);
        } finally {
            if (edb_connection != null) {
                try {
                    prepStmt.close();
                    edb_connection.close();
                } catch (SQLException e) {
                    logger.error("Failed to close db connection ", e);
                }
            }
        }

        return success;
    }

    /**
     * Deletes the connection from the default {@value #DEFAULT_CONNECTIONS_TABLE_NAME} table using
     * {@value #DEFAULT_QUERY_KEY} as the query key and {@code connectionUID} as the value
     * 
     * @param connectionUID
     * 
     * @return True if deletion executed successfully.
     */
    public Boolean deleteConnectionFromEDBPostgres(String connectionUID) {
        return deleteConnectionFromEDBPostgres(DEFAULT_CONNECTIONS_TABLE_NAME, DEFAULT_QUERY_KEY, connectionUID);
    }

    public Integer readCheckPointFromEDBPostgres(String connectionUID) {

        Connection connection = null;
        PreparedStatement prepStmt = null;
        ResultSet rs = null;
        Integer checkpoint_ts = 0;

        logger.info("readCheckPointFromPostgres() is triggered to read checkpoint value from postgres");

        String querySqlStatement = String.format("SELECT checkpoint_ts from %s WHERE %s = ?",
                DEFAULT_CONNECTIONS_TABLE_NAME, DEFAULT_QUERY_KEY);

        try {
            DataSource ds = this.EDBBasicDS;
            connection = ds.getConnection();

            logger.info("edb_ds - " + ds);
            logger.info("edb_connection - " + connection);

            prepStmt = connection.prepareStatement(querySqlStatement);

            prepStmt.setString(1, connectionUID);

            rs = prepStmt.executeQuery();

            if (rs.next()) {
                checkpoint_ts = rs.getInt("checkpoint_ts");
            } else {
                logger.warn("Checkpoint SQL query return empty result for connection_id - " + connectionUID
                        + " or this is a new historical data");
            }

        } catch (SQLException e) {
            logger.error("Failed to read checkpoint from SQL query ", e);
            throw new EDBPostgresException("Failed to read checkpoint from SQL query - " + e.getMessage());
        } finally {
            if (connection != null) {
                try {
                    prepStmt.close();
                    rs.close();
                    connection.close();
                } catch (SQLException e) {
                    logger.error("Failed to close db connection ", e);
                }
            }
        }

        return checkpoint_ts;
    }

    public Boolean saveCheckPointToEDBPostgres(String connection_id, String connection_type, String connection_name,
            JSONObject connection_config, Long checkpoint_ts) {
        Connection connection = null;
        Boolean success = false;
        PreparedStatement prepStmt = null;
        JSONObject connection_config_mask = new JSONObject();

        logger.info("A checkpoint is triggered to save : " + checkpoint_ts);

        connection_config_mask = maskPasswordAndKeys(connection_config);

        String createConnectionSql = String.format("INSERT INTO public.\"%s\" "
                + "(connection_id, connection_type, connection_name, configuration, checkpoint_ts, last_update_ts) "
                + "VALUES (?,?,?,?::json,?,?) ON CONFLICT(connection_id) DO UPDATE SET connection_type= EXCLUDED.connection_type, connection_name= EXCLUDED.connection_name, configuration= EXCLUDED.configuration, checkpoint_ts = EXCLUDED.checkpoint_ts, last_update_ts = EXCLUDED.last_update_ts;",
                DEFAULT_CONNECTIONS_TABLE_NAME);

        try {
            DataSource ds = this.EDBBasicDS;
            connection = ds.getConnection();

            prepStmt = connection.prepareStatement(createConnectionSql);

            Long last_update_ts = Instant.now().getEpochSecond();

            prepStmt.setString(1, !connection_id.isEmpty() ? connection_id.toString() : "empty_conn_id");
            prepStmt.setString(2, !connection_type.isEmpty() ? connection_type.toString() : "empty_type");
            prepStmt.setString(3, !connection_name.isEmpty() ? connection_name.toString() : "empty_name");
            prepStmt.setString(4,
                    !connection_config_mask.isEmpty() ? connection_config_mask.toString() : "empty_config");
            prepStmt.setLong(5, checkpoint_ts);
            prepStmt.setLong(6, last_update_ts);

            int rowsInserted = prepStmt.executeUpdate();

            if (rowsInserted > 0) {

                logger.info("A checkpoint was successfully saved! connection_id - " + connection_id.toString());
                success = true;

            } else {
                logger.error("Failed to save checkpoint ! connection_id - " + connection_id.toString());
            }

        } catch (SQLException e) {
            logger.error("Failed to save checkpoint from SQL query ", e);
            throw new EDBPostgresException("Failed to save checkpoint from SQL query - " + e.getMessage());
        } finally {
            if (connection != null) {
                try {
                    prepStmt.close();
                    connection.close();
                } catch (SQLException e) {
                    logger.error("Failed to close db connection ", e);
                }
            }
        }

        return success;
    }

    public String readSecret(String file) {
        String returnStr = "";
        try {
            File secrets_file = new File(file);
            if (!secrets_file.exists()) {
                logger.warn("No Secret File Found at " + file);
                return null;
            } else {
                // open input stream from /etc/zeno/secrets/edbpostgresif it exists
                // The secret file should be a single line of text with the full API Key in it
                FileInputStream inStream = new FileInputStream(secrets_file);
                BufferedReader br = new BufferedReader(new InputStreamReader(inStream));
                logger.info("Read Secret from " + file);
                returnStr = br.readLine();
            }
        } catch (Exception e) {
            logger.error("Failed to read secret from " + file, e);
            returnStr = null;
            throw new EDBPostgresException("Failed to read secret for EDB Postgres - " + e.getMessage());
        }
        return returnStr;
    }

    public static JSONObject maskPasswordAndKeys(JSONObject job) {
        return Util.maskSensitiveInfo(job);
    }

    public Boolean getFoundEDBPostgresEnv() {
        return foundEDBPostgresEnv;
    }

    public void setFoundEDBPostgresEnv(Boolean foundEDBPostgresEnv) {
        this.foundEDBPostgresEnv = foundEDBPostgresEnv;
    }

    public void setEDBDatasource(DataSource EDBBasicDS) {
        this.EDBBasicDS = (BasicDataSource) EDBBasicDS;
    }

    public DataSource getEDBDatasource() {
        return this.EDBBasicDS;
    }

    public void setEDBPostgresHost(String edbpostgresHost) {
        this.edbpostgresHost = edbpostgresHost;
    }

    public String getEDBPostgresHost() {
        return edbpostgresHost;
    }

    public void setEDBPostgresPort(String edbpostgresPort) {
        this.edbpostgresPort = edbpostgresPort;
    }

    public String getEDBPostgresPort() {
        return edbpostgresPort;
    }

    public void setEDBPostgresUsername(String edbpostgresUsername) {
        this.edbpostgresUsername = edbpostgresUsername;
    }

    public String getEDBPostgresUsername() {
        return edbpostgresUsername;
    }

    public void setEDBPostgresPassword(String edbpostgresPassword) {
        this.edbpostgresPassword = edbpostgresPassword;
    }

    public String getEDBPostgresPassword() {
        return edbpostgresPassword;
    }

    public void setEDBPostgresDbname(String edbpostgresDbname) {
        this.edbpostgresDbname = edbpostgresDbname;
    }

    public String getEDBPostgresDbname() {
        return edbpostgresDbname;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy