#!/bin/ksh
#
# Component: apache
#
# Purpose:
#    Control script of apache component
#
# Last Updated     : $Author$
# Update Date Time : $Date$
# RCS File Name    : $RCSfile$
# RCS Revision     : $Revision$
# Locked by        : $Locker$
# Symbolic name    : $Name$
# State            : $State$

#--- INIT ------------------------------
#needs $HOME
. "$HOME/etc/ctrl.main.shi"

[ -f "$HOME/etc/setenv.sh" ] && . "$HOME/etc/setenv.sh"

# Check if CONF/tomcat.cfg exists and pick up CATALINA_OPTS from this file
# CATALINA_OPTS is for passing extra options (eg. system properties) to tomcat java
# MUST be before apache/setenv.sh including, because apache/setenv.sh concatenates with its own options
[ -f "$CONF/tomcat.cfg" ] && . $CONF/tomcat.cfg

[ -f "$APACHE_HOME/setenv.sh" ] && . "$APACHE_HOME/setenv.sh"
[ -f "$ETC/virthost.sh" ] && . "$ETC/virthost.sh"


do_shell_()
{
	[ -z "$HTTP_PORT" ] && HTTP_PORT=`if [ develop = \$USER ]; then echo 8080; else echo 80; fi`
	[ -z "$HTTPS_PORT" ] && HTTPS_PORT=`if [ develop = \$USER ]; then echo 8443; else echo 443; fi`
	[ -z "$TOMCAT_PORT" ] && TOMCAT_PORT=`if [ develop = \$USER ]; then echo 8890; else echo 8090; fi`
	[ -z "$JSERV_PORT" ] && JSERV_PORT=`if [ develop = \$USER ]; then echo 8807; else echo 8007; fi`
	[ -z "$JSERV_HOST" ] && JSERV_HOST=localhost
	[ -z "$JSERV_BIND" ] && JSERV_BIND=127.0.0.1
	[ -z "$APACHE_LOGLEVEL" ] && APACHE_LOGLEVEL=warn

	cat <<-EndOfInlineData
		APACHE_HOME=\$HOME/component/apache
		TOMCAT_HOME=\$HOME/component/apache/tomcat
		TOMCAT_INITFILE=$TOMCAT_INITFILE
		CATALINA_HOME=\$TOMCAT_HOME
		CATALINA_TMPDIR=\$TMP
		CATALINA_PID=\$RUN/tomcat.pid
		APACHE_LOGS=\$LOG/apache
		APACHE_PIDFILE=\$RUN/httpd.pid
		APACHE_VAR=$APACHE_VAR
		APACHE_CONF_VAR=$APACHE_CONF_VAR
		APACHE_CONF_TPL=$APACHE_CONF_TPL
		TOMCAT_VAR=\$APACHE_VAR/tomcat
		TOMCAT_WORK=\$TOMCAT_VAR/work
		TOMCAT_WEBAPPS=\$TOMCAT_HOME/webapps
		TOMCAT_LOGS=\$APACHE_LOGS/tomcat
		DOCUMENT_ROOT=\$HOME/htdocs
		EXECUTER_PARAMS='maxThreads="350" minSpareThreads="25"'
		CONNECTOR_PARAMS='executor="tomcatThreadPool" connectionTimeout="600000" secretRequired="false"'
		HOST_PARAMS='unpackWARs="false" autoDeploy="true" deployXML="true" startStopThreads="15"'
		HTTP_PORT=$HTTP_PORT
		HTTPS_PORT=$HTTPS_PORT
		TOMCAT_PORT=$TOMCAT_PORT
		JSERV_PORT=$JSERV_PORT
		JSERV_HOST=$JSERV_HOST
		JSERV_BIND=$JSERV_BIND
		APACHE_LOGLEVEL=$APACHE_LOGLEVEL
		CLASSPATH="\$CLASSPATH:\$TOMCAT_HOME/lib/servlet-api.jar:\$TOMCAT_HOME/lib/jsp-api.jar:\$TOMCAT_HOME/lib/el-api.jar"
	EndOfInlineData

} #do_shell_()

do_start_()
{
	CWD="`pwd`"
	cd "$APACHE_HOME"
	# Make a symlink to ~/var/apache/log
	if [ ! -d "$APACHE_LOGS" ]; then mkdir -p "$APACHE_LOGS" ; fi
	if [ -d "$APACHE_HOME/logs" ]; then rm -rf "$APACHE_HOME/logs" ; fi
	[ -L "logs" ] && rm -f logs
	ln -sf "$APACHE_LOGS" logs

	cd "$TOMCAT_HOME/webapps"
	# Make a symlink to ~/htdocs/
	if [ -d "ROOT" -a ! -L "ROOT" ]; then rm -rf "ROOT"; fi
	[ -L "ROOT" ] && rm -f "ROOT"
	ln -sf "$HOME/htdocs" "ROOT"

	cd "$TOMCAT_HOME"
	# Make a symlink to ~/var/apache/tomcat/log
	mkdir -p $TOMCAT_LOGS
	if [ -d "$TOMCAT_HOME/logs" -a ! -L "$TOMCAT_HOME/logs" ]; then
		mv -f $TOMCAT_HOME/logs/* $TOMCAT_LOGS/
		rm -rf "$TOMCAT_HOME/logs"
	fi
	[ -L "logs" ] && rm -f logs
	ln -sf "$TOMCAT_LOGS" logs

	# Make a symlink to ~/var/apache/tomcat/work
	if [ -d "$TOMCAT_HOME/work" -a ! -L "$TOMCAT_HOME/work" ]; then
		rm -rf "$TOMCAT_HOME/work"
	fi

	[ ! -d "$TOMCAT_WORK" ] && mkdir -p "$TOMCAT_WORK"
	[ -L "work" ] && rm -f work
	ln -sf "$TOMCAT_WORK/" work


	cd "$HOME/htdocs"
	if [ ! -e "WEB-INF" ]; then mkdir "WEB-INF"; fi
	if [ -d "WEB-INF" -a ! -e "WEB-INF/classes" ]; then mkdir "WEB-INF/classes"; fi

	if [ -f $APACHE_VAR/conf.tpl/tomcat/conf/server.xml ]; then
		# custom server.xml that might need patching for scifilter
		if patch --dry-run -N $APACHE_VAR/conf.tpl/tomcat/conf/server.xml -r - < $APACHE_HOME/server.xml.scifilter.patch 2>&1 >/dev/null; then
			echo
			echo "Patching custom server.xml template for containerSciFilter:"
			patch -b -N $APACHE_VAR/conf.tpl/tomcat/conf/server.xml -r - < $APACHE_HOME/server.xml.scifilter.patch
			echo
		fi
	fi

	cd "$APACHE_CONF_TPL"
	if [ 0 != $? ]; then
		echo "Cannot change directory to '$APACHE_CONF_TPL'!"
		exit 1
	fi

	# Check debug config opts
	case $CONNECTOR_LOGLEVEL in
		!(info|error|debug|))
			echo -e "Warning: invalid \$CONNECTOR_LOGLEVEL value: \"$CONNECTOR_LOGLEVEL\". \nAllowed: info (default), error, debug." >&2
			CONNECTOR_LOGLEVEL=""
		;;
	esac
	[ -z "$CONNECTOR_LOGLEVEL" ] && CONNECTOR_LOGLEVEL=info

	case $TOMCAT_DEBUG in
		!(0|1|))
			echo -e "Warning: invalid \$TOMCAT_DEBUG value: \"$TOMCAT_DEBUG\". \nAllowed: 0 (default), 1." >&2
			TOMCAT_DEBUG=""
		;;
	esac
	[ -z "$TOMCAT_DEBUG" ] && TOMCAT_DEBUG=0

	case $APACHE_LOGLEVEL in
		!(debug|info|notice|warn|error|crit|alert|emerg|))
			echo -e "Warning: invalid \$APACHE_LOGLEVEL value: \"$APACHE_LOGLEVEL\". \nAllowed: debug, info, notice, warn (default), error, crit, alert, emerg." >&2
			APACHE_LOGLEVEL=""
		;;
	esac



	echo -n "Parsing config templates..."
	for m in conf tomcat/conf; do
		if [ -d "$APACHE_HOME/$m" ]; then rm -rf "$APACHE_HOME/$m"
		elif [ -L "$APACHE_HOME/$m" ]; then rm -f "$APACHE_HOME/$m"; fi
		rm -rf $APACHE_VAR/$m; mkdir -p $APACHE_VAR/$m
		ln -sf $APACHE_VAR/$m $APACHE_HOME/$m
	done

	EXTRA_JKMOUNTS=""
	for jkm in $SERVLETS_JKMOUNTS; do
	    EXTRA_JKMOUNTS="$EXTRA_JKMOUNTS\\nJkMount $jkm worker1"
	done

	# process files in template dir, then check for support overrides in var
	
	for tpldir in $APACHE_CONF_TPL $APACHE_VAR/conf.tpl; do
	    [ ! -d $tpldir ] && continue;
	    cd $tpldir
	    for n in `find -type f`; do
			sed -e "
s,@APACHE_HOME@,$APACHE_HOME,g
s,@TOMCAT_HOME@,$TOMCAT_HOME,g
s,@JDK_HOME@,$JDK_HOME,g
s,@JSDK_HOME@,$JSDK_HOME,g
s,@JAVA_HOME@,$JAVA_HOME,g
s,@CLASSPATH@,$CLASSPATH,g
s,@SERVERNAME@,$SERVERNAME,g
s,@SERVERIP@,$SERVERIP,g
s,@BINDIP@,$BINDIP,g
s,@APACHE_PIDFILE@,$APACHE_PIDFILE,g
s,@APACHE_CONF@,$APACHE_CONF_VAR,g
s,@APACHE_CONF_VAR@,$APACHE_CONF_VAR,g
s,@APACHE_CONF_TPL@,$APACHE_CONF_TPL,g
s,@LOGNAME@,$LOGNAME,g
s,@USERNAME@,$USERNAME,g
s,@HOME@,$HOME,g
s,@HTTP_PORT@,$HTTP_PORT,g
s,@HTTPS_PORT@,$HTTPS_PORT,g
s,@TOMCAT_PORT@,$TOMCAT_PORT,g
s,@TOMCAT_WORK@,$TOMCAT_WORK@,g
s,@TOMCAT_VAR@,$TOMCAT_VAR,g
s,@TOMCAT_WEBAPPS@,$TOMCAT_WEBAPPS,g
s,@TOMCAT_LOGS@,$TOMCAT_LOGS,g
s,@DOCUMENT_ROOT@,$DOCUMENT_ROOT,g
s,@JSERV_PORT@,$JSERV_PORT,g
s,@JSERV_HOST@,$JSERV_HOST,g
s,@JSERV_BIND@,$JSERV_BIND,g
s,@APACHE_LOGS@,$APACHE_LOGS,g
s,\$EXECUTER_PARAMS,$EXECUTER_PARAMS,g
s,\$CONNECTOR_PARAMS,$CONNECTOR_PARAMS,g
s,\$HOST_PARAMS,$HOST_PARAMS,g
s,@SSL_CRT_DIR@,,g
s,@SSL_KEY_DIR@,,g
s,@SSL_CRL_DIR@,,g
s,@SSL_PRM_DIR@,,g
s,@SSL_CSR_DIR@,,g
s,@SSL_SITE_CERT@,,g
s,@SSL_SITE_KEY@,,g
s,@OPENSSL_CA_DIR@,$OPENSSL_CA_DIR,g
s,@OPENSSL_EIMCA_CRL@,$OPENSSL_EIMCA_CRL,g
s,@OPENSSL_PRIVKEY@,$OPENSSL_PRIVKEY,g
s,@OPENSSL_CERT_DIR@,$OPENSSL_CERT_DIR,g
s,@OPENSSL_CERT_DEFAULT@,$OPENSSL_CERT_DEFAULT,g
s,@OPENSSL_CA_BUNDLE@,$OPENSSL_CA_BUNDLE,g
s,@SSL_CA_CERT@,$SSL_CA_CERT,g
s,@OPENSSL_PASS@,$OPENSSL_PASS,g
s,@CONNECTOR_LOGLEVEL@,$CONNECTOR_LOGLEVEL,g
s,@TOMCAT_DEBUG@,$TOMCAT_DEBUG,g
s,@APACHE_LOGLEVEL@,$APACHE_LOGLEVEL,g
s,@SERVLET_JKMOUNTS@,$EXTRA_JKMOUNTS,g
s,@JETTY_PORT@,$JETTY_PORT,
s,@JETTY_PORT_SECURE@,$JETTY_PORT_SECURE,g


" < "$tpldir/$n" > "$APACHE_HOME/$n.tmp"
		chmod --reference="$tpldir/$n" "$APACHE_HOME/$n.tmp"
		rm -f "$APACHE_HOME/$n"
		mv -f "$APACHE_HOME/$n.tmp" "$APACHE_HOME/$n"
	    done
	done
	echo

	export CATALINA_OPTS="$CATALINA_OPTS $LOG4J_ARGS -XX:+CreateCoredumpOnCrash -XX:+StartAttachListener"

	if [ "$1" = "debug" ] ; then
		cat <<-ENDDICOMOPTION > $RUN/tomcat.options
			PB_WITH_JPDA="jpda"
			export JPDA_ADDRESS="*:8000"
		ENDDICOMOPTION
	elif [ "$1" = "nodebug" ] ; then
		[ -f "$RUN/tomcat.options" ] && rm $RUN/tomcat.options
	fi



	cd "$APACHE_HOME"
	$ASROOT apache.asr start

	cd "$TOMCAT_HOME"
	# Remove tomcat work files before startup

	if [ "$TOMCAT_WORK" != "" -a -d "$TOMCAT_WORK/." ]; then
		echo "Purging Tomcat work files..."
		rm -rf $TOMCAT_WORK/*
	fi
#	if $APACHE_HOME/tomcatw.sh >/dev/null 2>&1; then
	if bin/startup.sh >/dev/null 2>&1; then
		PB_WITH_JPDA=""
		[ -f "$RUN/tomcat.options" ] && . "$RUN/tomcat.options"
		if [ "$PB_WITH_JPDA" = "jpda" ] ; then
			echo "Tomcat is started with jpda enabled."
		else
			echo "Tomcat is started."
		fi
	else
		echo "Tomcat isn't started!"
	fi

	# start a full recompile of all jsp files
#	echo "$TOOLS_HOME/recompile.sh >$HOME/tmp/recompile.log 2>&1" | at now + 2 min

	cd "$CWD"
} #do_start_()

do_stop_()
{
	CWD=`pwd`
	cd $TOMCAT_HOME
	if bin/shutdown.sh 2>&1 > /dev/null; then
		echo "Tomcat stopped."
	else
		echo "Tomcat isn't stopped or not running!"
	fi

	# wait for a bit for tomcat to stop
	if [ -f "$CATALINA_PID" ]; then
		pid=$(cat "$CATALINA_PID")
		$ETC/waitpid.sh $pid 5
	fi

	[ -f "$CATALINA_PID" ] && rm -f $CATALINA_PID

	cd "$CWD"
	$ASROOT apache.asr stop
} #do_stop_()

do_status_()
{
	if [ ! -f "$APACHE_PIDFILE" -a ! -f "$CATALINA_PID" ] ; then
		echo "STOPPED"
		return
	fi
	
	if [ -f "$TOMCAT_INITFILE" ]; then
		if diff -b "$TOMCAT_INITFILE" "$CATALINA_PID" >/dev/null; then
		    echo "STARTING"
		    return 0
		else
		    echo "ERROR"
		    return 1
		fi
	fi

	
	checkstr=$$

	echo -n "$checkstr" > $HOME/htdocs/test1.$$.txt 2>&1
	if [ ! -f "$HOME/htdocs/apachestatus.jsp" ] ; then
		echo -n "<% out.print(request.getParameter(\"id\")); if (true) return; %>" \
				> $HOME/htdocs/apachestatus.jsp 2>&1
	fi

	$CURL_HOME/bin/curl -s -m 10 http://$SERVERNAME:$HTTP_PORT/test1.$$.txt > $TMP/test1.$$.txt 2>&1
	$CURL_HOME/bin/curl -s -m 30 http://$SERVERNAME:$HTTP_PORT/apachestatus.jsp?id=$checkstr > $TMP/test1.$$.jsp 2>&1

	STAT="OK"

  	[ "`cat $TMP/test1.$$.txt`" != "$checkstr" ] && STAT="ERROR"
  	[ "`cat $TMP/test1.$$.jsp`" != "$checkstr" ] && STAT="ERROR"

	rm $HOME/htdocs/test1.$$.txt

	rm $TMP/test1.$$.txt
	rm $TMP/test1.$$.jsp

	echo $STAT

} #do_status_()

do_emergency_()
{
	# stop apache and tomcat
	do_stop_

	# wait for the apache/tomcat processes to disappear from the ps list
	counter=0
	while true ; do
		sleep 10
		processes=`ps x | grep -e "h[t]tpd" -e "c[a]talina.startup"`
		[ -z "$processes" ] && break;

		# during the first 3 cycle check the processes only
		counter=$(( $counter + 1 ))
		[ $counter -le 3 ] && continue;

		# collect pids
		pids=`awk -vORS=" " '{print $1}' <<<"$processes"`

		# during the 4th and 5th cycle send a kill to the processes
		if [ $counter -le 5 ] ; then
			kill $pids
			continue
		fi

		# send kill -9 to the processes
		kill -9 $pids
	done

	# start apache and tomcat
	do_start_

} #do_emergency_()


do_beforesubmit_()
{
	do_stop_

} #do_beforesubmit_()

do_aftersubmit_()
{
	do_start_

} #do_aftersubmit_()


#
# Monitoring number of apache threads
#
do_monitor_()
{
	# Get the number of maximum threads from httpd.conf
	#	The defaults for our apache is 400. This comes for the following directives:
	#     MaxRequestWorkers 400 (16 x 25 = 400)
	#     ServerLimit 16
	#     ThreadsPerChild 25
	DefServerLimit=16
	DefThreadsPerChild=25
	
	ConfSettings=$(awk ' \
	BEGIN { a = 0; } \
		($1 == "</IfModule>") { inIfModule = 0 } \
		($1 == "<IfModule" && $2 == "mpm_event_module>") { inIfModule = 1; next; } \
		($1 == "MaxRequestWorkers" && inIfModule == 1) { MaxRequestWorkers=$2; next; } \
		($1 == "ServerLimit" && inIfModule == 1) { ServerLimit=$2; next; } \
		($1 == "ThreadsPerChild" && inIfModule == 1) { ThreadsPerChild=$2; next; } \
	END { print ServerLimit; print MaxRequestWorkers; print ThreadsPerChild }' $APACHE_CONF_VAR/httpd.conf)

	read -d "\n" ServerLimit MaxRequestWorkers ThreadsPerChild <<<"${ConfSettings}"
	
	if [ -z "$MaxRequestWorkers" ]; then
		[ -z "$ServerLimit" ] && ServerLimit=$DefServerLimit
		[ -z "$ThreadsPerChild" ] && ThreadsPerChild=$DefThreadsPerChild
		
		MaxRequestWorkers=$(( $ServerLimit * $ThreadsPerChild ))
	fi
	maxThreads=$MaxRequestWorkers

	# Number of current httpd processes
	numProc=$(ps -C httpd h -o "%u" | grep "\<$USER\>" | wc -l)

	echo "apache_thread_num=${numProc}"

	echo "${numProc} ${maxThreads}" | awk '{printf("apache_proc=%1.2f\n", $1 * 100 / $2);}'

	# Get the number of max threads from tomcat's server.xml
	#   need to process xml comments 
	#   in newer apache config it is maxThreads, in older ones, it is 
	#   maxProcesses. Looking for both.
	# 
	#   as with the apache config, we are looking at the processed config
	#   not the template. If overrides will be supported, that is transparent
	#   to us as the end result will be the same processed config file in var 
	tc_maxThreads=`awk '\
			BEGIN { inComment=0 }
			$0 ~ "<!--" && $0 !~ "<!--.*-->" { inComment=1 } \
			$0 ~ "-->"  && $0 !~ "<!--.*-->" { inComment=0 } \
			inComment ==0 && $0 ~ "(maxThreads|maxProcessors) *=" \
			   { print gensub(/^.*(maxThreads|maxProcessors) *="([0-9]+)".*$/,"\\\\2","g") ; } \
			' $TOMCAT_VAR/conf/server.xml`

	[ -z "$tc_maxThreads" ] && tc_maxThreads="1"

	# number of current tomcat threads
	tc_pid=$(ps auxwww | grep "^${USER}.*[c]atalina.start" | awk '{ print $2}')
	if [ -n "$tc_pid" ] ; then
		tc_numProc=$($JAVA_HOME/bin/jstack $tc_pid | grep -c catalina-worker)
	else
		tc_numProc=0
	fi

	echo "tomcat_thread_num=${tc_numProc}"

	echo "${tc_numProc} ${tc_maxThreads}" | awk '{printf("tomcat_proc=%1.2f\n", $1 * 100 / $2);}'
}

#
# List files/tables to be backed up grouped by categories
#
# output lines should be in '<category> <type> <names>' format
#
do_listbackup_()
{
	cat <<-EOFLISTBACKUP
		config.apache FILE ${APACHE_CONF_VAR#$HOME/}
		config.tomcat FILE ${TOMCAT_VAR#$HOME/}/conf
		nobackup.nobackup FILE ${TOMCAT_WORK#$HOME/}
	EOFLISTBACKUP
}



#
# Kills a process, and sends a kill -9 if the process does not terminate on regular kill
#
# $1 - pid of the process to kill
#
kill_() {
	local pid=$1

	[ -z "$1" ] && return

	if ps --pid "$pid" >/dev/null ; then
		kill $pid >/dev/null 2>/dev/null
		if ps --pid "$pid" >/dev/null ; then
			kill -9 $pid 2>/dev/null
		fi
	fi
}


#
# Executes a command and kills after a given timeout
#
# $1 - timeout seconds
# $@ - command and arguments to execute
#
timeout_() {
	local to
	local pid
	local waiter
	local exitcode

	to=$1
	shift

	# start the command in background
	( $@ 2>&1 ) & pid=$!


	# start a background process to kill command after timeout expired
	(sleep $to && kill_ $pid) & waiter=$!


	# wait for the command to complete
	wait $pid

	# exit code of the process - indicates whether it was killed or not
	exitcode=$?

	# kill the 'timeout killer' process if still runs
	kill_ $waiter

	return $exitcode
}


do_capture_()
{
	tomcatPID=`cat $CATALINA_PID`
	if [ -n "$tomcatPID" ] ; then
		kill -QUIT $tomcatPID
		timeout_ 10 $JAVA_HOME/bin/jstack $tomcatPID 2>/dev/null 
		if [ $? -ne 0 ] ; then
			timeout_ 10 $JAVA_HOME/bin/jstack -F $tomcatPID 2>/dev/null
			if [ $? -ne 0 ] ; then
				echo "Capturing tomcat threads failed"
			fi
		fi
	else 
		echo "No tomcat PID found" 
	fi
}
        
#--- MAIN ------------------------------

check_action_ $1
if [ 0 = $? ]; then
	cmd=$1
	shift
	do_${cmd}_ "$@"
else
	echo "--- Component apache [ ctrl $$ ] : Bad command: $1" >&2
	exit 1

fi
