#!/bin/bash

# Copyright (c) 2002-2012 "Neo Technology,"
# Network Engine for Objects in Lund AB [http://neotechnology.com]
#
# This file is part of Neo4j.
#
# Neo4j is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# getconfig <filename>
#   - plain key-value pairs become environment variables
#   - keys have '.' chars changed to '_'
#   - keys of the form KEY.# (where # is a number) are concatenated
#     into a single environment variable named KEY
function getconfig {
  if [ -e "$1" ]; then
    while read line ; do
      if [[ ${line} =~ ^([^#\s][^=]+)=(.+)$ ]]; then
        key=`echo ${BASH_REMATCH[1]} | sed 's/\./_/g'`
        value="${BASH_REMATCH[2]}"
        if [[ ${key} =~ ^(.*)_([0-9]+)$ ]]; then
          key=${BASH_REMATCH[1]}
          if [[ ${!key} ]]; then
            export ${key}="${!key} ${value}"
          else
            export ${key}="$value"
          fi
        else
          export ${key}="${value}"
        fi
      fi
    done < "$1"
  fi
}

function getconfigquoted {
  if [ -e "$1" ]; then
    while read line ; do
      if [[ ${line} =~ "^([^#\s][^=]+)=(.+)$" ]]; then
        key=`echo ${BASH_REMATCH[1]} | sed 's/\./_/g'`
        value="${BASH_REMATCH[2]}"
        if [[ ${key} =~ "^(.*)_([0-9]+)$" ]]; then
          key=${BASH_REMATCH[1]}
          if [[ ${!key} ]]; then
            export ${key}="${!key} ${value}"
          else
            export ${key}="$value"
          fi
        else
          export ${key}="${value}"
        fi
      fi
    done < "$1"
  fi
}

# Detect java and set JAVACMD on successful find.
findjava() {
  # OS specific support.  $var _must_ be set to either true or false.
  cygwin=false;
  darwin=false;
  case "`uname`" in
    CYGWIN*) cygwin=true ;;
    Darwin*) darwin=true
           if [ -z "$JAVA_VERSION" ] ; then
             JAVA_VERSION="CurrentJDK"
           else
             echo "Using Java version: $JAVA_VERSION"
           fi
           if [ -z "$JAVA_HOME" ] ; then
             JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home
           fi
           ;;
  esac

  if [ -z "$JAVA_HOME" ] ; then
    if [ -r /etc/gentoo-release ] ; then
      JAVA_HOME=`java-config --jre-home`
    fi
  fi

  # For Cygwin, ensure paths are in UNIX format before anything is touched
  if $cygwin ; then
    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
    [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
  fi

  # If a specific java binary isn't specified search for the standard 'java' binary
  if [ -z "$JAVACMD" ] ; then
    if [ -n "$JAVA_HOME"  ] ; then
      if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
      else
        JAVACMD="$JAVA_HOME/bin/java"
      fi
    else
      JAVACMD=`which java`
    fi
  fi
}

checkstatus() {
  if [ -e "$PID_FILE" ] ; then
    NEO4J_PID=$( cat "$PID_FILE" )
    kill -0 $NEO4J_PID 2>/dev/null || NEO4J_PID=
  fi
}

checkwriteaccess() {
    if [ $UID != 0 ] ; then
    if [ ! -w "$NEO4J_INSTANCE/data" ] ; then
      echo "ERROR: No write access to data/ directory, run either as user $NEO4J_USER or root"
      exit 1
    fi
    fi
}

reportstatus() {

  checkstatus
  detectos
  exitonnojava

  if [ $DIST_OS = "macosx" ] ; then
    getlaunchdpid
    if [ $LAUNCHDPID -gt 0 ] ; then
      echo "Instance running via launchd with PID $LAUNCHDPID"
      exit 0
    fi
    # We fall through here since if there is no launchd install we may be still running via script
  fi

  if [ -z $NEO4J_PID ] ; then
    echo "$FRIENDLY_NAME is not running"
  else
    echo "$FRIENDLY_NAME is running at pid $NEO4J_PID"
  fi
}

# Use findjava to set JAVACMD. If that fails ($JAVACMD is not set) then exit with failure
exitonnojava() {
  findjava
  if [ ! -x "$JAVACMD" ] ; then
    echo "Error: JAVA_HOME is not defined correctly."
    echo "  We cannot execute $JAVACMD"
    exit 1
  fi
}

# Resolve the os
detectos() {
  DIST_OS=`uname -s | tr [A-Z] [a-z] | tr -d ' '`
  case "$DIST_OS" in
    'sunos')
      DIST_OS="solaris"
      ;;
    'hp-ux' | 'hp-ux64')
      # HP-UX needs the XPG4 version of ps (for -o args)
      DIST_OS="hpux"
      UNIX95=""
      export UNIX95   
      ;;
    'darwin')
      DIST_OS="macosx"
      ;;
    'unix_sv')
      DIST_OS="unixware"
      ;;
    'os/390')
      DIST_OS="zos"
      ;;
    'cygwin')
      DIST_OS="cygwin"
      ;;
  esac
}

getlaunchdpid() {
  LAUNCHDPID=$(launchctl list | grep $LAUNCHD_NAME | cut -f 1)
  if [ -z $LAUNCHDPID ] ; then
    # Not there
    LAUNCHDPID=-1
  elif [ $LAUNCHDPID = "-" ] ; then
    # There but not running
    LAUNCHDPID=0
  else
    # There and running
    LAUNCHDPID=$(($LAUNCHDPID))
  fi
}

stopit() {

  detectos
  checkstatus
  checkwriteaccess

  if [ $DIST_OS = "macosx" ] ; then
    getlaunchdpid
    if [ $LAUNCHDPID -gt 0 ] ; then
      echo "Instance running via launchd with PID $LAUNCHDPID, stopping it..."
      launchctl stop $LAUNCHD_NAME
      return
    fi
    # We fall through here since if there is no launchd install we stop manually started instance
  fi

  if [ -z $NEO4J_PID ] ; then
    echo "ERROR: $FRIENDLY_NAME not running"
    [ -e "$PID_FILE" ] && rm "$PID_FILE"
  else
    printf "Stopping $FRIENDLY_NAME [$NEO4J_PID]..."
    x=0
    while [ $x -lt $TIMEOUT ] && [ "$NEO4J_PID" != "" ]  ; do
      kill $NEO4J_PID 2>/dev/null
      printf "."
      sleep 1
      checkstatus
      x=$[$x+1]
    done
	  [  $x -eq $TIMEOUT ] && ( echo " force shutdown" ;  kill -9 $NEO4J_PID >/dev/null ) || echo " done"
	  [ -e "$PID_FILE" ] && rm  "$PID_FILE"
  fi
}

# Creates a user on the system
create_user() {
  useradd -r $1
  modify_user_config $1 "true"
  echo "Created user \"${1}\"."
}

remove_user() {
  if [[ $wrapper_user_created == "true" ]]; then
    read -p "It appears that user \"${wrapper_user}\" was created during install. Remove that user now? [yN] " yn
    case $yn in
      [Yy]* ) deluser $wrapper_user
              modify_user_config "" created=true
        ;;
      * ) echo "OK, we'll let that user live, for now." 
        ;;
    esac
  else
    echo "$FRIENDLY_NAME was running as user \"${wrapper_user}\", which remains."
  fi
}

removeservice() {
    detectos
    checkstatus

    PLIST_FILE=$LAUNCHD_NAME.plist

    if [[ -d "/etc/init.d" ]]; then
      if [[ -e "/etc/init.d/${SERVICE_NAME}" ]]; then
        if [  $UID != 0 ] ; then
          eval echo  'Must be root to perform this action.'
          exit 1
        else
          if [ ! -z $NEO4J_PID ] ; then
            stopit
          fi
	  update-rc.d -f ${SERVICE_NAME} remove
          rm /etc/init.d/${SERVICE_NAME}
        fi
        # remove effective user, if created by install-script
        remove_user
      else
        echo "${SERVICE_NAME} not installed."
      fi

    elif [[ $DIST_OS -eq "macosx" ]] ; then
      if [[ -e ${LAUNCHD_DIR}/$PLIST_FILE ]]; then
        launchctl unload -w ${LAUNCHD_DIR}/$PLIST_FILE
        rm ${LAUNCHD_DIR}/$PLIST_FILE
      fi
    else
      echo "Sorry, don't know how to install on ${DIST_OS}."
    fi
}

# Runs before the server command, making sure that whatever should be in place is
# in place.
checkandrepairenv() {
    # Create data/log if missing, change owner if created.
    if [ ! -d "$NEO4J_HOME"/data/log ]; then
      echo "${NEO4J_HOME}/data/log was missing, recreating..."
      mkdir "$NEO4J_HOME"/data/log
      if [ $UID == 0 ] ; then
        chown $NEO4J_USER "$NEO4J_HOME"/data/log
      fi
    fi
}

# Checks system limits, warns if not proper
checklimits() {
	OPEN_FILES=`ulimit -n`
    if [ $OPEN_FILES -lt 40000 ]; then
	  echo "WARNING: Detected a limit of $OPEN_FILES for maximum open files, while a minimum value of 40000 is recommended."
	  echo "WARNING: Problems with the operation of the server may occur. Please refer to the Neo4j manual regarding lifting this limitation."
	fi
}
