#!/bin/sh -
#
#  $Id: runjava,v 1.5 2004/10/07 20:23:53 tarus Exp $
#
#
# Wrapper script for starting a JRE within OpenNMS.
# DJ Gregor
# Copyright (c) Daniel J. Gregor, Jr.
#    parts Copyright (c) The OpenNMS Group
# Tuesday, August 31, 2004
#
# Parts based on parseMib.sh, a Java MIB parser by David Hustace
# Copyright (c) The OpenNMS Group
# Friday, February 13, 2004
#
# This program 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# For more information contact:
#      OpenNMS Licensing       <license@opennms.org>
#      http://www.opennms.org/
#      http://www.opennms.com/
#

opennms_home="/usr/share/opennms"
searchdirs="/usr /opt /Library"

java_conf="$opennms_home/etc/java.conf"
basename="`basename $0`"

die(){
    echo "${basename}: $*" >&2
    exit 1
}
warn(){
    echo "${basename}: $*" >&2
}
tell(){
    echo "${basename}: $*" >&3
}


#
# Function: printHelp()
# Give the user some basic help.
#
printHelp() {
    echo "$basename: usage:"
    echo "    $basename -r <java options>"
    echo "    $basename [-q] [-n] -s | -f <JRE> | -c | -h"
    echo ""
    echo "The first usage option (\"-r\") will verify that the configured"
    echo "Java Runtime Environment (JRE) is appropriate for use with OpenNMS"
    echo "and will exec that JRE with <java options>."
    echo ""
    echo "The second usage option will attempt to find and configure a JRE"
    echo "for use with OpenNMS (\"-s\"), force the configuration of a specific"
    echo "JRE (\"-f <JRE>\"), verify that the configured JRE is appropriate"
    echo "for use with OpenNMS (\"-c\"), or print this help text (\"-h\")."
    echo ""
    echo "In the second usage option, you can pass \"-q\" to be quiet and"
    echo "only print errors.  Dry run mode can be enabled with \"-n\", which"
    echo "won't modify the stored java.conf file (good for testing)."
    echo ""
    echo "The \"-s\" option chooses a JRE based on these factors:"
    echo "    1) If the JAVA_HOME environment variable is set and points at"
    echo "       an appropriate JRE, it \$JAVA_HOME/bin/java will be used."
    echo "    2) If \"which java\" returns an appropriate JRE, it will be used."
    echo "    3) Lastly, a few directories are searched to find an"
    echo "       appropriate JRE: \"$searchdirs\"."
    echo ""
    echo "If none of the above options work or if they don't find the JRE"
    echo "you want OpenNMS to use, use \"-f <JRE>\" to specify the JRE you"
    echo "want OpenNMS to use."
}

#
# Function: javaCheck()
# Requires: varible $JP (java path)
# This function verifies the version of the java
# command found in the javaPath() and the
# javaFind() functions.
#
javaCheck() {
    ret="`$JP -version 2>&1 | grep '^java version' | sed 's/^java version \"//;s/\".*//'`"
    if echo "$ret" | egrep '^1\.4\.[2-9]' > /dev/null; then
	return 0
    else
	return 1
    fi
}

#
# Function: javaPaths()
# This function attempts to find a path
# to a java executable.  It searchs for
# files (hopefully directories) that match
# the regex "^j2*" or "^java$" and appends "/bin/java".
# It then tests to see if this there is an
# executable file by this name.  This is not
# foolproof but should get us close.
#
javaPaths() {
    for searchdir in $searchdirs; do
	# We search "j2*" for the Sun-supplied Java packages ("j2sdk"),
	# "java" for the Java installation shipped with SuSE, and "Home"
	# to catch /Library/Java/Home on Mac OS X.
	jdirs="`find \"$searchdir\" -name \"j2*\" -o -name \"java\" -o -name \"Home\" -maxdepth 2 -print`"
	for jdir in $jdirs; do
	    if [ -x $jdir/bin/java ]; then
		JP=$jdir/bin/java
		javaCheck && return 0
	    fi
	done
    done

    return 1
}

#
# Function: checkJavaHome()
# See if $JAVA_HOME/bin/java is a good JRE.
#
checkJavaHome() {
    tell "Checking for an appropriate JRE in JAVA_HOME..."
    if [ x"$JAVA_HOME" = x"" ]; then
	tell "skipping... JAVA_HOME not set"
	return 1
    fi

    if [ ! -d "$JAVA_HOME" ]; then
	tell "skipping... JAVA_HOME (\"$JAVA_HOME\") is not a directory"
	return 1
    fi
    
    if [ ! -x "$JAVA_HOME/bin/java" ]; then
	tell "skipping... \"$JAVA_HOME/bin/java\" does not exist or is not executable"
	return 1
    fi

    JP=$JAVA_HOME/bin/java
    if javaCheck; then
	tell "found: \"$JAVA_HOME/bin/java\" is an appropriate JRE"
	return 0
    else
	tell "\"$JAVA_HOME/bin/java\" is not an appropriate JRE"
	return 1
    fi
}

#
# Function: checkPath()
# Checks for a JRE in our path, using which(1).
#
checkPath() {
    JP="`which java`"
    if [ $? -eq 1 ]; then
	tell "did not find a JRE in user's path"
	return 1
    fi

    tell "Checking JRE in user's path: \"$JP\"..."
    if javaCheck; then
	tell "found an appropriate JRE in user's path: \"$JP\""
	return 0
    else
	tell "did not find an appropriate JRE in user's path: \"$JP\""
	return 1
    fi
}

#
# Function: findJava()
# A wrapper around javaPaths to give the user a clue about what is going on.
# 
findJava() {
    tell "searching for a good JRE..."
    if javaPaths; then
	tell "found a good JRE in \"$JP\""
	return 0
    else
	tell "did not find an appropriate JRE while searching for one"
	return 1
    fi
}


#
# Function: javaFind()
# This function first checks JAVA_HOME, then
# the current path for a java executable and then
# searches for one by calling javaPaths().
#
javaFind() {
    tell "Looking for an appropriate JRE..."

    checkJavaHome && return 0
    checkPath && return 0
    findJava && return 0

    warn "Could not find an appropriate JRE."
    warn "You can force a particular JRE by using"
    warn "\"$basename -f <JRE>\"."

    return 1
}

#
# Function: checkConfiguredJava()
# Verifies that the java configured in $java_conf looks good.
# Complains and returns 1 if it doesn't look good.
# Is quiet and returns 0 if things look good.
#
checkConfiguredJava() {
    mantra="run \"$opennms_home/bin/runjava -s\""

    if [ ! -f $java_conf ]; then
	warn "error: $java_conf file not found"
	warn "$mantra"

	return 1
    fi

    JP="`cat $java_conf`"

    if [ ! -x $JP ]; then
	warn "error: configured Java runtime environment not found"
	warn "\"$JP\" does not exist or is not executable"
	warn "$mantra"

	return 1
    fi

    javaCheck

    if [ $? -ne 0 ]; then
	warn "error: bad version for configured Java runtime environment"
	warn "\"$JP -version\" does not report that is version 1.4.2+"
	warn "$mantra"

	return 1
    fi

    return 0
}

#
# Function: runJava()
# Verifies that we have an appropriate JRE configured in $java_conf and
# execs it with the command-line arguments passed to us.
#
runJava() {
    checkConfiguredJava || return 1

    add_ld_path
    exec "$JP" "$@"
}

#
# Function: add_ld_path()
# Adds $opennms_home/lib to the linker path.
#
add_ld_path () {
    case "`uname`" in
	Darwin)
	    if echo "$DYLD_LIBRARY_PATH" | \
		grep -v "$opennms_home/lib" >/dev/null; then
		DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$opennms_home/lib"
		export DYLD_LIBRARY_PATH
	    fi
	    return
	    ;;

	*)
	    if echo "$LD_LIBRARY_PATH" | \
		grep -v "$opennms_home/lib" >/dev/null; then
		LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$opennms_home/lib"
		export LD_LIBRARY_PATH
	    fi
	    return
	    ;;
    esac
    
    return 1
}


#
# Function: setupJava()
# Calls javaFind and if successful, stores the location of the JRE in
# $java_conf.
#
setupJava() {
    if javaFind; then
	saveJava
	return $?
    else
	return 1
    fi
}

#
# Function: forceJava()
# Calls javaFind and if successful, stores the location of the JRE in
# $java_conf.
#
forceJava() {
    tell "checking forced JRE: \"$JP\"..."
    if [ ! -x "$JP" ]; then
	die "forced JRE \"$JP\" does not exist or is not executable"
    fi
    if javaCheck; then
	tell "forced JRE is good."
	saveJava
	return $?
    else
	die "forced JRE \"$JP\" is not an appropriate JRE"
    fi
}

saveJava() {
    if [ $dryrun -eq 0 ]; then
	echo "$JP" > $java_conf
	if [ $? -ne 0 ]; then
	    warn "error saving JRE to configuration file"
	    warn "configuration file: $java_conf"
	    die "exiting..."
	fi
	tell "value of \"$JP\" stored in configuration file"
    else
	tell "value of \"$JP\" would have been stored if not in dryrun mode"
    fi

    return 0
}

exclusive=0

check=0
force=""
dryrun=0
quiet=0
run=0
search=0

while getopts cf:hnqrs c
do
  case $c in
      c)
	  check=1
	  exclusive=`expr $exclusive + 1`
	  ;;

      f)
	  force="$OPTARG"
	  exclusive=`expr $exclusive + 1`
	  ;;

      h)
	  printHelp
	  exit 0
	  ;;

      n)
	  dryrun=1
	  ;;

      q)
	  quiet=1
	  ;;

      r)
	  run=1
	  exclusive=`expr $exclusive + 1`
	  ;;

      s)
	  search=1
	  exclusive=`expr $exclusive + 1`
	  ;;

      \?)
          die "Invalid option.  Use \"-h\" for help."
	  ;;
  esac
done
shift `expr $OPTIND - 1`

if [ $exclusive -eq 0 ]; then
    warn "You must choose one of the command-line options."
    die "Use \"-h\" for help."
fi

if [ $exclusive -gt 1 ]; then
    warn "You must choose only one of the command-line options."
    die "Use \"-h\" for help."
fi

if [ $quiet -gt 0 ]; then
    exec 3>/dev/null
else
    exec 3>&1
fi

if [ $check -gt 0 ]; then
    checkConfiguredJava
    exit $?
fi

if [ x"$force" != x"" ]; then
    JP="$force"
    forceJava
    exit $?
fi

if [ $run -gt 0 ]; then
    runJava "$@"
    exit $?
fi

if [ $search -gt 0 ]; then
    setupJava
    exit $?
fi

die "internal error... got to end of script and shouldn't have"
