#!/bin/bash
# or
#!/bin/ksh
##
## Apache Tomcat Instance Creator
## Copyright (c) 2015-2016 SATOH Fumiyasu @ OSS Technology Corp., Japan
##
## License: Apache License version 2.0
##

set -u
umask 0022

perr()
{
  echo "$0: ERROR: $1" 1>&2
}

pdie()
{
  perr "$1"
  exit "${2-1}"
}

getopts_want_arg()
{
  if [[ $# -lt 2 ]]; then
    pdie "Option requires an argument: $1"
  fi
  if [[ -n ${3:+set} ]]; then
    if [[ $2 =~ $3 ]]; then
      : OK
    else
      pdie "Invalid value for option: $1: $2"
    fi
  fi
  if [[ -n ${4:+set} ]]; then
    if [[ $2 =~ $4 ]]; then
      pdie "Invalid value for option: $1: $2"
    fi
  fi
}

ln_s_relative() {
  local root=""
  if [ $# -eq 3 ]; then
    local root="$1"; shift
  fi
  local target="$1"; shift
  local linkname="$1"; shift

  ## Refuse relative paths in arguments
  case "$target/$linkname" in
  .|..|./*|../*|*/./*|*/../*|*/.|*/..)
    echo "ln_s_relative: ERROR: Invalid argument" 1>&2
    return 1
    ;;
  esac
  if [ -n "${root##/*}" ] || [ -z "$target" ] || [ -n "${target##/*}" ] || [ -z "$linkname" ] || [ -n "${linkname##/*}" ]; then
    echo "ln_s_relative: ERROR: Invalid argument" 1>&2
    return 1
  fi

  if [ -d "$root$linkname" ]; then
    local dirname="$linkname"
  else
    local dirname=`/usr/bin/dirname "$linkname"`
  fi

  local root_from_linkname=`echo "$dirname" |/bin/sed 's#^/##;s#/$##;s#[^/][^/]*#..#g'`
  local target_relative="$root_from_linkname$target"

  [ "$dirname" = "/" ] && dirname=""
  /bin/ln -s "$target_relative" "$root$dirname/${linkname##*/}"
}

## ======================================================================

root=""
sv_name="tomcat"
instance_base="/opt/osstech/var/lib"
skel_dir="/opt/osstech/share/tomcat/skel"
catalina_home="${CATALINA_HOME-/usr/share/tomcat}"
tomcat_user="${TOMCAT_USER-tomcat}"
tomcat_group="${TOMCAT_GROUP-tomcat}"
java_home="${JAVA_HOME-/usr/lib/jvm/jre-openjdk}"
control_port="${CONTROL_PORT-8005}"
http_port="${HTTP_PORT-8080}"
ajp_port="${AJP_PORT-8009}"

sysconf_base=""
localstate_base=""

chgrp="${CHGRP-/bin/chgrp}"

while [[ $# -gt 0 ]]; do
  opt="$1"; shift

  if [[ -z "${opt##-[!-]?*}" ]]; then
    set -- "-${opt#??}" ${1+"$@"}
    opt="${opt%${1#-}}"
  fi
  if [[ -z "${opt##--*=*}" ]]; then
    set -- "${opt#--*=}" ${1+"$@"}
    opt="${opt%%=*}"
  fi

  case "$opt" in
  --root)
    getopts_want_arg "$opt" ${1+"$1"} ${1+"^/.*"}
    root="$1"; shift
    ;;
  --skel)
    getopts_want_arg "$opt" ${1+"$1"} ${1+"^/.*"}
    skel_dir="$1"; shift
    ;;
  --sysconf-base)
    getopts_want_arg "$opt" ${1+"$1"} ${1+"^/.*"}
    sysconf_base="$1"; shift
    ;;
  --localstate-base)
    getopts_want_arg "$opt" ${1+"$1"} ${1+"^/.*"}
    localstate_base="$1"; shift
    ;;
  --user)
    getopts_want_arg "$opt" ${1+"$1"}
    tomcat_user="$1"; shift
    ;;
  --group)
    getopts_want_arg "$opt" ${1+"$1"}
    tomcat_group="$1"; shift
    ;;
  --)
    break
    ;;
  -*)
    pdie "Invalid option: $opt"
    ;;
  *)
    set -- "$opt" ${1+"$@"}
    break
    ;;
  esac
done

## ----------------------------------------------------------------------

[[ -z $skel_dir ]] && skel_dir="$catalina_home"

## ----------------------------------------------------------------------

if [[ $# -lt 1 ]]; then
  echo "Usage: $0 [OPTIONS] INSTANCE_NAME [CATALINA_BASE]"
  exit 1
fi

instance_name="$1"; shift

if [[ -n ${1+set} ]]; then
  catalina_base="$1"; shift
else
  catalina_base="$instance_base/$instance_name"
fi

[[ -e $root$catalina_base ]] && pdie "Base directory already exists: $catalina_base"
#getent passwd "$tomcat_user" &>/dev/null || pdie "Unknown user: $tomcat_user"
[[ -z $tomcat_group ]] && tomcat_group=`id -g "$tomcat_user"`

if [[ -n $sysconf_base ]]; then
  sysconf_dir="$sysconf_base/$instance_name"
  [[ -e $root$sysconf_dir ]] && pdie "Sysconf directory already exists: $sysconf_dir"
fi

log_dir=""
cache_dir=""
if [[ -n $localstate_base ]]; then
  log_dir="$localstate_base/log/$instance_name"
  [[ -e $root$log_dir ]] && pdie "Log directory already exists: $log_dir"
  cache_dir="$localstate_base/cache/$instance_name"
  [[ -e $root$cache_dir ]] && pdie "Cache directory already exists: $cache_dir"
fi

## ======================================================================

mkdir -p -m 0755 "$root$catalina_base" || exit 1
cd "$root$catalina_base" || exit 1

mkdir -m 0755 bin || exit 1

mkdir -p -m 0755 conf lib || exit 1
mkdir -p -m 0755 conf/$sv_name.conf.d || exit 1
mkdir -p -m 0775 conf/Catalina || exit 1
mkdir -p -m 0775 conf/Catalina/localhost || exit 1
mkdir -p -m 0775 webapps || exit 1
mkdir -p -m 0770 logs logs/old work temp || exit 1
"$chgrp" -h "$tomcat_group" conf logs logs/old temp webapps work || exit 1
chmod g+s conf conf/Catalina conf/Catalina/localhost logs logs/old temp webapps work || exit 1

cp -p "$root$skel_dir/conf/"* conf/ || exit 1

sed \
  -e "s/\(<Server port=\"\)[0-9]*/\1$control_port/" \
  -e "s/\(<Connector port=\"\)[0-9]*\(\" protocol=\"HTTP\/\)/\1$http_port\2/" \
  -e "s/\(<Connector port=\"\)[0-9]*\(\" protocol=\"AJP\/\)/\1$ajp_port\2/" \
 "$root$skel_dir/conf/server.xml" \
>conf/server.xml || exit 1

cat <<EOF_TOMCAT_CONF >conf/$sv_name.conf || exit 1
NAME="$instance_name"

CATALINA_BASE="$catalina_base"
CATALINA_HOME="$catalina_home"
CATALINA_TMPDIR="$catalina_base/temp"

TOMCAT_USER="$tomcat_user"

LANG="en_US.UTF-8"

JAVA_HOME="$java_home"
JAVA_OPTS="-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom -Xms2048M -Xmx2048M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:+UseConcMarkSweepGC"

## Java Security Manager
#SECURITY_MANAGER="true"

## Java Platform Debugger Architecture
#JPDA="true"

## See also $sv_name.conf.d/*.conf files if any that are loaded after this file
EOF_TOMCAT_CONF

## ----------------------------------------------------------------------

if [[ -n $sysconf_base ]]; then
  mv conf "$root$sysconf_dir" || exit 1
  ln_s_relative "$root" "$sysconf_dir" "$catalina_base/conf" || exit 1
fi

if [[ -n $log_dir ]]; then
  mv logs "$root$log_dir" || exit 1
  ln_s_relative "$root" "$log_dir" "$catalina_base/logs" || exit 1
fi

if [[ -n $cache_dir ]]; then
  mkdir -p -m 0750 "$root$cache_dir" || exit 1
  chmod g+s "$root$cache_dir" || exit 1
  mv temp work "$root$cache_dir/" || exit 1
  ln_s_relative "$root" "$cache_dir/temp" "$catalina_base/temp" || exit 1
  ln_s_relative "$root" "$cache_dir/work" "$catalina_base/work" || exit 1
fi

## ======================================================================

exit 0

