#!/bin/sh -e

# This is a script for modifying JServ's configuration files - it can be
# used by the local sysadmin or by other packages to automatically set them
# up. It can perform 3 basic tasks:
#
# 1. Add/remove a JAR file (or a directory) from the JVM's classpath
# 2. Add/remove a file ending mapping to a servlet
# 3. Add/remove servlet parameters in the root servlet zones
#
# Note: This script does not activate the changes made to Apache.

# JServ's main configuration file
jservconf="/etc/jserv/jserv.conf"

# The servlet zone to which file extensions are mapped and where servlet
# parameters are added
jservzone="root"


echo_debug() {
    if [ "$debug" = "true" ]; then
	echo "DEBUG: " $*
    fi
}


checkConfigfile() {

    # This function tests/sets the following variables:
    # $jservconf  JServ's configuation file (usually /etc/jserv/jserv.conf)
    # $jservprop  JServ's properties file (usually /etc/jserv/jserv.properties)
    # $jervzone   The name of the servlet zone to modify (usually root)
    # $zonemnt    The mount point (part of the URL) of this servlet zone
    #             (usually /servlets)
    # $zoneprop   The zone's properties file (usually
    #             /etc/jserv/zones/root.properties)

    if ! grep -q "^ApJServProperties" $jservconf; then
	echo >&2 "Invalid JServ configuration file $jervconf!"
	exit 1
    fi

    # Look for the properties file (parameter ApJServProperties inside the
    # configuration file)
    jservprop=`grep "^ApJServProperties" $jservconf | cut -d\  -f2`
    if [ ! -e $jsersvprop ]; then
	echo >&2 "Invalid JServ properties file $jservprop!"
	exit 1
    fi

    # Get the first mount point and properties file of our servlet zone
    zonemnt=`grep "^ApJServMount[[:space:]]\+/.*[[:space:]]\+/$jservzone$" $jservconf | head -1 | cut -d\  -f2`
    if [ "x$zonemnt" = "x" ]; then
	echo >&2 "Could not find a mount point for the $jservzone zone in $jservconf!"
	exit 1
    else
	zoneprop=`grep "^$jservzone.properties=" $jservprop | cut -d= -f2`
	if [ "x$zoneprop" = "x" ]; then
	    echo >&2 "Could not find the properties file for the $jservzone zone in $jservprop!"
	    exit 1
	fi
	echo_debug "$jservzone's mount point is $zonemnt ..."
	echo_debug "... and its properties file is $zoneprop"
    fi
}


insertHttpdConf() {
    apacheconf=$1
    if ! grep -q "^Include[[:space:]]\+$jservconf" $apacheconf; then
	echo_debug "Adding JServ configuration section to $apacheconf"
	echo >> $apacheconf "<IfModule mod_jserv.c>"
	echo >> $apacheconf "# The following line is for apacheconfig - DO NOT REMOVE!"
	echo >> $apacheconf "ApJServLogFile DISABLED"
	echo >> $apacheconf "Include /etc/jserv/jserv.conf"
	echo >> $apacheconf "</IfModule>"
	echo "done."
    else
	echo_debug "JServ configuration section already present in $apacheconf"
    fi
}


removeHttpdConf() {
    apacheconf=$1
    # Remove all lines from <IfModule mod_jserv.c> to </IfModule>
    if grep -q "^Include[[:space:]]\+$jservconf" $apacheconf; then
	echo_debug "Removing JServ configuration section from $apacheconf"
	perl -00 -p -i -e "s:<IfModule mod_jserv.c>\n(.*\n)+</IfModule>\n?::" $apacheconf
    else
	echo_debug "No JServ configuration section found in $apacheconf"
    fi
}


# Beginning of main program: Parse options first

if [ "$1" = "-d" -o "$1" = "--debug" ]; then
    debug="true"
    shift
else
    debug="false"
fi
case "$1" in
    add-apache)
	if [ -x /usr/sbin/apacheconfig ]; then
	    insertHttpdConf /etc/apache/httpd.conf
	    /usr/sbin/apacheconfig --force-modules --fullauto
	fi
	if [ -x /usr/sbin/apache-sslconfig ]; then
	    insertHttpdConf /etc/apache-ssl/httpd.conf
	    /usr/sbin/apache-sslconfig --force-modules --fullauto
	fi
    ;;

    remove-apache)
	if [ -x /usr/sbin/apacheconfig ]; then
	    removeHttpdConf /etc/apache/httpd.conf
	    /usr/sbin/apacheconfig --force-modules --fullauto
	fi
	if [ -x /usr/sbin/apache-sslconfig ]; then
	    removeHttpdConf /etc/apache-ssl/httpd.conf
	    /usr/sbin/apache-sslconfig --force-modules --fullauto
	fi
    ;;

    add-classpath)
	checkConfigfile
	shift

	for path in $*; do
	    if grep -q "^wrapper.classpath=$path" $jservprop; then
		echo_debug "$path is already in $jservprop's classpath!"
	    else
                echo_debug "Adding $path to $jservprop's classpath"
	        # Replace the largest block of (commented) lines
		# "wrapper.classpath=...\n" with this block and an additional
		# line, i.e. add our line to the end of this block. I have to
		# use \1 instead of $1 in the replacing expression because
		# otherwise $1 would be relaced by the shell and I can't use
		# single quoted either because some variables have to be
		# replaced
		perl -00 -p -i -e "s:(\n([#\s]*wrapper.classpath\s*=\s*.*\n)+):\1wrapper.classpath=$path\n:" $jservprop
	    fi
	done
    ;;

    remove-classpath)
	checkConfigfile
	shift

	for path in $*; do
	    if grep -q "^wrapper.classpath=$path" $jservprop; then
		echo_debug "Removing $path from $1's classpath"
		perl -p -i -e "s:^wrapper.classpath=$path.*\n::" $jservprop
	    else
		echo_debug "$path is not in $jservprop's classpath!"
	    fi
	done
    ;;

    add-mapping)
	checkConfigfile
	if [ "x$2" == "x" -o "x$3" == "x" ]; then
	    echo >&2 "Required argument for add-mapping command missing!"
	    exit 1
	fi
	fileext=$2; urlpath="$zonemnt/$3"

	# First check if there is already a commented entry with this mapping:
	# yes: Remove comment from this entry (possibly overwriting the old
	#      urlpath)
	#  no: create a new entry after all other ApJServAction statements
	if ! grep -q "^ApJServAction[[:space:]]\+\.$fileext" $jservconf; then
	    if grep -q "^#[#[:space:]]*ApJServAction[[:space:]]\+\.$fileext" $jservconf; then
		echo_debug "Activating *.$fileext mapping to $urlpath"
		perl -p -i -e "s:#[#\s]*(ApJServAction\s+\.$fileext\s+).*:\1$urlpath:" $jservconf
	    else
		echo_debug "Adding *.$fileext mapping to $urlpath" 
		perl -00 -p -i -e "s:(\n([#\s]*ApJServAction.*\n)+):\1ApJServAction .$fileext $urlpath\n:" $jservconf
	    fi
	else
	    echo_debug "$fileext mapping already present in $jservconf"
	fi
    ;;

    remove-mapping)
	checkConfigfile
	if [ "x$2" == "x" ]; then
	    echo >&2 "Required argument for remove-mapping command missing!"
	    exit 1
	fi
	fileext=$2

	if grep -q "^ApJServAction[[:space:]]\+\.$fileext" $jservconf; then
	    echo_debug "Removing $fileext mapping from $jservconf"
	    perl -p -i -e "s:^(ApJServAction\s+\.$fileext.*\n):#\1:" $jservconf
	else
	    echo_debug "$fileext mapping not present in $jservconf"
	fi
    ;;

    add-option)
	checkConfigfile
	if [ "x$2" == "x" -o "x$3" == "x" ]; then
	    echo >&2 "Required argument for add-option command missing!"
	    exit 1
	fi
	option=$2; parameter=$3; value=$4
	to_add="$option=$parameter"
	if [ "x$value" != "x" ]; then
	    to_add="$to_add=$value"
	fi

	# What to do if no value is submitted? This implies an a=b constuct
	# (as opposed to a=b=c). If we have no value, we should probaby
	# replace the whole line (or issue a warning) -- <stefan@alfredsson.org>

	# Check if there is already a line with this option present, if so
	# add $parameter=$value to this option (or substitue the old value)
	if grep -q "^$option=" $zoneprop; then
	    if grep -q "^$option=.*$parameter=" $zoneprop; then
	        perl -p -i -e "s:^($option=.*)$parameter=.*?([,\n]):\1$parameter=$value\2:" $zoneprop
	    else
		# only add multiple parameters if we have a value, otherwise replace 
		# (dangerous? might wipe other scripts changes. but so does remove...)
		if [ "x$value" != "x" ]; then
		    perl -p -i -e "s:^($option=.*)\n:\1,$parameter=$value\n:" $zoneprop
		else
		    perl -p -i -e "s:^$option=.*\n:$to_add\n:" $zoneprop
		fi
	    fi
	else
	    echo >> $zoneprop "$to_add"
	fi
    ;;

    remove-option)
	checkConfigfile
	if [ "x$2" == "x" ]; then
	    echo >&2 "Required argument for remove-option command missing!"
	    exit 1
	fi
	option=$2; parameter=$3

	if [ "x$parameter" == "x" ]; then
	    # Remove the whole line
	    perl -p -i -e "s:^$option=.*\n::" $zoneprop
	else
	    # The 2nd substitution is in case this paramter is the last one,
	    # the 3rd one in case this parameter is the onle one
	    perl -p -i -e "s:^($option=.*)$parameter=.+?,:\1:; s:^($option=.*),$parameter=.+:\1:; s:^$option=$parameter=.+\n::" $zoneprop
	fi
    ;;

    *)
	echo >&2 "Usage: `basename $0` [options] command [arguments]"
	echo >&2 ""
	echo >&2 "Possible options are:"
	echo >&2 "-d/--debug                             Print debug messages"
	echo >&2 ""
	echo >&2 "Possible commands are:"
	echo >&2 "add-apache                             Include JServ into Apache's configuration"
	echo >&2 "remove-apache                          Remove JServ from Apache's configuration"
	echo >&2 "add-classpath <path> ...               Add <path> to JServ's JVM classpath"
	echo >&2 "remove-classpath <path> ...            Remove <path> from JServ's JVM classpath"
	echo >&2 "add-mapping <fileext> <urlpath>        Add a mapping for *.fileext to urlpath"
	echo >&2 "remove-mapping <fileext>               Remove the mapping for *.fileext"
	echo >&2 "add-option <option> <param> [<value>]  Add <option> to the root servlet zone"
	echo >&2 "remove-option <option> [<parameter>}    Remove <option> from the root servlet zone"
	exit 1
	;;
esac

exit 0
