#!/bin/bash
# or
#!/bin/ksh
##
## Apache Tomcat Instance Creator
## Copyright (c) 2015-2018 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=""
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 $?
mkdir -p -m 0750 "$root$catalina_base" || exit $?
cd "$root$catalina_base" || exit $?

mkdir -m 0755 bin || exit $?

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

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

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 $?

cat <<EOF_TOMCAT_CONF >conf/tomcat.conf || exit $?
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"

if [ -z "\${HEAPSIZE:-}" ] && [ -f /proc/meminfo ]; then
  memorysize="\$(awk '\$1=="MemTotal:" { print int(\$2 / 1024); exit }' /proc/meminfo)"
  if [ -n "\$memorysize" ] && [ "\$memorysize" -ge 4096 ]; then
    HEAPSIZE="\$((\${memorysize} * \${HEAPSIZE_RATIO:-50} / 100))M"
  fi
fi

JAVA_HOME="$java_home"
JAVA_OPTS="\\
  -Djava.awt.headless=true \\
  -Djava.security.egd=file:/dev/urandom \\
  -Xms\${HEAPSIZE:-2048M} \\
  -Xmx\${HEAPSIZE:-2048M} \\
  -XX:MetaspaceSize=256M \\
  -XX:MaxMetaspaceSize=256M \\
  -XX:+UseConcMarkSweepGC \\
  -XX:-MaxFDLimit \\
"

## Java Security Manager
#SECURITY_MANAGER="true"

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

## See also tomcat.conf.pre.d/*.conf and tomcat.conf.d/*.conf files if any
EOF_TOMCAT_CONF

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

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

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

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

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

exit 0
