#! /bin/sh
#  ------------------------------------------------------------
#  Company: Software- und Organisations-Service GmbH
#  Purpose: Start Script for JS7 Controller
#  ------------------------------------------------------------

set -e

### BEGIN INIT INFO
# Provides:          JS7Controller
# Required-Start:    $syslog $remote_fs
# Required-Stop:     $syslog $remote_fs
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Description:       Start JS7 Controller
### END INIT INFO

### USAGE OF THIS FILE ##################################
#
# It can be used as a service start script in /etc/init.d
#
# Each JS7 Controller must use its own Controller ID.
# For example if the Controller ID 'jobscheduler' 
# is used for the instance then copy this file
# 
# 'controller.sh' 
# -> 'controller_jobscheduler.sh'
#
# and set the JS7_CONTROLLER_ID variable.
#
# If you move this script outside the bin directory of 
# the JS7 Controller installation path, e.g. for use with
# /etc/init.d, then you have to set JS7_CONTROLLER_HOME.
#  
# Further set the JS7_CONTROLLER_USER variable.
#
##########################################################


### SETTINGS #############################################

# This variable has to point to the installation path of 
# the JS7 Controller. If this variable is not defined then the parent
# directory of this start script is used.
### NOTE: 
# This variable is required if this start script is used for a  
# JS7 Controller service in /etc/init.d to locate the installation 
# path of the JS7 Controller.
#
# JS7_CONTROLLER_HOME=


# Sets the user account for the JS7 Controller.
# Without this setting the currently logged in user account is used.
# The JS7 Controller should always be started with the same user account
# to avoid problems about permissions in the JS7_CONTROLLER_DATA folder.
# This variable has to be set if this script is used for autostart
# to avoid that the JS7 Controller is started as the 'root' user account.
#
# JS7_CONTROLLER_USER=


# The default JS7 Controller ID

test -z "${JS7_CONTROLLER_ID}" && JS7_CONTROLLER_ID=controller


# The default port of the JS7 Controller

JS7_CONTROLLER_DEFAULT_HTTP_PORT=4444

# Sets the http port for the JS7 Controller.
# Without this setting the default port 4444 is used.
# If just a port is specified then the JS7 Controller listens to all
# available network interfaces. This corresponds to 0.0.0.0:<port>.
# Use the form <ip address or hostname>:<port> to indicate
# a specific network interface the JS7 Controller should listen to.
# The command line option --http-port beats the environment
# variable JS7_CONTROLLER_HTTP_PORT.
#
# JS7_CONTROLLER_HTTP_PORT=


# In addition to the http port an https port for the
# JS7 Controller can be specified. If just a port is specified
# then the JS7 Controller listens to all available network interfaces.
# This corresponds to using 0.0.0.0:<port>.
# Use the form <ip address or hostname>:<port> to indicate
# a specific network interface the JS7 Controller should listen to.
# The command line option --https-port beats the environment
# variable JS7_CONTROLLER_HTTPS_PORT.
#
# JS7_CONTROLLER_HTTPS_PORT=


# Sets the directory used by the JS7 Controller for configuration
# files, log files, journal files and temporary files.
# This directory has to be unique for any instance of the
# JS7 Controller. The default value is JS7_CONTROLLER_HOME/var.
# Check that the JS7 Controller user account has read/write
# permissions for this directory.
#
# JS7_CONTROLLER_DATA=


# Sets the directory used by the JS7 Controller for configuration
# files. The default value is JS7_CONTROLLER_DATA/config.
# The command line option --config-directory beats the environment
# variable JS7_CONTROLLER_CONFIG_DIR.
# Check that the JS7 Controller user account has read/write
# permissions for this directory.
#
# JS7_CONTROLLER_CONFIG_DIR=


# Sets the directory to which the JS7 Controller stores log files.
# The default value is JS7_CONTROLLER_DATA/logs.
# Check that the JS7 Controller user account has read/write
# permissions for this directory.
#
# JS7_CONTROLLER_LOGS=


# Sets the directory to which the JS7 Controller stores its PID file.
# The default value is JS7_CONTROLLER_LOGS.
# Check that the JS7 Controller user account has read/write
# permissions for this directory.
#
# JS7_CONTROLLER_PID_FILE_DIR=


# Specifies the Java Runtime Environment to be used by the
# JS7 Controller. If JAVA_HOME is not set then Java is used from
# the PATH.
#
# JAVA_HOME=


# With Java 1.8 initial memory allocation has changed,
# for details see https://kb.sos-berlin.com/x/aIC9
# As a result on start-up of the JS7 Controller the amount of
# virtual memory assigned by Java depends on the physical
# memory and in most cases is by far too high.
# The environment variable JAVA_OPTIONS can be used to apply
# memory settings.
# The default value for JAVA_OPTIONS is -Xmx500m -Dfile.encoding=UTF-8.
#
# JAVA_OPTIONS=

##########################################################


usage() 
{
  echo "Usage: $(basename "$0") command [options] [switches]"
  echo "  command:"
  echo "    start           [options]"
  echo "    start-container [options]"
  echo "    stop            [options]"
  echo "    restart         [options]"
  echo "    status          [options]"
  echo "    cancel          [options]"
  echo "    switch-over     [options]"
  echo "    revert          [options]"
  echo "    cert            [cert-options]         | see https://kb.sos-berlin.com/x/jLbAAw"
  echo "  options:"
  echo "    --id=<identifier>                      | Controller ID, default: $JS7_CONTROLLER_ID"
  echo "    --http-port=<[interface:]port>         | http network interface and port, default: $JS7_CONTROLLER_HTTP_PORT"
  echo "    --https-port=<[interface:]port>        | https network interface and port, default: $JS7_CONTROLLER_HTTPS_PORT"
  echo "    --data-directory=<directory>           | default: $JS7_CONTROLLER_DATA"
  echo "    --config-directory=<directory>         | default: $JS7_CONTROLLER_CONFIG_DIR"
  echo "    --timeout=<seconds>                    | timeout for terminating Controller instance"
  echo "    --java-options=<java options>          | default: ${JS7_CONTROLLER_JAVA_OPTIONS}; see https://kb.sos-berlin.com/x/uYo7B"
  echo "    --watchdog=<path>                      | default: ${JS7_CONTROLLER_WATCHDOG_DEFAULT}; see https://kb.sos-berlin.com/x/R7pfCQ"
  echo "  switches:"
  echo "    -c | --curl                            | use curl instead of Java http client"
  echo "    -f | --fail-over                       | fail-over active role on stop and restart"
  echo "    --watchdog-log-stdout                  | use stdout channel instead of watchdog.log file"
  echo ""
  more_info
}

more_info()
{
  echo "see https://kb.sos-berlin.com/x/CKrAAw for more information."
}

start_controller() 
{
  JS7_CONTROLLER_EXIT=0
  if running
  then
    echo "...JS7 Controller(${JS7_CONTROLLER_ID}) is already running with pid=$(get_pid)!"
    exit 0
  fi
  JS7_CONTROLLER_CLASSPATH="${JS7_CONTROLLER_CONFIG_DIR}/patches/*:${JS7_CONTROLLER_CONFIG_DIR}/lib/*:${JS7_CONTROLLER_HOME}/lib/patches/*:${JS7_CONTROLLER_HOME}/lib/user_lib/*:${JS7_CONTROLLER_HOME}/lib/sos/*:${JS7_CONTROLLER_HOME}/lib/3rd-party/*"
  if [ -f "${JS7_CONTROLLER_CONFIG_DIR}/log4j2.xml" ]
  then
    # JS7_CONTROLLER_JAVA_OPTIONS="${JS7_CONTROLLER_JAVA_OPTIONS} -Dlog4j2.configurationFile=\"${JS7_CONTROLLER_CONFIG_DIR}/log4j2.xml\""
    JS7_CONTROLLER_CLASSPATH="${JS7_CONTROLLER_CONFIG_DIR}:${JS7_CONTROLLER_CLASSPATH}"
  else
    # JS7_CONTROLLER_JAVA_OPTIONS="${JS7_CONTROLLER_JAVA_OPTIONS} -Dlog4j2.configurationFile=\"${JS7_CONTROLLER_HOME}/lib/log4j2.xml\""
    JS7_CONTROLLER_CLASSPATH="${JS7_CONTROLLER_HOME}/lib:${JS7_CONTROLLER_CLASSPATH}"
  fi
  if [ -z "$JS7_CONTROLLER_TZ" ]
  then
    JS7_CONTROLLER_TZ="$(get_timezone)"
  fi
  if [ "${JS7_CONTROLLER_DATA}" != "$(pwd)" ]
  then
    cd "${JS7_CONTROLLER_DATA}"
  fi
  if [ ! -x "${JS7_CONTROLLER_WATCHDOG}" ]
  then
	echo "...${JS7_CONTROLLER_WATCHDOG} doesn't exist or is not executable"
	exit 3
  fi
 
  export_env
  
  #remove_folder "${JS7_CONTROLLER_DATA}/work"
  #create_folder "${JS7_CONTROLLER_DATA}/work"
  
  "${JS7_CONTROLLER_WATCHDOG}" -"${JS7_CONTROLLER_ID}" &
  JS7_CONTROLLER_EXIT=$?
}

start_controller_in_container()
{
  JS7_CONTROLLER_EXIT=0
  if running
  then
     echo "...JS7 Controller(${JS7_CONTROLLER_ID}) is already running with pid=$(get_pid)!"
     exit 0
  fi
  JS7_CONTROLLER_CLASSPATH="${JS7_CONTROLLER_CONFIG_DIR}/patches/*:${JS7_CONTROLLER_CONFIG_DIR}/lib/*:${JS7_CONTROLLER_HOME}/lib/patches/*:${JS7_CONTROLLER_HOME}/lib/user_lib/*:${JS7_CONTROLLER_HOME}/lib/sos/*:${JS7_CONTROLLER_HOME}/lib/3rd-party/*"
  if [ -f "${JS7_CONTROLLER_CONFIG_DIR}/log4j2.xml" ]
  then
    JS7_CONTROLLER_CLASSPATH="${JS7_CONTROLLER_CONFIG_DIR}:${JS7_CONTROLLER_CLASSPATH}"
  else
    JS7_CONTROLLER_CLASSPATH="${JS7_CONTROLLER_HOME}/lib:${JS7_CONTROLLER_CLASSPATH}"
  fi
  if [ -z "$JS7_CONTROLLER_TZ" ]
  then
    JS7_CONTROLLER_TZ="$(get_timezone)"
  fi
  if [ "${JS7_CONTROLLER_DATA}" != "$(pwd)" ]
  then
    cd "${JS7_CONTROLLER_DATA}"
  fi
  export_env
  
  trap "shutdown_controller" INT TERM
  
  #remove_folder "${JS7_CONTROLLER_DATA}/work"
  #create_folder "${JS7_CONTROLLER_DATA}/work"
  
  HTTPS_PORT_OPTION=""
  test -z "${JS7_CONTROLLER_HTTPS_PORT}" || HTTPS_PORT_OPTION="--https-port=${JS7_CONTROLLER_HTTPS_PORT}"
  
  echo "\"${JAVABIN}\" ${JS7_CONTROLLER_JAVA_OPTIONS} -classpath \"${JS7_CONTROLLER_CLASSPATH}\" js7.controller.ControllerMain --id=${JS7_CONTROLLER_ID} --http-port=\"${JS7_CONTROLLER_HTTP_PORT}\" ${HTTPS_PORT_OPTION} --config-directory=\"${JS7_CONTROLLER_CONFIG_DIR}\" --data-directory=\"${JS7_CONTROLLER_DATA}\""
  "${JAVABIN}" ${JS7_CONTROLLER_JAVA_OPTIONS} -classpath "${JS7_CONTROLLER_CLASSPATH}" js7.controller.ControllerMain --id=${JS7_CONTROLLER_ID} --http-port="${JS7_CONTROLLER_HTTP_PORT}" ${HTTPS_PORT_OPTION} --config-directory="${JS7_CONTROLLER_CONFIG_DIR}" --data-directory="${JS7_CONTROLLER_DATA}" &
  JS7_CONTROLLER_EXIT=$?
  
  if [ "${JS7_CONTROLLER_EXIT}" = "0" ]
  then
    create_pid_file $!
    JS7_CONTROLLER_PID=$!
    echo "...JS7 Controller(${JS7_CONTROLLER_ID}) is started with pid=${JS7_CONTROLLER_PID}!"
    wait "${JS7_CONTROLLER_PID}" || JS7_CONTROLLER_EXIT=$?
    restart_container
  fi
}

restart_container()
{
  echo "...JS7 Controller terminates with exit code ${JS7_CONTROLLER_EXIT}"
  
  rm "${JS7_CONTROLLER_PID_FILE}" >/dev/null 2>/dev/null || true
  
  #abort and restart
  if [ "${JS7_CONTROLLER_EXIT}" = "98" ]
  then
    start_controller_in_container
  fi
  #terminate and restart
  if [ "${JS7_CONTROLLER_EXIT}" = "97" ]
  then
    start_controller_in_container
  fi
  if with_revert
  then
    call_revert_option 
  fi
}

stop_controller() 
{
  if with_failover
  then
  	abort_controller
  else
  	shutdown_controller
  fi
}

shutdown_controller() 
{
  if with_revert_option
  then
    touch "${JS7_CONTROLLER_LOGS}/with_revert" 2>/dev/null || true
  fi
  if running
  then
    echo "...try to terminate the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
    http_command POST "{\"TYPE\": \"ShutDown\"}"
  else
    echo "...not started!"
    if with_revert
    then
      call_revert_option 
    fi
  fi
  if [ "${JS7_CONTROLLER_EXIT}" != "0" ]
  then
    echo "...could not terminate the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}!"
    exit 3
  else
    loop_counter=2
    sleep 2
    while running
    do
      if [ "${loop_counter}" = "2" ]
      then
        printf "...waiting for termination"
      fi
      if [ "${JS7_CONTROLLER_STOP_TIMEOUT}" -gt "-1" ] && [ "${loop_counter}" -ge "${JS7_CONTROLLER_STOP_TIMEOUT}" ]
      then
      	echo "..timeout reached"
      	echo "...try to kill (SIGKILL) the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
      	no_mercy "${JS7_CONTROLLER_PID}" || kill_err=$?
      	if [ "$kill_err" = "0" ]
      	then
      	  exit 0
      	fi
      fi
      printf ".."
      loop_counter=$(( loop_counter + 2 ))
      sleep 2
    done
    echo "...terminated!"
    remove_pid_file
  fi
}

abort_controller() 
{
  if with_revert_option
  then
    touch "${JS7_CONTROLLER_LOGS}/with_revert" 2>/dev/null || true
  fi
  if running
  then
    echo "...try to forcibly terminate the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
    http_command POST "{\"TYPE\": \"EmergencyStop\"}" 2>/dev/null
  else
    echo "...not started!"
    if with_revert
    then
      call_revert_option 
    fi
  fi
  sleep 2
  if running
  then
    echo "...could not terminate the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}!"
    exit ${JS7_CONTROLLER_EXIT}
  else
    JS7_CONTROLLER_EXIT=0
    echo "...forcibly terminated!"
    remove_pid_file
  fi
}

status_controller() 
{  
  http_command GET "?"
  #exit 3 if program is not running according LSB 3.1
  if [ "${JS7_CONTROLLER_EXIT}" != "0" ]
  then
    echo "...JS7 Controller(${JS7_CONTROLLER_ID}) not started?"
    JS7_CONTROLLER_EXIT=3
  fi
}

cancel_controller()
{
  if running
  then
    JS7_CONTROLLER_PID=$(get_pid)
    #echo "...try to kill (SIGTERM) the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
    #kill -15 "${JS7_CONTROLLER_PID}" 2> /dev/null
    #sleep 5
    #if ps -p "${JS7_CONTROLLER_PID}" > /dev/null 2>&1
    #then
    #  echo "...try once more with SIGKILL."
      echo "...try to cancel (SIGKILL) the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
      no_mercy "${JS7_CONTROLLER_PID}"
    #else
    #  echo "...killed!"
    #  remove_pid_file
    #fi
  else
    echo "...not started!" 
  fi
}

no_mercy()
{
  JS7_CONTROLLER_STOP_TIMEOUT=-1
  kill_err=0
  kill -9 "$1" || kill_err=$?
  if [ "$kill_err" = "0" ]
  then
    echo "...canceled!"
    remove_pid_file
    exit 0
  else
    echo "...could not cancel the JS7 Controller(${JS7_CONTROLLER_ID}) with pid=$1!"
    exit 3
  fi
}

switch_over()
{
  if running
  then
    echo "...try to switch over the Controller cluster of JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
    http_command POST "{\"TYPE\": \"ClusterSwitchOver\"}"
  else
    echo "...not started!"
  fi	
}

take_snapshot()
{
  if running
  then
    echo "...try to take a jounal snapshot of JS7 Controller(${JS7_CONTROLLER_ID}) with pid=${JS7_CONTROLLER_PID}."
    http_command POST "{\"TYPE\": \"TakeSnapshot\"}"
  else
    echo "...not started!"
  fi	
}

call_cert() 
{
  JS7_CONTROLLER_LIBDIR="${JS7_CONTROLLER_HOME}/lib"
  JS7_CONTROLLER_LIBEXTDIR="${JS7_CONTROLLER_LIBDIR}/ext"
  "${JAVABIN}" -Xmx100m -classpath "${JS7_CONTROLLER_LIBDIR}/http-client:${JS7_CONTROLLER_CONFIG_DIR}/patches/*:${JS7_CONTROLLER_CONFIG_DIR}/lib/*:${JS7_CONTROLLER_LIBDIR}/patches/*:${JS7_CONTROLLER_LIBEXTDIR}/sos/*:${JS7_CONTROLLER_LIBEXTDIR}/3rd-party/*:${JS7_CONTROLLER_LIBDIR}/3rd-party/*" -Djs7.config-directory="${JS7_CONTROLLER_CONFIG_DIR}" com.sos.cli.ExecuteRollOut "$@"
  exit $?
}

call_revert() 
{
  if running
  then
    echo "first, stop the JS7 Controller(${JS7_CONTROLLER_ID})"
    exit 1
  else
    call_revert_option
  fi
}

call_revert_option() 
{
  export JS7_CONTROLLER_DATA
  "${JAVABIN}" -classpath "${JS7_CONTROLLER_HOME}/lib/classes" RevertClusterInJournal
  exit $?
}

http_command()
{
  if with_curl
  then
    command_with_curl "$1" "$2"
  else
    command_with_controller_client "$2"
  fi
}

command_with_controller_client()
{
  JS7_CONTROLLER_EXIT="0"
  JS7_CONTROLLER_LIBDIR="${JS7_CONTROLLER_HOME}/lib"
  "${JAVABIN}" -Xmx100m -classpath "${JS7_CONTROLLER_LIBDIR}/http-client:${JS7_CONTROLLER_LIBDIR}/sos/*:${JS7_CONTROLLER_LIBDIR}/3rd-party/*" js7.controller.client.main.ControllerClientMain --config-directory="${JS7_CONTROLLER_CONFIG_DIR}" --data-directory="${JS7_CONTROLLER_DATA}" "$(get_url_cutted)" "$1" || JS7_CONTROLLER_EXIT=$?
}

command_with_curl()
{
  JS7_CONTROLLER_EXIT="0"
  if [ "$1" = "POST" ]
  then
    curl --fail -L -X POST -d "$2" -H "X-JS7-Session: $(cat "${JS7_CONTROLLER_DATA}/work/session-token")" -H "Content-Type: application/json" "$(get_url)/api/command" || JS7_CONTROLLER_EXIT=$?
  else
    curl --fail -L -H "X-JS7-Session: $(cat "${JS7_CONTROLLER_DATA}/work/session-token")" "$(get_url)/api$2" || JS7_CONTROLLER_EXIT=$?
  fi
  echo ""
}

get_pid() 
{
  if [ -f "${JS7_CONTROLLER_PID_FILE}" ]
  then
    cat "${JS7_CONTROLLER_PID_FILE}"
    return 0
  else
    JS7_CONTROLLER_PID=$(get_pid_from_ps)
    echo "${JS7_CONTROLLER_PID}"
    if [ -z "${JS7_CONTROLLER_PID}" ]
    then
      return 1
    fi
  fi 
  return 0
}

get_pid_from_ps() 
{
  ps -ef | grep -E "js7\.controller\.ControllerMain.*--http-port=${JS7_CONTROLLER_HTTP_PORT}" | grep -v "grep" | awk '{print $2}'
}

running()
{
  JS7_CONTROLLER_PID=$(get_pid 2>/dev/null) || return 1 
  if kill -0 "${JS7_CONTROLLER_PID}" 2>/dev/null
  then
    return 0
  else
    remove_pid_file
  fi
  return 1
}

get_timezone()
{
  if [ -f "${JS7_CONTROLLER_HOME}/lib/classes/DefaultTimeZone.class" ]
  then
    "${JAVABIN}" -classpath "${JS7_CONTROLLER_HOME}/lib/classes" DefaultTimeZone 2>/dev/null || echo "Etc/UTC"
  else
    echo "Etc/UTC"
  fi
}

with_curl()
{
  which curl >/dev/null 2>/dev/null || return 1
  return "${WITH_CURL}"
}

with_failover()
{
  test -z "${WITH_FAILOVER}" && return 1
  return "${WITH_FAILOVER}"
}

without_watchdog()
{
  test -z "${JS7_WITHOUT_WATCHDOG}" && return 1
  return "${JS7_WITHOUT_WATCHDOG}"
}

with_revert_option()
{
  test -z "${WITH_REVERT}" && return 1
  return "${WITH_REVERT}"
}

with_revert()
{
  if [ -f "${JS7_CONTROLLER_LOGS}/with_revert" ]
  then
    rm -f "${JS7_CONTROLLER_LOGS}/with_revert" 2>/dev/null || true
	return 0
  fi
  return 1
}

create_pid_file() 
{
  JS7_CONTROLLER_PID=$1
  echo "${JS7_CONTROLLER_PID}" > "${JS7_CONTROLLER_PID_FILE}" || true
  if [ ! -f "${JS7_CONTROLLER_PID_FILE}" ]
  then
    echo "...could not create pid file \"${JS7_CONTROLLER_PID_FILE}\""
    echo "...please check permissions for directory: \"${JS7_CONTROLLER_PID_FILE_DIR}\"."
    more_info
    exit 3
  else
    chmod 666 "${JS7_CONTROLLER_PID_FILE}" 2>/dev/null || true
  fi 
}

remove_pid_file()
{
  rm -f "${JS7_CONTROLLER_PID_FILE}" 2>/dev/null || return 1
  return 0
}

mkdir_error()
{
  echo "...could not create directory: \"$1\""
  echo "please create directory \"$1\" with read/write permissions for user account \"${JS7_CONTROLLER_USER}\""
  MKDIR_ERROR_EXISTS=1
  more_info
}

export_env()
{
  JS7_CONTROLLER_APPNAME=controller
  export JS7_CONTROLLER_ID
  export JS7_CONTROLLER_USER
  export JS7_CONTROLLER_APPNAME
  export JS7_CONTROLLER_HOME
  export JS7_CONTROLLER_DATA
  export JS7_CONTROLLER_CONFIG_DIR
  export JS7_CONTROLLER_PORT
  export JS7_CONTROLLER_HTTP_PORT
  export JS7_CONTROLLER_HTTPS_PORT
  export JAVABIN
  export JS7_CONTROLLER_LOGS
  export JS7_CONTROLLER_JAVA_OPTIONS
  export JS7_CONTROLLER_CLASSPATH
  export JS7_CONTROLLER_PID_FILE
  export JS7_CONTROLLER_PID_FILE_DIR
  export JS7_CONTROLLER_TZ
  export JS7_WITHOUT_WATCHDOG
  export JS7_CONTROLLER_WATCHDOG
}

get_port()
{
  echo "$1" | cut -d : -f 2 
}

get_url()
{
  if [ -f "${JS7_CONTROLLER_DATA}/work/http-uri" ]
  then
    cat "${JS7_CONTROLLER_DATA}/work/http-uri"
  else
    echo "http://$(add_ip_address "${JS7_CONTROLLER_HTTP_PORT}" 127.0.0.1)/controller"
  fi
}

get_url_cutted()
{
  echo "$(get_url | cut -d / -f 1,2,3)"
}

add_ip_address()
{
  IP_ADDRESS=$(echo "$1" | grep ":" | cut -d : -f 1)
  NEW_IP_ADDRESS="$2"
  if [ -n "$NEW_IP_ADDRESS" ]
  then
    NEW_IP_ADDRESS="${NEW_IP_ADDRESS}:"
  fi
  if [ -z "${IP_ADDRESS}" ] || [ "${IP_ADDRESS}" = "0.0.0.0" ]
  then
    echo "${NEW_IP_ADDRESS}$1"
  else
    echo "$1"
  fi
}

create_folder()
{
  if [ ! -d "$1" ]
  then
    if [ "${CURRENT_USER}" = "${JS7_CONTROLLER_USER}" ] || [ "${CURRENT_GROUP}" = "root" ]
    then
      mkdir -p "$1" 2>/dev/null || mkdir_error "$1"
    else
      su - "${JS7_CONTROLLER_USER}" -c "mkdir -p $1 2>/dev/null" || mkdir_error "$1"
    fi
  fi
}

remove_folder()
{
  if [ -d "$1" ]
  then
    if [ "${CURRENT_USER}" = "${JS7_CONTROLLER_USER}" ] || [ "${CURRENT_GROUP}" = "root" ]
    then
      rm -rf "$1" 2>/dev/null || return 1
    else
      su - "${JS7_CONTROLLER_USER}" -c "rm -rf $1 2>/dev/null" || return 1
    fi
  fi
  return 0
}

copy_file()
{
  if [ -f "$1" ] && [ ! -f "$2" ]
  then
    if [ "${CURRENT_USER}" = "${JS7_CONTROLLER_USER}" ] || [ "${CURRENT_GROUP}" = "root" ]
    then
      cp -f "$1" "$2" 2>/dev/null || mkdir_error "$2"
    else
      su - "${JS7_CONTROLLER_USER}" -c "cp -f $1 $2 2>/dev/null" || mkdir_error "$2"
    fi
  fi
}

is_integer()
{ 
  if [ -n "$1" ]
  then
  	test "$1" -eq "$1" 2>/dev/null
    if [ $? -ne 0 ]
    then
      echo "$1 is not an integer"
      return 1
    fi
  else
  	return 1
  fi
  return 0
}

end()
{
  if [ "${CUR_DIR}" != "$(pwd)" ]
  then
    cd "${CUR_DIR}" || true
  fi
  
  unset JS7_CONTROLLER_ID
  unset JS7_CONTROLLER_USER
  unset JS7_CONTROLLER_HOME
  unset JS7_CONTROLLER_DATA
  unset JS7_CONTROLLER_CONFIG_DIR
  unset JS7_CONTROLLER_PORT
  unset JS7_CONTROLLER_HTTP_PORT
  unset JS7_CONTROLLER_HTTPS_PORT
  unset JAVABIN
  unset JS7_CONTROLLER_LOGS
  unset JS7_CONTROLLER_JAVA_OPTIONS
  unset JS7_CONTROLLER_CLASSPATH
  unset JS7_CONTROLLER_PID
  unset JS7_CONTROLLER_PID_FILE
  unset JS7_CONTROLLER_PID_FILE_DIR
  unset JS7_CONTROLLER_TZ
  unset CUR_DIR
  unset JS7_CONTROLLER_LIBDIR
  unset WITH_CURL
  unset JS7_WITHOUT_WATCHDOG
  unset JS7_CONTROLLER_WATCHDOG
  unset MKDIR_ERROR_EXISTS
  unset IP_ADDRESS
  unset NEW_IP_ADDRESS
  unset CURRENT_USER
  unset CURRENT_GROUP
  unset JS7_CONTROLLER_BINDIR
  unset JS7_CONTROLLER_STARTSCRIPT
  unset HTTPS_PORT_OPTION
  unset WITH_REVERT
  unset JS7_CONTROLLER_STOP_TIMEOUT
  
  set +e
}

trap 'end' EXIT

##########################
# set and check home
CUR_DIR="$(pwd)"
JS7_CONTROLLER_BINDIR="$(dirname "$0")"
JS7_CONTROLLER_BINDIR="$(cd "${JS7_CONTROLLER_BINDIR}" >/dev/null && pwd)"
JS7_CONTROLLER_STARTSCRIPT="${JS7_CONTROLLER_BINDIR}/$(basename "$0")"
if [ -z "${JS7_CONTROLLER_HOME}" ]
then
  JS7_CONTROLLER_HOME="$(cd "${JS7_CONTROLLER_BINDIR}/.." >/dev/null && pwd)"
fi
JS7_CONTROLLER_WATCHDOG_DEFAULT="${JS7_CONTROLLER_HOME}/bin/controller_watchdog.sh"

if [ ! -d "${JS7_CONTROLLER_HOME}/lib" ]
then
  echo "...directory is missing: \"${JS7_CONTROLLER_HOME}/lib\""
  echo "did you move the start script to some other location?"
  echo "please set the JS7_CONTROLLER_HOME environment variable in: '$0'."
  more_info
  exit 3
fi


##########################
# set user
# 'whoami' on Solaris sometimes not available
CURRENT_USER=$(whoami 2>/dev/null || ( id | sed 's/.*uid=[^(]*(\([^)]*\)).*/\1/' ))
CURRENT_GROUP="$(id -g -n -r)"
if [ -z "${JS7_CONTROLLER_USER}" ]
then
  JS7_CONTROLLER_USER="${CURRENT_USER}"
  #if [ "${CURRENT_USER}" = "root" ]
  #then
  #  echo "The current JS7_CONTROLLER_USER is 'root'!"
  #  echo "Please set the JS7_CONTROLLER_USER variable in '$0'."
  #  echo "If you really want the 'root' user then set"
  #  echo "JS7_CONTROLLER_USER=root in '$0'."
  #  more_info
  #  exit 2
  #fi
fi


##########################
# set http port etc.
HTTPS_PORT_OPTION=
JS7_CONTROLLER_PORT=
WITH_CURL=1
WITH_REVERT=1
WITH_FAILOVER=1
JS7_WITHOUT_WATCHDOG=1
JS7_CONTROLLER_STOP_TIMEOUT=-1
for param in "$@"
do
  case "$param" in
     --id=*)                JS7_CONTROLLER_ID=$(echo "$param" | sed 's/--id=//' | sed 's/^"//' | sed 's/"$//')
                            ;;
     --http-port=*)         JS7_CONTROLLER_HTTP_PORT=$(echo "$param" | sed 's/--http-port=//' | sed 's/^"//' | sed 's/"$//')
                            ;;
     --https-port=*)        JS7_CONTROLLER_HTTPS_PORT=$(echo "$param" | sed 's/--https-port=//' | sed 's/^"//' | sed 's/"$//')
                            ;;
     --data-directory=*)    JS7_CONTROLLER_DATA=$(echo "$param" | sed 's/--data-directory=//' | sed 's/^"//' | sed 's/"$//' | sed 's/^\(.*\)\/$/\1/')
                            ;;
     --config-directory=*)  JS7_CONTROLLER_CONFIG_DIR=$(echo "$param" | sed 's/--config-directory=//' | sed 's/^"//' | sed 's/"$//' | sed 's/^\(.*\)\/$/\1/')
                            ;;
     --timeout=*)           JS7_CONTROLLER_STOP_TIMEOUT=$(echo "$param" | sed 's/--timeout=//' | sed 's/^"//' | sed 's/"$//')
                            ;;
     --java-options=*)      JS7_CONTROLLER_JAVA_OPTIONS=$(echo "$param" | sed 's/--java-options=//' | sed 's/^"//' | sed 's/"$//')
                            ;;
     -c | --curl)           WITH_CURL=0
                            ;;
     -f | --fail-over)      WITH_FAILOVER=0
                            ;;
     --revert)              WITH_REVERT=0
                            ;;
     --watchdog-log-stdout) JS7_WITHOUT_WATCHDOG=0
                            ;;
     --watchdog=*)          JS7_CONTROLLER_WATCHDOG=$(echo "$param" | sed 's/--watchdog=//' | sed 's/^"//' | sed 's/"$//' | sed 's/^\(.*\)\/$/\1/')
                            ;;
  esac
done

JS7_CONTROLLER_HTTP_PORT=$(echo "${JS7_CONTROLLER_HTTP_PORT}" | sed 's/^://')
JS7_CONTROLLER_HTTPS_PORT=$(echo "${JS7_CONTROLLER_HTTPS_PORT}" | sed 's/^://')
test -z "${JS7_CONTROLLER_HTTP_PORT}" && JS7_CONTROLLER_HTTP_PORT=$(add_ip_address "${JS7_CONTROLLER_DEFAULT_HTTP_PORT}" "")
JS7_CONTROLLER_PORT=$(get_port "${JS7_CONTROLLER_HTTP_PORT}")
if ! is_integer "${JS7_CONTROLLER_STOP_TIMEOUT}"
then
  JS7_CONTROLLER_STOP_TIMEOUT=-1
fi

##########################
# set pid file etc.
test -z "${JS7_CONTROLLER_DATA}" && JS7_CONTROLLER_DATA="${JS7_CONTROLLER_HOME}/var"
test -z "${JS7_CONTROLLER_CONFIG_DIR}" && JS7_CONTROLLER_CONFIG_DIR="${JS7_CONTROLLER_DATA}/config"
test -z "${JS7_CONTROLLER_LOGS}" && JS7_CONTROLLER_LOGS="${JS7_CONTROLLER_DATA}/logs"
test -z "${JS7_CONTROLLER_PID_FILE_DIR}" && JS7_CONTROLLER_PID_FILE_DIR="${JS7_CONTROLLER_LOGS}"
test -z "${JS7_CONTROLLER_PID_FILE_NAME}" && JS7_CONTROLLER_PID_FILE_NAME="controller.pid"
JS7_CONTROLLER_PID_FILE="${JS7_CONTROLLER_PID_FILE_DIR}/${JS7_CONTROLLER_PID_FILE_NAME}"
test -z "${JS7_CONTROLLER_WATCHDOG}" && JS7_CONTROLLER_WATCHDOG="${JS7_CONTROLLER_WATCHDOG_DEFAULT}"

MKDIR_ERROR_EXISTS=0 
create_folder "${JS7_CONTROLLER_DATA}"
create_folder "${JS7_CONTROLLER_LOGS}"
if [ "${JS7_CONTROLLER_LOGS}" != "${JS7_CONTROLLER_PID_FILE_DIR}" ]
then 
  create_folder "${JS7_CONTROLLER_PID_FILE_DIR}"
fi
create_folder "${JS7_CONTROLLER_DATA}/state"
create_folder "${JS7_CONTROLLER_DATA}/work"
create_folder "${JS7_CONTROLLER_CONFIG_DIR}/license"
create_folder "${JS7_CONTROLLER_CONFIG_DIR}/lib"
create_folder "${JS7_CONTROLLER_CONFIG_DIR}/private"
create_folder "${JS7_CONTROLLER_CONFIG_DIR}/patches"
create_folder "${JS7_CONTROLLER_CONFIG_DIR}/private/trusted-x509-keys"
create_folder "${JS7_CONTROLLER_CONFIG_DIR}/private/trusted-pgp-keys"
copy_file "${JS7_CONTROLLER_HOME}/var/config/controller.conf-example" "${JS7_CONTROLLER_CONFIG_DIR}/controller.conf"
copy_file "${JS7_CONTROLLER_HOME}/var/config/private/private.conf-example" "${JS7_CONTROLLER_CONFIG_DIR}/private/private.conf"
copy_file "${JS7_CONTROLLER_HOME}/var/config/log4j2.xml-example" "${JS7_CONTROLLER_CONFIG_DIR}/log4j2.xml-example"
# only if trusted-x509-keys folder is empty
if [ "$(ls -p "${JS7_CONTROLLER_CONFIG_DIR}/private/trusted-x509-keys" | wc -l)" = "0" ]
then
  copy_file "${JS7_CONTROLLER_HOME}/var/config/private/trusted-x509-keys/sos.intermediate-ca.pem" "${JS7_CONTROLLER_CONFIG_DIR}/private/trusted-x509-keys/sos.intermediate-ca.pem"
fi
if [ "${MKDIR_ERROR_EXISTS}" = 1 ]
then
  exit 4
fi


##########################
# set java options
test -z "${JS7_CONTROLLER_JAVA_OPTIONS}" && JS7_CONTROLLER_JAVA_OPTIONS="${JAVA_OPTIONS}"
echo "${JS7_CONTROLLER_JAVA_OPTIONS}" | grep -e "-Xmx" >/dev/null 2>/dev/null || JS7_CONTROLLER_JAVA_OPTIONS="${JS7_CONTROLLER_JAVA_OPTIONS} -Xmx500m"
echo "${JS7_CONTROLLER_JAVA_OPTIONS}" | grep -e "-Dfile.encoding" >/dev/null 2>/dev/null || JS7_CONTROLLER_JAVA_OPTIONS="${JS7_CONTROLLER_JAVA_OPTIONS} -Dfile.encoding=UTF-8"
echo "${JS7_CONTROLLER_JAVA_OPTIONS}" | grep -e "HeapDumpOnOutOfMemoryError" >/dev/null 2>/dev/null || JS7_CONTROLLER_JAVA_OPTIONS="${JS7_CONTROLLER_JAVA_OPTIONS} -XX:+HeapDumpOnOutOfMemoryError"


##########################
# set and check java
JAVABIN=$(which java 2>/dev/null || echo "")
test -n "$JAVA_HOME" && test -x "$JAVA_HOME/bin/java" && JAVABIN="$JAVA_HOME/bin/java"
if [ -z "$JAVABIN" ]
then
  echo "...could not identify Java environment"
  echo "...please set JAVA_HOME environment variable"
  more_info 
  exit 5
fi


##########################
# ... and action
case "$1" in
    start)
        if [ "${CURRENT_USER}" = "${JS7_CONTROLLER_USER}" ]
        then
          start_controller
        else
          su - "${JS7_CONTROLLER_USER}" -c "${JS7_CONTROLLER_STARTSCRIPT} $*"
        fi
        ;;
    start-container|start_container|start-docker|start_docker)
        if without_watchdog
        then
          start_controller_in_container
        else
          start_controller_in_container > "${JS7_CONTROLLER_LOGS}/watchdog.log" 2>&1
        fi
        ;;
    stop)
        stop_controller
        ;;
    restart)
        if [ "${CURRENT_USER}" = "${JS7_CONTROLLER_USER}" ]
        then
          stop_controller
          start_controller
        else
          su - "${JS7_CONTROLLER_USER}" -c "${JS7_CONTROLLER_STARTSCRIPT} $*"
        fi
        ;;
    abort)
        abort_controller
        ;;
    cancel|kill)
        cancel_controller
        ;;
    switch-over|switch_over)
        switch_over
        ;;
    take-snapshot|take_snapshot)
        take_snapshot
        ;;
    status)
        shift
        status_controller "$@"
        ;;
    setup)
        echo "Directory for logs and pid files exists!"
        echo "Java version ok!"
        ;;
    cert)
        shift
        call_cert "$@"
        ;;
    revert)
        shift
        call_revert
        ;;
    *)
        usage
        ;;
esac

test -z "${JS7_CONTROLLER_EXIT}" && JS7_CONTROLLER_EXIT=0
exit $JS7_CONTROLLER_EXIT