#!/bin/bash

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Ldap Synchronization Connector provides tools to synchronize electronic
# identities from a list of data sources including any database with a JDBC
# connector, another LDAP directory, flat files...
#
# LSC automatically embeds HSQLDB library. So, this script can:
# - Create a table from a CSV file header in a HSQLDB database;
# - Inject CSV data into a HSQLDB database;
# - Read data from a HSQLDB database table.
#
# ---------------------------------------------------------------------------------
#
# Copyright (c) 2008 - 2025 LSC Project 
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice, this
#     list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
#   * Neither the name of the LSC Project nor the names of its contributors may be
#     used to endorse or promote products derived from this software without
#     specific prior written permission.
#
# 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.
#
#       (c) 2008 - 2025 LSC Project
#   Sebastien Bahloul <seb@lsc-project.org>
#   Thomas Chemineau <thomas@lsc-project.org>
#   Jonathan Clarke <jon@lsc-project.org>
#   Remy-Christophe Schermesser <rcs@lsc-project.org>
#   David Coutadeur <david.coutadeur@gmail.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ---------------------------------------------------------------------------------
# CONFIGURATION
# ---------------------------------------------------------------------------------

# work out where LSC sample lives
SAMPLE_HOME=$(dirname "${BASH_SOURCE}")/..
if [ ${SAMPLE_HOME:0:1} != "/" ] ; then
        SAMPLE_HOME="${PWD}/${SAMPLE_HOME}"
fi
CONFIGPATH="${SAMPLE_HOME}/etc"

LSC_LIB_DIR="${SAMPLE_HOME}/../../lib"
LSC_BIN_DIR="${SAMPLE_HOME}/../../bin"

# HSQLDB jar file
[ -z "$HSQLDB_LIB" -a -e "${LSC_LIB_DIR}"/hsqldb*.jar ] && HSQLDB_LIB=$( readlink -f "${LSC_LIB_DIR}"/hsqldb*.jar )
[ -z "$HSQLDB_LIB" ] && echo "hsqldb driver (hsqldb*.jar) is missing" && exit 1
# Temporary directory so that HSQLDB server could store files
HSQLDB_DIR=/tmp/lsc/hsqldb
# HSQLDB configuration file
HSQLDB_RC=$SAMPLE_HOME/etc/hsqldb.rc
# HSQLDB server properties file
HSQLDB_PROP=$SAMPLE_HOME/etc/server.properties
# Table name
HSQLDB_TABLE=userdata
HSQLDB_TABLEDEF="ID VARCHAR,UID VARCHAR,MAIL VARCHAR,MAIL_LOWER VARCHAR,LAST_UPDATE TIMESTAMP, STATUS BOOLEAN, ENDOFVALIDITY VARCHAR,SN VARCHAR,CN VARCHAR,GIVENNAME VARCHAR,O VARCHAR,ADDRESS VARCHAR,TELEPHONENUMBER VARCHAR,CARLICENSE VARCHAR"
# Default CSV separator
CSV_SEPARATOR=";"

# ---------------------------------------------------------------------------------
# FUNCTIONS
# ---------------------------------------------------------------------------------

#
# Drop all data from the HSQLDB instance.
#
data_drop()
{
  hsqldb_sqlQuery "DROP TABLE ${HSQLDB_TABLE};"
}

#
# Create table in the HSQLDB instance.
#
data_create()
{
	hsqldb_sqlQuery "CREATE TABLE ${HSQLDB_TABLE} (${HSQLDB_TABLEDEF});"
}

#
# Show data from the HSQLDB instance.
#
data_show()
{
  hsqldb_sqlQuery "SELECT * FROM ${HSQLDB_TABLE};"
}

#
# Remove all data on disk that have been created by an hsqldb server. No checks
# on a running process are performed, so be carefull.
#
hsqldb_cleanData()
{
  oldpwd=`pwd`
  cd ${HSQLDB_DIR} > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    rm -f *
    cd ..
    rmdir `basename "${HSQLDB_DIR}"`
  fi
  cd ${oldpwd}
}

#
# Perform a SQL query on the running HSQLDB instance. No checks on a running
# process are performed, so be carefull.
#
hsqldb_sqlQuery()
{
  # $1 : sql query
        #echo "Run hsqldb_sqlQuery: $1"
	# check if we have java executable
	get_java

	"${JAVA_COMMAND}" -jar "$HSQLDB_LIB" --rcFile "$HSQLDB_RC" --sql "$1" lscdb
	erg=$?
	if [ $erg -eq 0 ]; then
		echo "Command executed successfully"
	fi
	exit $erg
}

# Determine where the java exectuable is
function get_java() {
    # Do we have a JAVA_HOME environment variable?
    if [ "z" != "z${JAVA_HOME}" ]; then
        JAVA_COMMAND="${JAVA_HOME}/bin/java"
        return
    fi  

    # Try java command on PATH as an alternative
    JAVA_COMMAND="$(which java 2>/dev/null)"
    if [ -e "$JAVA_COMMAND" ]; then return; fi

    # Nothing seems approprite, warn and exit
    log "No java executable found on PATH or in JAVA_HOME! Aborting."
    log "Define JAVA_HOME or adjust your PATH variable to include java."
    exit 2
}

run_java_command()
{
        # check if we have java executable
        get_java

        for jar in "${LSC_LIB_DIR}"/*.jar; do
                LDAPCP="$LDAPCP:$jar"
        done

        "${JAVA_COMMAND}" \
                -cp "$LDAPCP" \
                --add-exports java.base/sun.security.tools.keytool=ALL-UNNAMED \
                --add-exports java.base/sun.security.x509=ALL-UNNAMED $1 $2 $3 $4 $5
}

start_ldap() {
	echo "Starting LDAP server on ldap://localhost:33389/ ..."
	run_java_command "org.lsc.opendj.LdapServer -a -f ${CONFIGPATH}"
}

start_hsql() {
	echo "Starting HSQL server on localhost ..."
	run_java_command "org.hsqldb.Server" -database.0 "file:/tmp/hsqldb/ldap2sql" -dbname.0 lscdb 
}

stop_hsql() {
	run_java_command "org.hsqldb.util.ShutdownServer" -url "jdbc:hsqldb:hsql://localhost/lscdb" 
}

start_dbtool() {
	echo "Starting HSQL Database Manager ..."
	run_java_command "org.hsqldb.util.DatabaseManager" -url "jdbc:hsqldb:hsql://localhost/lscdb"
}
run() {
	SYNCTASK=$1
	if [ -z "$SYNCTASK" ]; then
		SYNCTASK=all
	fi
	CLEANTASK=$2
	if [ -n "$CLEANTASK" ]; then
		CLEANTASK="--clean $CLEANTASK"
	fi
	
	command="\"${SAMPLE_HOME}/../../bin/lsc\" --config \"${CONFIGPATH}\" -t 1 --synchronize ${SYNCTASK} ${CLEANTASK}"
	echo "Running $command"
	eval "${command}"
}

# ---------------------------------------------------------------------------------
# MAIN
# ---------------------------------------------------------------------------------

# -- Check script parameters --

ACTIONS=""

case "$1" in
  "--drop")
    ACTIONS="$ACTIONS dropdata"
    shift
    ;;
  "--create")
    ACTIONS="$ACTIONS createdata"
    shift
    ;;
  "--show")
    ACTIONS="$ACTIONS showdata"
    shift
    ;;
  "--sql")
    ACTIONS="$ACTIONS sql"
    shift
    SQL_COMMAND="$1"
    shift
    ;;
  "--dbtool")
    ACTIONS="$ACTIONS startdbtool"
    shift
    ;;
  "--start-ldap-server")
    ACTIONS="$ACTIONS startldap"
	shift
	;;
  "--start-hsql-server")
    ACTIONS="$ACTIONS starthsql"
	shift
	;;
  "--stop-hsql-server")
    ACTIONS="$ACTIONS stophsql"
!	shift
	;;
  "--run")
	run LDAP2JDBCTask LDAP2JDBCTask
	shift
	;;
  "--set-ext-id")
	run SetExtIdTask
	shift
	;;
  "--clean")
	ACTIONS="$ACTIONS cleandata cleanldapdata"
	shift
	;;
  "--help"|*)
    echo ""
    echo " $0 <option>"
    echo ""
    echo " One option from available options is:"
    echo "  Database:"
    echo "   --start-hsql-server    Launch an embedded HSQL DB server"
    echo "   --stop-hsql-server     Halt an embedded HSQL DB server"
    echo "   --create               Create the table $HSQLDB_TABLE in database"
    echo "   --show                 Show data from database"
    echo "   --dbtool               Start DB Tool"
    echo "   --sql <command>        run sql command"
    echo "   --drop                 Drop the table $HSQLDB_TABLE from database"
    echo "  LDAP"
    echo "   --start-ldap-server    Launch an embedded OpenDJ LDAP server"
    echo "  Other functions"
    echo "   --run                  Run the synchronization task"
    echo "   --set-ext-id           Run task to set externalId"
    echo "   --clean                Remove all files from disk"
    echo "   --help                 Print informations"
    echo ""
    exit 1
    ;;
esac

# -- Run actions --

for action in $ACTIONS; do
  case "$action" in
    "dropdata")
      data_drop
      ;;
    "createdata")
      data_create
      ;;
    "showdata")
      data_show
      ;;
    "sql")
      hsqldb_sqlQuery "$SQL_COMMAND"
      ;;
    "startldap")
      start_ldap
      ;;
    "stopldap")
      stop_ldap
      ;;
    "starthsql")
      start_hsql
      ;;
    "stophsql")
      stop_hsql
      ;;
    "startdbtool")
      start_dbtool
      ;;
    "cleandata")
      hsqldb_cleanData
      ;;
    "cleanldapdata")
      rm -rf /tmp/opendj-test
      ;;
  esac
done

