#!/bin/bash
##
## (C) Copyright 2010-2015 Nuxeo SA (http://nuxeo.com/) and contributors.
##
## All rights reserved. This program and the accompanying materials
## are made available under the terms of the GNU Lesser General Public License
## (LGPL) version 2.1 which accompanies this distribution, and is available at
## http://www.gnu.org/licenses/lgpl-2.1.html
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## Contributors:
##     Julien Carsique
##     Florent Guillaume
##     Mathieu Guillaume
##
## Shell script calling a multi-OS Nuxeo Java launcher.
## Using explicitely bash to avoid dash which is not POSIX.
##
MAX_FD_LIMIT_HELP_URL="http://doc.nuxeo.com/display/KB/java.net.SocketException+Too+many+open+files"

: ${NUXEO_HOME:=$(cd "$(dirname "$0")"/..; pwd -P)}
: ${NUXEO_CONF:="$NUXEO_HOME"/bin/nuxeo.conf}

## Backward compatibility
cmdargs=( "$@" )
for ((i=0; i<$#; i++)); do
  if [ "${cmdargs[$i]}" = "nogui" ]; then
    cmdargs[$i]="--gui=false"
  elif [ "${cmdargs[$i]}" = "--debug-launcher" ]; then
    LAUNCHER_DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=8788,server=y,suspend=y"
    unset cmdargs[$i]
  fi
done
set -- "${cmdargs[@]}"

## Helper functions
warn() {
  echo "WARNING: $*"
}

die() {
  echo "ERROR: $*"
  exit 1
}


## OS detection
cygwin=false
darwin=false
#linux=false
case "`uname`" in
  CYGWIN*) cygwin=true;;
  Darwin*) darwin=true;;
  #Linux) linux=true;;
esac

## Empty $GREP_OPTIONS to prevent some undesirable behaviors
GREP_OPTIONS=""

## Check for DOS CRLF
if grep $'\r' "$NUXEO_CONF" >/dev/null 2>&1 ; then
  warn "Found DOS CRLF in $NUXEO_CONF! Fixing in a temporary file..."
  sed 's/\r//' "$NUXEO_CONF" > "$NUXEO_CONF.fixed"
  NUXEO_CONF="$NUXEO_CONF.fixed"
fi

## Setup the JVM (find JAVA_HOME if undefined; use JAVA if defined)
while read line; do
  case $line in
    JAVA_HOME=*) JAVA_HOME="$(echo $line | cut -d= -f2-)" ;;
  esac
done << EOF
`grep "^JAVA_HOME=" "$NUXEO_CONF"`
EOF
if [ -z "$JAVA" ]; then
  JAVA=java
fi
if [ -z "$JAVA_HOME" ]; then
  JAVA=`command -v $JAVA`
  # follow symlinks
  while [ -h "$JAVA" ]; do
    ls=`ls -ld "$JAVA"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    case "$link" in
      /*) JAVA="$link" ;;
      *)  JAVA=`dirname "$JAVA"`/"$link" ;;
    esac
  done
  JAVA_HOME=`dirname "$JAVA"`
  JAVA_HOME=`dirname "$JAVA_HOME"`
fi
PATH="$JAVA_HOME/bin:$PATH"

# Check Java
: ${REQUIRED_JAVA_VERSION:=1.7}
# Check 'java' bin
which java >/dev/null 2>&1 || die "Nuxeo requires Java $REQUIRED_JAVA_VERSION+. No java command detected in the PATH (including JAVA_HOME)."
# Check Java version
JAVA_VERSION=`java -version 2>&1 | awk -F '"' '/version/{print $2}'`
if [ "$JAVA_VERSION" \< "$REQUIRED_JAVA_VERSION" ]; then
  die "Nuxeo requires Java $REQUIRED_JAVA_VERSION+ (detected $JAVA_VERSION)"
fi

## Setup JAVA_OPTS
while read line; do
  case $line in
    JAVA_OPTS=*)
      line=$(echo $line | cut -d= -f2-)
      # expand $JAVA_OPTS
      case $line in
        \$JAVA_OPTS*) JAVA_OPTS="$JAVA_OPTS $(echo $line | cut -c 12-)" ;;
        *) JAVA_OPTS="$line" ;;
      esac
      ;;
  esac
done << EOF
`grep "^JAVA_OPTS=" "$NUXEO_CONF"`
EOF
# Defaults
: ${JAVA_OPTS:="-Xms512m -Xmx1024m -XX:MaxPermSize=512m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dfile.encoding=UTF-8"}
# Force IPv4
JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"

if [[ ! "x$@" =~ --gui=true ]] && [[ ! "x$@" =~ " gui" ]]; then
  # Set AWT headless
  JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"
fi

# Set -server if possible
if ! [[ "x$JAVA_OPTS" =~ -server ]]; then
  # Enable -server if we have HotSpot
  if [[ x`"$JAVA" -version 2>&1` =~ HotSpot ]]; then
    "$JAVA" -server -version >/dev/null 2>&1
    if [ $? -eq 0 ]; then
      JAVA_OPTS="-server $JAVA_OPTS"
    fi
  fi
fi

## OS specific checks
# Check file descriptor limit is not too low
if [ $cygwin = false ]; then
  MAX_FD_LIMIT=`ulimit -H -n`
  if [ $? -eq 0 ]; then
    if [ $darwin = true ] && [ "$MAX_FD_LIMIT" = "unlimited" ]; then
      MAX_FD_LIMIT=`sysctl -n kern.maxfilesperproc`
      ulimit -n $MAX_FD_LIMIT
    fi
    if [ $MAX_FD_LIMIT -lt 2048 ]; then
      warn "Maximum file descriptor limit is too low: $MAX_FD_LIMIT"
      warn "See: $MAX_FD_LIMIT_HELP_URL"
    fi
  else
    warn "Could not get system maximum file descriptor limit (got $MAX_FD_LIMIT)"
  fi
fi


## nuxeo.log.dir
LOG_DIR=$(grep "^nuxeo.log.dir=" "$NUXEO_CONF" | cut -d= -f2-)
# Defaults
: ${LOG_DIR:="$NUXEO_HOME"/log}

## nuxeo.tmp.dir
TMP_DIR=$(grep "^nuxeo.tmp.dir=" "$NUXEO_CONF" | cut -d= -f2-)
# Defaults
: ${TMP_DIR:="$NUXEO_HOME"/tmp}
# TMPDIR is the canonical Unix environment variable specified in various Unix and similar standards
TMPDIR=$TMP_DIR
TMP=$TMP_DIR
TEMP=$TMP_DIR
TEMPDIR=$TMP_DIR
export TMP_DIR TMPDIR TMP TEMP TEMPDIR

# For Cygwin, ensure paths are in UNIX format before anything is touched
if [ "$cygwin" = "true" ]; then
  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath -am "$JAVA_HOME"`
  NUXEO_HOME=`cygpath -am "$NUXEO_HOME"`
  NUXEO_CONF=`cygpath -am "$NUXEO_CONF"`
  LOG_DIR=`cygpath -am "$LOG_DIR"`
  TMP_DIR=`cygpath -am "$TMP_DIR"`
fi


## Launcher
NUXEO_LAUNCHER="$NUXEO_HOME"/bin/nuxeo-launcher.jar
if [ ! -e "$NUXEO_LAUNCHER" ]; then
    die "Could not locate $NUXEO_LAUNCHER"
fi

[ -d "$LOG_DIR" ] || mkdir -p "$LOG_DIR"
echo "[`date`] Command: $0 $@" >> "$LOG_DIR"/nuxeoctl.log

[ -d "$TMP_DIR" ] || mkdir -p "$TMP_DIR"

while true; do
  while true; do
    TMPLAUNCHER="$TMP_DIR/nuxeo-launcher-$RANDOM.jar"
    if [ ! -f "$TMPLAUNCHER" ]; then
      break
    fi
  done
  cp "$NUXEO_LAUNCHER" "$TMPLAUNCHER"
  [[ "x $@" =~ " -d" || "x $@" =~ " --debug" || -n "$LAUNCHER_DEBUG" ]] && \
           echo "Launcher command: $JAVA $LAUNCHER_DEBUG -Dlauncher.java.opts=\"$JAVA_OPTS\" -Dnuxeo.home=\"$NUXEO_HOME\" -Dnuxeo.conf=\"$NUXEO_CONF\" -Dnuxeo.log.dir=\"$LOG_DIR\" -jar \"$TMPLAUNCHER\" $@"
  echo [`date`] "Launcher command: $JAVA $LAUNCHER_DEBUG -Dlauncher.java.opts=\"$JAVA_OPTS\" -Dnuxeo.home=\"$NUXEO_HOME\" -Dnuxeo.conf=\"$NUXEO_CONF\" -Dnuxeo.log.dir=\"$LOG_DIR\" -jar \"$TMPLAUNCHER\" $@" >> "$LOG_DIR"/nuxeoctl.log
  "$JAVA" $LAUNCHER_DEBUG -Dlauncher.java.opts="$JAVA_OPTS" -Dnuxeo.home="$NUXEO_HOME" -Dnuxeo.conf="$NUXEO_CONF" -Dnuxeo.log.dir="$LOG_DIR" -jar "$TMPLAUNCHER" "$@"
  exitcode=$?
  rm -f "$TMPLAUNCHER"
  if [ "$exitcode" != "128" ]; then
    break
  fi
done

exit $exitcode

