@echo off

rem #  ------------------------------------------------------------
rem #  Company: Software- und Organisations-Service GmbH
rem #  Purpose: Start script for JS7 Controller
rem #  ------------------------------------------------------------

SETLOCAL

rem ### SETTINGS ##############################################

rem # This variable has to point to the installation path of 
rem # the JS7 Controller.
rem # If this variable not defined then the parent directory 
rem # of this start script is used.
  
rem set JS7_CONTROLLER_HOME=


rem # The default JS7 Controller Id

if not defined JS7_CONTROLLER_ID set JS7_CONTROLLER_ID=controller


rem # The Controller is installed as a Windows Service. The name of 
rem # a Windows Service must be unique. The ControllerId is already
rem # used for the name of the Windows Service. Only in the case that
rem # a Controller cluster is installed on one computer, e.g. the 
rem # standby node must get a suffix, because the ControllerIds are
rem # the same.

rem set JS7_SERVICE_NAME_SUFFIX=


rem # The default port of the JS7 Controller 

set /a JS7_CONTROLLER_DEFAULT_HTTP_PORT=4444


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

rem set JS7_CONTROLLER_HTTP_PORT=


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

rem set JS7_CONTROLLER_HTTPS_PORT=


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

rem set JS7_CONTROLLER_DATA=


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

rem set JS7_CONTROLLER_CONFIG_DIR=


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

rem set JS7_CONTROLLER_LOGS=


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

rem set JS7_CONTROLLER_PID_FILE_DIR=


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

rem set JAVA_HOME=


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

rem set JAVA_OPTIONS=

rem ###########################################################


rem ##########################
rem # internal global vars
set JS7_CONTROLLER_APPNAME=controller
set /a CREATE_PID_FILE_TRIAL=0
set /a RESTART_CONTROLLER=0
set JS7_CONTROLLER_COMMAND=%~1
set JS7_CONTROLLER_STARTSCRIPT=%~dpnx0
if defined JS7_CONTROLLER_INSTANCESCRIPT set JS7_CONTROLLER_STARTSCRIPT=%JS7_CONTROLLER_INSTANCESCRIPT%
set /a LOOP_COUNTER=0
set /a LOOP_SESSION=0
set WEBSERVICES=


rem ##########################
rem # set and check home
if not defined JS7_CONTROLLER_HOME set JS7_CONTROLLER_HOME=%~dp0..
call :normalize_home "%JS7_CONTROLLER_HOME%\dummy"
if not exist "%JS7_CONTROLLER_HOME%\lib" (
  echo ...the directory "%JS7_CONTROLLER_HOME%\lib" is missing!
  echo did you move the startscript?
  echo please set the JS7_CONTROLLER_HOME variable.
  call :more_info
  exit /b 3
)
set JS7_CONTROLLER_WATCHDOG_DEFAULT=%JS7_CONTROLLER_HOME%\bin\controller_watchdog.cmd


rem ##########################
rem # read command line options
set HTTPS_PORT_OPTION=
set WITH_REVERT_OPTION=0
set WITH_FAILOVER=0
set WITH_CURL=0
set JS7_WITHOUT_WATCHDOG=0
set /A JS7_CONTROLLER_STOP_TIMEOUT=-1
:read_command_line_options
shift
if "%~1" == "" goto read_command_line_options_end
if "%~1" == "--revert" ( 
  set WITH_REVERT_OPTION=1
  goto read_command_line_options
)
if "%~1" == "-f" ( 
  set WITH_FAILOVER=1
  goto read_command_line_options
)
if "%~1" == "--fail-over" ( 
  set WITH_FAILOVER=1
  goto read_command_line_options
)
if "%~1" == "-c" ( 
  set WITH_CURL=1
  goto read_command_line_options
)
if "%~1" == "--curl" ( 
  set WITH_CURL=1
  goto read_command_line_options
)
if "%~1" == "--watchdog-log-stdout" ( 
  set JS7_WITHOUT_WATCHDOG=1
  goto read_command_line_options
)
set "OPTION_VALUE=%~2"
set "OPTION_VALUE=%OPTION_VALUE:--id=%"
set "OPTION_VALUE=%OPTION_VALUE:--http-port=%"
set "OPTION_VALUE=%OPTION_VALUE:--https-port=%"
set "OPTION_VALUE=%OPTION_VALUE:--data-directory=%"
set "OPTION_VALUE=%OPTION_VALUE:--config-directory=%"
set "OPTION_VALUE=%OPTION_VALUE:--timeout=%"
set "OPTION_VALUE=%OPTION_VALUE:--java-options=%"
set "OPTION_VALUE=%OPTION_VALUE:--watchdog=%"

if "%~1" == "--id" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set JS7_CONTROLLER_ID=%~2
)
if "%~1" == "--http-port" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set JS7_CONTROLLER_HTTP_PORT=%~2
)
if "%~1" == "--https-port" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set JS7_CONTROLLER_HTTPS_PORT=%~2
)
if "%~1" == "--data-directory" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set "JS7_CONTROLLER_DATA=%~2"
)
if "%~1" == "--config-directory" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set "JS7_CONTROLLER_CONFIG_DIR=%~2"
)
if "%~1" == "--timeout" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set /A JS7_CONTROLLER_STOP_TIMEOUT=%~2
)
if "%~1" == "--java-options" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set "JAVA_OPTIONS=%~2"
)
if "%~1" == "--watchdog" (
  if "%OPTION_VALUE%" == "" goto read_command_line_options
  set "JS7_CONTROLLER_WATCHDOG=%~2"
)

goto read_command_line_options
:read_command_line_options_end
if not defined JS7_CONTROLLER_HTTP_PORT set JS7_CONTROLLER_HTTP_PORT=%JS7_CONTROLLER_DEFAULT_HTTP_PORT%
set JS7_CONTROLLER_SERVICE_NAME=js7_%JS7_CONTROLLER_APPNAME%_%JS7_CONTROLLER_ID%
if defined JS7_SERVICE_NAME_SUFFIX set JS7_CONTROLLER_SERVICE_NAME=%JS7_CONTROLLER_SERVICE_NAME%-%JS7_SERVICE_NAME_SUFFIX%
if defined JS7_CONTROLLER_HTTPS_PORT set HTTPS_PORT_OPTION=--https-port=%JS7_CONTROLLER_HTTPS_PORT%


rem ##########################
rem # set environment and create directories
if not defined JS7_CONTROLLER_DATA set JS7_CONTROLLER_DATA=%JS7_CONTROLLER_HOME%\var
if not defined JS7_CONTROLLER_LOGS set JS7_CONTROLLER_LOGS=%JS7_CONTROLLER_DATA%\logs
if not defined JS7_CONTROLLER_CONFIG_DIR set JS7_CONTROLLER_CONFIG_DIR=%JS7_CONTROLLER_DATA%\config
if not defined JS7_CONTROLLER_WATCHDOG set JS7_CONTROLLER_WATCHDOG=%JS7_CONTROLLER_WATCHDOG_DEFAULT%
if not exist "%JS7_CONTROLLER_WATCHDOG%" (
  echo ..."%JS7_CONTROLLER_WATCHDOG%" doesn't exist
  exit /b 3
)

if not exist "%JS7_CONTROLLER_LOGS%" mkdir "%JS7_CONTROLLER_LOGS%"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_LOGS%"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
rem TODO change to "%JS7_CONTROLLER_DATA%\state" for pid file
if not defined JS7_CONTROLLER_PID_FILE_DIR set JS7_CONTROLLER_PID_FILE_DIR=%JS7_CONTROLLER_LOGS%
if not exist "%JS7_CONTROLLER_PID_FILE_DIR%" mkdir "%JS7_CONTROLLER_PID_FILE_DIR%"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_PID_FILE_DIR%"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not defined JS7_CONTROLLER_PID_FILE_NAME set JS7_CONTROLLER_PID_FILE_NAME=%JS7_CONTROLLER_APPNAME%.pid
if not exist "%JS7_CONTROLLER_DATA%\state" mkdir "%JS7_CONTROLLER_DATA%\state"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_DATA%\state"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\private" mkdir "%JS7_CONTROLLER_CONFIG_DIR%\private"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\private"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\license" mkdir "%JS7_CONTROLLER_CONFIG_DIR%\license"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\license"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\lib" mkdir "%JS7_CONTROLLER_CONFIG_DIR%\lib"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\lib"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\patches" mkdir "%JS7_CONTROLLER_CONFIG_DIR%\patches"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\patches"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-x509-keys" mkdir "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-x509-keys"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-x509-keys"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-pgp-keys" mkdir "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-pgp-keys"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-pgp-keys"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\controller.conf" (
  if exist "%JS7_CONTROLLER_HOME%\var\config\controller.conf-example" copy "%JS7_CONTROLLER_HOME%\var\config\controller.conf-example" "%JS7_CONTROLLER_CONFIG_DIR%\controller.conf" 2>nul
)
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\controller.conf"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\private\private.conf" (
  if exist "%JS7_CONTROLLER_HOME%\var\config\private\private.conf-example" copy "%JS7_CONTROLLER_HOME%\var\config\private\private.conf-example" "%JS7_CONTROLLER_CONFIG_DIR%\private\private.conf" 2>nul
)
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\private\private.conf"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-x509-keys\sos.intermediate-ca.pem" (
  if exist "%JS7_CONTROLLER_HOME%\var\config\private\trusted-x509-keys\sos.intermediate-ca.pem" (
    dir /a-d "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-x509-keys\*" >nul 2>nul || copy "%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" 2>nul
  )
)
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\private\trusted-x509-keys\sos.intermediate-ca.pem"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
if not exist "%JS7_CONTROLLER_CONFIG_DIR%\log4j2.xml-example" (
  if exist "%JS7_CONTROLLER_HOME%\var\config\log4j2.xml-example" copy "%JS7_CONTROLLER_HOME%\var\config\log4j2.xml-example" "%JS7_CONTROLLER_CONFIG_DIR%\log4j2.xml-example" 2>nul
)
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_CONFIG_DIR%\log4j2.xml-example"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
set JS7_CONTROLLER_PID_FILE=%JS7_CONTROLLER_PID_FILE_DIR%\%JS7_CONTROLLER_PID_FILE_NAME%


rem ##########################
rem # set java options
echo.%JAVA_OPTIONS% | findstr /I /C:-Xmx >nul
if ERRORLEVEL 1 set JAVA_OPTIONS=%JAVA_OPTIONS% -Xmx500m
echo.%JAVA_OPTIONS% | findstr /I /C:-Dfile.encoding >nul
if ERRORLEVEL 1 set JAVA_OPTIONS=%JAVA_OPTIONS% -Dfile.encoding=UTF-8
echo.%JAVA_OPTIONS% | findstr /I /C:HeapDumpOnOutOfMemoryError >nul
if ERRORLEVEL 1 set JAVA_OPTIONS=%JAVA_OPTIONS% -XX:+HeapDumpOnOutOfMemoryError
echo.%JAVA_OPTIONS% | findstr /I /C:ExitOnOutOfMemoryError >nul
if ERRORLEVEL 1 set JAVA_OPTIONS=%JAVA_OPTIONS% -XX:+ExitOnOutOfMemoryError


rem ##########################
rem # set and check java
set JAVABIN=java.exe
if exist "%JAVA_HOME%\bin\java.exe" set JAVABIN=%JAVA_HOME%\bin\java.exe


rem ##########################
rem # set and check java version
set /a JAVA_VERSION_MAJOR=0
set JAVA_UNSAFE_OPTION=
call :set_java_version "%JAVA_HOME%\release"
if %JAVA_VERSION_MAJOR% GEQ 24 set JAVA_UNSAFE_OPTION=--sun-misc-unsafe-memory-access=allow
if defined JAVA_UNSAFE_OPTION set JAVA_OPTIONS=%JAVA_UNSAFE_OPTION% %JAVA_OPTIONS%


rem ##########################
rem # ... and action
:action
if "%JS7_CONTROLLER_COMMAND%"=="start"   goto do_start
if "%JS7_CONTROLLER_COMMAND%"=="stop"    goto do_stop
if "%JS7_CONTROLLER_COMMAND%"=="abort"   goto do_abort
if "%JS7_CONTROLLER_COMMAND%"=="restart" goto do_restart
if "%JS7_CONTROLLER_COMMAND%"=="status"  goto do_status
if "%JS7_CONTROLLER_COMMAND%"=="switch-over" goto do_switch_over
if "%JS7_CONTROLLER_COMMAND%"=="switch_over" goto do_switch_over
if "%JS7_CONTROLLER_COMMAND%"=="take-snapshot" goto do_take_snapshot
if "%JS7_CONTROLLER_COMMAND%"=="take_snapshot" goto do_take_snapshot
if "%JS7_CONTROLLER_COMMAND%"=="cancel"  goto do_cancel
if "%JS7_CONTROLLER_COMMAND%"=="kill"    goto do_cancel
if "%JS7_CONTROLLER_COMMAND%"=="cert"    goto do_cert
if "%JS7_CONTROLLER_COMMAND%"=="pid-file"        goto do_pid_file
if "%JS7_CONTROLLER_COMMAND%"=="install-service" goto do_install_service
if "%JS7_CONTROLLER_COMMAND%"=="install_service" goto do_install_service
if "%JS7_CONTROLLER_COMMAND%"=="install" goto do_install_service
if "%JS7_CONTROLLER_COMMAND%"=="remove-service"  goto do_remove_service
if "%JS7_CONTROLLER_COMMAND%"=="remove_service"  goto do_remove_service
if "%JS7_CONTROLLER_COMMAND%"=="remove"  goto do_remove_service
if "%JS7_CONTROLLER_COMMAND%"=="start-service"   goto do_start_service
if "%JS7_CONTROLLER_COMMAND%"=="start_service"   goto do_start_service
if "%JS7_CONTROLLER_COMMAND%"=="revert"  goto do_revert
rem is called only during the installation
if "%JS7_CONTROLLER_COMMAND%"=="setup-start-service" goto do_setup_start_service
if "%JS7_CONTROLLER_COMMAND%"=="setup_start_service" goto do_setup_start_service
if "%JS7_CONTROLLER_COMMAND%"=="show_env" goto do_show_env
if "%JS7_CONTROLLER_COMMAND%"=="show-env" goto do_show_env
goto usage


:usage
echo Usage: %JS7_CONTROLLER_STARTSCRIPT% command [options] [switches]
echo   command:
echo     start           [options]
echo     stop            [options]
echo     restart         [options]
echo     status          [options]
echo     cancel          [options]
echo     switch-over     [options]
echo     revert          [options]
echo     start-service   [options]
echo     install-service [options]
echo     remove-service  [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: %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.
call :more_info
exit /b 0


:more_info
echo see https://kb.sos-berlin.com/x/CKrAAw for more information.
goto final


:set_java_version
if exist "%~1" call :set_java_version_from_release_file "%~1"
if not exist "%~1" call :set_java_version_from_out
goto final


:set_java_version_from_release_file
for /F "usebackq delims== tokens=1,2" %%i in ("%~1") do if /I "%%~i"=="JAVA_VERSION" set JAVA_VERSION=%%~j
if defined JAVA_VERSION call :set_java_version_major "%JAVA_VERSION%"
goto final


:set_java_version_from_out
for /F "usebackq tokens=2,3" %%i in (`"%JAVABIN%" -version 2^>^&1`) do if /I "%%~i"=="version" set JAVA_VERSION=%%~j
if defined JAVA_VERSION call :set_java_version_major "%JAVA_VERSION%"
goto final


:set_java_version_major
for /F "usebackq delims=. tokens=1" %%i in (`echo.%~1`) do set /a JAVA_VERSION_MAJOR=%%~i
goto final


:set_class_path
set JS7_CONTROLLER_LIBDIR=%JS7_CONTROLLER_HOME:\=/%/lib
if not defined JS7_CONTROLLER_TZ (
  if exist "%JS7_CONTROLLER_HOME%\lib\classes\DefaultTimeZone.class" (
    for /f "usebackq" %%i in (`%JAVABIN% -classpath "%JS7_CONTROLLER_LIBDIR%/classes" DefaultTimeZone 2^>nul`) do set JS7_CONTROLLER_TZ=%%i
  )
)
if not defined JS7_CONTROLLER_TZ set JS7_CONTROLLER_TZ=Etc/UTC
set JS7_CONTROLLER_CLASSPATH=%JS7_CONTROLLER_CONFIG_DIR:\=/%/patches/*;%JS7_CONTROLLER_CONFIG_DIR:\=/%/lib/*;%JS7_CONTROLLER_LIBDIR%/patches/*;%JS7_CONTROLLER_LIBDIR%/user_lib/*;%JS7_CONTROLLER_LIBDIR%/sos/*;%JS7_CONTROLLER_LIBDIR%/3rd-party/*
if exist "%JS7_CONTROLLER_CONFIG_DIR%\log4j2.xml" (
  set "JS7_CONTROLLER_CLASSPATH=%JS7_CONTROLLER_CONFIG_DIR:\=/%;%JS7_CONTROLLER_CLASSPATH%"
) else (
  set "JS7_CONTROLLER_CLASSPATH=%JS7_CONTROLLER_LIBDIR%;%JS7_CONTROLLER_CLASSPATH%"
)
goto final


:do_start
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 1 (
  call :message "...JS7 Controller(%JS7_CONTROLLER_ID%) already running"
  exit /b 0 
)
call :set_class_path
call :cleanup_workdir

if %JS7_WITHOUT_WATCHDOG% equ 1 (
  start "JS7ControllerW" /B "%COMSPEC%" /C "%JS7_CONTROLLER_WATCHDOG%" -%JS7_CONTROLLER_ID%
) else (
  start "JS7ControllerW" /B "%COMSPEC%" /C "%JS7_CONTROLLER_WATCHDOG%" -%JS7_CONTROLLER_ID% >"%JS7_CONTROLLER_LOGS%\watchdog.log" 2>&1
)
if ERRORLEVEL 1 (
  exit /b %ERRORLEVEL%
) else (
  goto create_pid_file
)
goto finally


:do_stop
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 0 (
  echo ...not started!
  goto finally
)
set /a RESTART_CONTROLLER=%RESTART_CONTROLLER%+%JS7_CONTROLLER_RUNNING_AS_SERVICE%
if %WITH_FAILOVER% equ 1 (
  call :call_emergency_stop
) else (
  call :call_shutdown
)
if %RESTART_CONTROLLER% equ 3 goto do_start_service
if %RESTART_CONTROLLER% equ 2 goto do_start
goto finally


:call_shutdown
call :message "...trying to terminate the JS7 Controller(%JS7_CONTROLLER_ID%)"
call :wait_for_session_token
call :command POST "{\"TYPE\": \"ShutDown\"}"
if ERRORLEVEL 1 (
  call :message "...could not terminate the JS7 Controller(%JS7_CONTROLLER_ID%)"
  exit /b 3
) else (
  call :sleep 2
  call :wait_for_termination
  if not ERRORLEVEL 1 echo ...terminated!
  call :remove_pid_file
  if %WITH_REVERT_OPTION% equ 1 call :do_revert_option
)
goto final


:do_abort
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 0 (
  echo ...not started!
  goto finally
)
call :call_emergency_stop
goto finally


:call_emergency_stop
call :message "...trying to forcibly terminate the JS7 Controller(%JS7_CONTROLLER_ID%)"
call :wait_for_session_token
call :command POST "{\"TYPE\": \"EmergencyStop\"}" 2>nul
call :sleep 2
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 1 (
  call :message "...could not forcibly terminate the JS7 Controller(%JS7_CONTROLLER_ID%)"
  exit /b 3
) else (
  echo ...forcibly terminated!
  call :remove_pid_file
  if %WITH_REVERT_OPTION% equ 1 call :do_revert_option
)
goto final


:do_cancel
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 0 (
  echo ...not started!
  goto finally
)
if x%JS7_CONTROLLER_PID%==x (
  echo ...the pid of the JS7 Controller^(%JS7_CONTROLLER_ID%^) process couldn't determine!
  exit /b 3
)
call :message "...trying to cancel the JS7 Controller(%JS7_CONTROLLER_ID%)"
call :no_mercy
goto finally


:no_mercy
set /A JS7_CONTROLLER_STOP_TIMEOUT=-1
taskkill /F /PID %JS7_CONTROLLER_PID% > nul
if ERRORLEVEL 1 (
  call :message "...could not cancel the JS7 Controller(%JS7_CONTROLLER_ID%)"
  exit /b 3
) else (
  echo ...cancelled!
  call :remove_pid_file
) 
goto finally


:do_restart
set /a RESTART_CONTROLLER=2
goto do_stop


:do_switch_over
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 0 (
  echo ...not started!
  goto finally
)
call :message "...trying to switch-over the Controller cluster of JS7 Controller(%JS7_CONTROLLER_ID%)"
call :command POST "{\"TYPE\": \"ClusterSwitchOver\"}"
goto finally


:do_take_snapshot
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 0 (
  echo ...not started!
  goto finally
)
call :message "...trying to take a journal snapshot of JS7 Controller(%JS7_CONTROLLER_ID%)"
call :command POST "{\"TYPE\": \"TakeSnapshot\"}"
goto finally


:do_status
call :command GET "?"
if ERRORLEVEL 1 (
  echo ...JS7 Controller^(%JS7_CONTROLLER_ID%^) not started?
  exit /b 3
)
goto finally


:do_install_service
if not exist "%JS7_CONTROLLER_HOME%\service\install_%JS7_CONTROLLER_APPNAME%_windows_service.cmd" (
  echo ...service install script "..\service\install_%JS7_CONTROLLER_APPNAME%_windows_service.cmd" is missing.
  exit /b 2
)
call "%JS7_CONTROLLER_HOME%\service\install_%JS7_CONTROLLER_APPNAME%_windows_service.cmd" "%JS7_CONTROLLER_ID%" ^
  "%JS7_SERVICE_NAME_SUFFIX%" "%JS7_CONTROLLER_LOGS%" "" "" "%JS7_CONTROLLER_HOME%"
goto finally


:do_remove_service
if not exist "%JS7_CONTROLLER_HOME%\service\uninstall_%JS7_CONTROLLER_APPNAME%_windows_service.cmd" (
  echo ...service remove script "..\service\uninstall_%JS7_CONTROLLER_APPNAME%_windows_service.cmd" is missing.
  exit /b 2
)
call "%JS7_CONTROLLER_HOME%\service\uninstall_%JS7_CONTROLLER_APPNAME%_windows_service.cmd" ^
  "%JS7_CONTROLLER_ID%" "%JS7_SERVICE_NAME_SUFFIX%" "%JS7_CONTROLLER_LOGS%" "%JS7_CONTROLLER_HOME%"
goto finally


:do_start_service
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 1 (
  call :message "...JS7 Controller(%JS7_CONTROLLER_ID%) already running"
  exit /b 0 
)
if %RESTART_CONTROLLER% equ 0 sc.exe query %JS7_CONTROLLER_SERVICE_NAME%
if ERRORLEVEL 1 goto finally
"%JS7_CONTROLLER_HOME%\service\%JS7_CONTROLLER_SERVICE_NAME%.exe" //ES/%JS7_CONTROLLER_SERVICE_NAME%
if ERRORLEVEL 1 (
  echo Failed to start JS7 Controller^(%JS7_CONTROLLER_ID%^) service. Refer to log in "%JS7_CONTROLLER_LOGS%"
  exit /b 2
)
sc.exe query %JS7_CONTROLLER_SERVICE_NAME%
echo ...JS7 Controller^(%JS7_CONTROLLER_ID%^) service has been started.
goto finally


:do_setup_start_service
call :do_start_service
if ERRORLEVEL 1 exit /b 0
echo.
echo ...check connection in 20 seconds
call :sleep 20
echo.
call :do_status
exit /b 0


:do_show_env
set JS7_CONTROLLER_
set JAVA_
exit /b 0


:do_revert
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 1 (
  echo first, stop the JS7 Controller^(%JS7_CONTROLLER_ID%^)
  exit /b 1 
)
:do_revert_option
set WITH_REVERT_OPTION=0
call "%JAVABIN%" -classpath "%JS7_CONTROLLER_HOME:\=/%/lib/classes" RevertClusterInJournal
exit /b %ERRORLEVEL%
goto final


:do_cert
set JS7_CONTROLLER_LIBDIR=%JS7_CONTROLLER_HOME:\=/%/lib
set JS7_CONTROLLER_LIBEXTDIR=%JS7_CONTROLLER_LIBDIR%/ext
call "%JAVABIN%" -Xmx100m -Djs7.config-directory="%JS7_CONTROLLER_CONFIG_DIR%" ^
  -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/*" ^
  com.sos.cli.ExecuteRollOut %*
exit /b %ERRORLEVEL%
goto final


:with_curl
where curl 1>nul 2>nul
if ERRORLEVEL 1 set WITH_CURL=0
if not exist "%JS7_CONTROLLER_DATA%\work\session-token" set WITH_CURL=0
goto final


:command
call :with_curl
if %WITH_CURL% equ 1 (
  call :command_with_curl "%~1" "%~2"
) else (
  call :command_with_controller_client "%~2"
)
goto final


:command_with_controller_client
set JS7_CONTROLLER_LIBDIR=%JS7_CONTROLLER_HOME:\=/%/lib
call "%JAVABIN%" %JAVA_UNSAFE_OPTION% -Xmx100m -classpath "%JS7_CONTROLLER_LIBDIR%/http-client;%JS7_CONTROLLER_LIBDIR%/sos/*;%JS7_CONTROLLER_LIBDIR%/3rd-party/*" ^
  js7.controller.client.main.ControllerClientMain --data-directory="%JS7_CONTROLLER_DATA%" --config-directory="%JS7_CONTROLLER_CONFIG_DIR%" %*
exit /b %ERRORLEVEL%
goto final


:command_with_curl
for /f "usebackq tokens=1" %%i in (`type "%JS7_CONTROLLER_DATA%\work\session-token"`) do set TOKEN=%%i
call :set_url
if x%~1==xPOST (
  curl --fail -L -X POST -d "%~2" -H "X-JS7-Session: %TOKEN%" -H "Content-Type: application/json" "%JS7_CONTROLLER_URL%/controller/api/command"
) else (
  curl --fail -L -H "X-JS7-Session: %TOKEN%" "%JS7_CONTROLLER_URL%/controller/api%~2"
)
echo.
exit /b %ERRORLEVEL%
goto final
  

:running
set /a JS7_CONTROLLER_IS_RUNNING=0
set JS7_CONTROLLER_PID=
set JS7_CONTROLLER_PID_FROMWMIC=
if not exist "%JS7_CONTROLLER_PID_FILE%" goto running2
for /f "usebackq tokens=1" %%i in (`type "%JS7_CONTROLLER_PID_FILE%"`) do set JS7_CONTROLLER_PID=%%i
if x%JS7_CONTROLLER_PID%==x goto running2
rem check if process exist with pid from pidfile
for /f "usebackq tokens=2 delims==" %%i in (`wmic process where "processid=%JS7_CONTROLLER_PID%" get processid /format:value 2^>nul`) do set JS7_CONTROLLER_PID_FROMWMIC=%%i
if x%JS7_CONTROLLER_PID_FROMWMIC% == x%JS7_CONTROLLER_PID% set /a JS7_CONTROLLER_IS_RUNNING=1
goto running3
:running2
if not exist "%JS7_CONTROLLER_DATA%\work\session-token" goto running3
call :command GET "?" >nul 2>nul
if %ERRORLEVEL% equ 0 set /a JS7_CONTROLLER_IS_RUNNING=1
:running3
call :running_as_service
if %JS7_CONTROLLER_IS_RUNNING% equ 0 goto remove_pid_file
goto final


:running_as_service
set /a JS7_CONTROLLER_RUNNING_AS_SERVICE=0
for /F "usebackq tokens=3 delims=: " %%i in (`sc.exe query %JS7_CONTROLLER_SERVICE_NAME% ^| findstr /I "STATE"`) do (
  if /I x%%i==xRUNNING set /a JS7_CONTROLLER_RUNNING_AS_SERVICE=1
)
goto final


:message
echo|set /p="%~1 "
if %JS7_CONTROLLER_RUNNING_AS_SERVICE% equ 1 echo|set /p="as service "
if x%JS7_CONTROLLER_PID%==x (
  echo !
) else (
  echo with pid=%JS7_CONTROLLER_PID%!
)
goto final


:wait_for_termination
call :sleep 2
call :running
if %JS7_CONTROLLER_IS_RUNNING% equ 0 goto final
set /a LOOP_COUNTER=%LOOP_COUNTER%+2
if %LOOP_COUNTER% equ 2 echo|set /p=...waiting for termination
if %JS7_CONTROLLER_STOP_TIMEOUT% gtr -1 (
  if %LOOP_COUNTER% geq %JS7_CONTROLLER_STOP_TIMEOUT% (
    echo ..timeout reached
    call :message "...trying to cancel the JS7 Controller(%JS7_CONTROLLER_ID%)"
    call :no_mercy
    if not ERRORLEVEL 1 goto finally
  )
)      
echo|set /p=..
goto wait_for_termination


:wait_for_session_token
set /a LOOP_SESSION=%LOOP_SESSION%+2
if not exist "%JS7_CONTROLLER_DATA%\work\session-token" (
  if %LOOP_SESSION% geq 10 (
	echo "%JS7_CONTROLLER_DATA%\work\session-token" doesn't exist: command cannot be sent
	goto finally
  )
  echo "%JS7_CONTROLLER_DATA%\work\session-token" doesn't exist: ...waiting  
  call :sleep 2
  goto wait_for_session_token
)
goto finally


:normalize_home
set JS7_CONTROLLER_HOME=%~dp1
set JS7_CONTROLLER_HOME=%JS7_CONTROLLER_HOME:~0,-1%
goto final


:sleep
waitfor SomethingThatNeverHappens /t %1 >nul 2>nul
exit /B 0
goto final


:do_pid_file
call :sleep 2

:create_pid_file
set /a CREATE_PID_FILE_TRIAL=%CREATE_PID_FILE_TRIAL%+1
set JS7_CONTROLLER_PID_FROMWMIC=
if %CREATE_PID_FILE_TRIAL% geq 5 (
  echo ...the pid of the JS7 Controller^(%JS7_CONTROLLER_ID%^) process couldn't determine!
  exit /b 3
)
for /f "usebackq tokens=2 delims==" %%i in (`wmic process where "commandline like '%%js7.controller.ControllerMain%%-http-port=%JS7_CONTROLLER_HTTP_PORT%%%' and caption like '%%java%%'" get processid /format:value 2^>nul`) do set JS7_CONTROLLER_PID_FROMWMIC=%%i
if x%JS7_CONTROLLER_PID_FROMWMIC% == x (
  call :sleep 2
  goto create_pid_file
) else (
  echo %JS7_CONTROLLER_PID_FROMWMIC%> "%JS7_CONTROLLER_PID_FILE%"
)
if exist "%JS7_CONTROLLER_PID_FILE%" (
  echo ...JS7 Controller^(%JS7_CONTROLLER_ID%^) started with pid=%JS7_CONTROLLER_PID_FROMWMIC%! 
  echo ...see log file "%JS7_CONTROLLER_LOGS%\%JS7_CONTROLLER_APPNAME%.log"
  exit /b %ERRORLEVEL%
) else (
  echo ...pid file "%JS7_CONTROLLER_PID_FILE%" could not created!
  echo ...please check the permissions in "%JS7_CONTROLLER_PID_FILE_DIR%".
  call :more_info
  rem taskkill /F /PID %JS7_CONTROLLER_PID_FROMWMIC% > nul
  exit /b 3
)
goto finally


:remove_pid_file
if exist "%JS7_CONTROLLER_PID_FILE%" del "%JS7_CONTROLLER_PID_FILE%"  
goto final


:cleanup_workdir
rem if exist "%JS7_CONTROLLER_DATA%\work" rmdir /S /Q "%JS7_CONTROLLER_DATA%\work"
if not exist "%JS7_CONTROLLER_DATA%\work" mkdir "%JS7_CONTROLLER_DATA%\work"
if ERRORLEVEL 1 (
  echo ...could not create "%JS7_CONTROLLER_DATA%\work"
  echo ...please check the permissions
  call :more_info
  exit /b %ERRORLEVEL%
)
goto final


:add_ip_address
set NEW_IP_ADDRESS=%~2
if defined NEW_IP_ADDRESS set NEW_IP_ADDRESS=%NEW_IP_ADDRESS%:
for /F "tokens=1,2 delims=:" %%i in ("%~1") do (
  if x%%j==x (
    call :set_url_schema %NEW_IP_ADDRESS%%%i
    goto final
  )
  if x%%i==x0.0.0.0 (
    call :set_url_schema %NEW_IP_ADDRESS%%%j
    goto final
  )
  call :set_url_schema %~1
  goto final
)


:set_url
set JS7_CONTROLLER_URL=
if exist "%JS7_CONTROLLER_DATA%\work\http-uri" (
  for /F "usebackq tokens=1,2 delims=/" %%i in (`type "%JS7_CONTROLLER_DATA%\work\http-uri"`) do set JS7_CONTROLLER_URL=%%i//%%j
)
if not defined JS7_CONTROLLER_URL call :set_controller_default_http_url
goto final


:set_controller_default_http_url
call :add_ip_address %JS7_CONTROLLER_HTTP_PORT% 127.0.0.1
set JS7_CONTROLLER_URL=http://%JS7_CONTROLLER_URL_SCHEMA%
goto final


:set_url_schema
set JS7_CONTROLLER_URL_SCHEMA=%~1
goto final


:finally
exit /b %ERRORLEVEL%

ENDLOCAL
:final