#!/bin/sh

#
# Launch script for WebObjects applications.
#

#
# Reads a value from config.txt.
# Lines have the format: Key=Value
#
readConfigValue() {
    value="`sed -n \"s/^$2 *= *//p\" \"$3\"`"
    eval "$1=\${value}"
}

CURRDIR="`pwd`"
SCRIPT_NAME="`basename \"$0\" .sh`"

#
# Locate the .woa bundle root directory.
#
RELATIVE_WOADIR="`dirname \"$0\"`"
WOA_TOP_LEVEL="`cd \"${RELATIVE_WOADIR}\"; pwd | sed -e 's%\/Contents.*$%%'`"
CONTENTS_DIR="${WOA_TOP_LEVEL}/Contents"

#
# We need to be in the .woa when we invoke the JVM (so that the "user.dir"
# Java system property is equal to the path to the .woa).
#
cd "${WOA_TOP_LEVEL}"

CONFIG_FILE="${WOA_TOP_LEVEL}/config.txt"
CLASSPATH_FILE="${WOA_TOP_LEVEL}/classpath.txt"

#
# First pass: extract -launch.key=value arguments.
# These override config.txt values and are stripped from the arguments
# passed to the application.
#
LAUNCH_PRINCIPAL_CLASS=
LAUNCH_JVM=
LAUNCH_JVM_OPTIONS=
REMAINING_ARGS=

for arg in "$@"
do
    case ${arg} in
        -launch.principalClass=*)
                  LAUNCH_PRINCIPAL_CLASS="${arg#-launch.principalClass=}"
                  ;;
        -launch.jvm=*)
                  LAUNCH_JVM="${arg#-launch.jvm=}"
                  ;;
        -launch.jvmOptions=*)
                  LAUNCH_JVM_OPTIONS="${arg#-launch.jvmOptions=}"
                  ;;
        *)        REMAINING_ARGS="${REMAINING_ARGS:+${REMAINING_ARGS} }${arg}"
                  ;;
    esac
done

# Replace $@ with the remaining arguments (launch args stripped out)
set -- ${REMAINING_ARGS}

#
# Read the configuration file.
#
if [ ! -f "${CONFIG_FILE}" -o ! -r "${CONFIG_FILE}" ]
then
    echo ${SCRIPT_NAME}: Unable to read \"${CONFIG_FILE}\"!  Terminating.
    exit 1
fi

readConfigValue APPLICATION_CLASS principalClass "${CONFIG_FILE}"
readConfigValue JVM_EXECUTABLE    jvm            "${CONFIG_FILE}"
readConfigValue JVM_OPTIONS       jvmOptions     "${CONFIG_FILE}"

# Apply -launch.* overrides
if [ -n "${LAUNCH_PRINCIPAL_CLASS}" ]; then APPLICATION_CLASS="${LAUNCH_PRINCIPAL_CLASS}"; fi
if [ -n "${LAUNCH_JVM}" ];             then JVM_EXECUTABLE="${LAUNCH_JVM}"; fi
if [ -n "${LAUNCH_JVM_OPTIONS}" ];     then JVM_OPTIONS="${LAUNCH_JVM_OPTIONS}"; fi

if [ "${APPLICATION_CLASS}" = "" ]
then
    echo ${SCRIPT_NAME}: WARNING -- principalClass missing from config.txt, using default.
    APPLICATION_CLASS=Application
fi
if [ "${JVM_EXECUTABLE}" = "" ]
then
    JVM_EXECUTABLE=java
fi

#
# Read the classpath file: each non-empty line is a classpath entry.
# Replace the APPROOT token with the actual Contents directory path.
#
if [ ! -f "${CLASSPATH_FILE}" -o ! -r "${CLASSPATH_FILE}" ]
then
    echo ${SCRIPT_NAME}: Unable to read \"${CLASSPATH_FILE}\"!  Terminating.
    exit 1
fi

SCRIPT_CLASSPATH="`awk 'NF{CLSPTH=CLSPTH\":\"$0} END{print CLSPTH}' \"${CLASSPATH_FILE}\" | sed -e 's%^:%%' -e \"s%APPROOT%${CONTENTS_DIR}%g\"`"

#
# Append any pre-existing CLASSPATH from the environment.
#
if [ -n "${CLASSPATH}" ]
then
    SCRIPT_CLASSPATH="${SCRIPT_CLASSPATH}:${CLASSPATH}"
fi

#
# Default JVM arguments.
#
JVM_ARGS="-DWOUserDirectory=\"${CURRDIR}\""

#
# Append JVMOptions from config.txt.
#
if [ -n "${JVM_OPTIONS}" ]
then
    JVM_ARGS="${JVM_ARGS} ${JVM_OPTIONS}"
fi

JAVA_EXECUTABLE=${JVM_EXECUTABLE}

#
# Process command line arguments:
# - -D and -X flags are added to JVM_ARGS (before the application class)
# - -D flags are also passed as application arguments (to avoid possible errors)
# - -X flags are only passed to the JVM
# - All other arguments are passed to the application
#
COMMAND_LINE_ARGS=

for arg in "$@"
do
    case ${arg} in
        [\"]-D*=*[\"] | [\']-D*=*[\'] | -D*=[\"]*[\"] | -D*=[\']*[\'])
                  # These args are already quoted.
                  JVM_ARGS="${JVM_ARGS} ${arg}"
                  COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }${arg}"
                  ;;
        -D*=*\ * | -D*=*[\(]*)
                  # These args need to be quoted properly.
                  if echo ${arg} | grep -e '"' >/dev/null
                  then
                      JVM_ARGS="${JVM_ARGS} "`echo "${arg}" | sed -e "s/=\(.*\)$/=\'\1\'/"`
                      COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }"`echo "${arg}" | sed -e "s/=\(.*\)$/=\'\1\'/"`
                  else
                      JVM_ARGS="${JVM_ARGS} "`echo "${arg}" | sed -e "s/=\(.*\)$/=\"\1\"/"`
                      COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }"`echo "${arg}" | sed -e "s/=\(.*\)$/=\"\1\"/"`
                  fi
                  ;;
        -D*=*)    # These args have no spaces and don't need quotes.
                  JVM_ARGS="${JVM_ARGS} ${arg}"
                  COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }${arg}"
                  ;;
        -XX:*PrintVMOptions)
                  # Always give this argument precedence.
                  JVM_ARGS="${arg} ${JVM_ARGS}"
                  ;;
        [\"]-X*[\"] | [\']-X*[\'])
                  # These args are already quoted, add to the JVM arg list.
                  JVM_ARGS="${JVM_ARGS} ${arg}"
                  ;;
        -X*\ *)   # This only belongs in the JVM arg list, needs quotes.
                  if echo ${arg} | grep -e '"' >/dev/null
                  then
                      JVM_ARGS="${JVM_ARGS} "`echo "${arg}" | sed -e "s/^\(.*\)$/\'\1\'/"`
                  else
                      JVM_ARGS="${JVM_ARGS} "`echo "${arg}" | sed -e "s/^\(.*\)$/\"\1\"/"`
                  fi
                  ;;
        -X*)      # This only belongs in the JVM arg list, doesn't need quotes.
                  JVM_ARGS="${JVM_ARGS} ${arg}"
                  ;;
        [\"]*[\"] | [\']*[\'])
                  # These args are already quoted.
                  COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }${arg}"
                  ;;
        *\ * | *[\(]*)
                  # These args need to be quoted properly.
                  if echo ${arg} | grep -e '"' >/dev/null
                  then
                      COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }"`echo "${arg}" | sed -e "s/^\(.*\)$/\'\1\'/"`
                  else
                      COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }"`echo "${arg}" | sed -e "s/^\(.*\)$/\"\1\"/"`
                  fi
                  ;;
        *)        COMMAND_LINE_ARGS="${COMMAND_LINE_ARGS:+$COMMAND_LINE_ARGS }${arg}"
                  ;;
    esac
done

#
# Launch the application.
#
echo Launching ${SCRIPT_NAME}.woa ...

echo ${JAVA_EXECUTABLE} ${JVM_ARGS} -classpath \"${SCRIPT_CLASSPATH}\" ${APPLICATION_CLASS} ${COMMAND_LINE_ARGS}
eval exec ${JAVA_EXECUTABLE} ${JVM_ARGS} -classpath "${SCRIPT_CLASSPATH}" ${APPLICATION_CLASS} ${COMMAND_LINE_ARGS}
