#! /bin/sh

#
# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
# ident "$Revision: 1.70 $  SMI"
#

OS=`uname -s`
if [ -z "${OS}" ]; then
   # No I18N at this point
   echo "Unable to determine operating system."
   exit 1
fi
if [ "${OS}" = "SunOS" ]; then
   CACAO_ROOT=/opt/SUNWcacao
   LIB_DIR=${CACAO_ROOT}/lib
elif [ "${OS}" = "AIX" ]; then
   CACAO_ROOT=/opt/SUNWcacao
   LIB_DIR=${CACAO_ROOT}/lib
elif [ "${OS}" = "Linux" ]; then
   CACAO_ROOT=/opt/sun/cacao
   LIB_DIR=${CACAO_ROOT}/private/lib
else
   # No I18N at this point
   echo "Not supported on detected OS \"${OS}\"."
   exit 1
fi

. ${LIB_DIR}/tools/helpers

# Key cacao properties
JAVA_FLAGS_KEY="java.flags"
JMXMP_PORT_KEY="com.sun.cacao.jmxmp.connector.port"
SNMP_ADAPTOR_PORT_KEY="com.sun.cacao.snmp.adaptor.port"
SNMP_ADAPTOR_TRAP_PORT_KEY="com.sun.cacao.snmp.adaptor.trap.port"
COMMAND_STREAM_ADAPTOR_PORT_KEY="com.sun.cacao.commandstream.adaptor.port"
RETRIES_KEY="cacao.retries"
PROCESS_USERNAME_KEY="process.username"
ENABLE_KEY="start.at.boot.enabled"
JAVA_HOME_KEY="java.home"
JDMK_HOME_KEY="jdmk.home"
NSS_LIB_HOME_KEY="nss.lib.home"
NSS_TOOLS_HOME_KEY="nss.tools.home"
DEPENDENCIES_OK_KEY="dependencies.ok"

# Param name
JAVA_FLAGS="java-flags"
JAVA_DEBUG_FLAGS="java.debug.flags"
JMXMP_PORT="jmxmp-connector-port"
SNMP_ADAPTOR_PORT="snmp-adaptor-port"
SNMP_ADAPTOR_PORT_ALTERNATIVE="snmp-adapter-port"
SNMP_ADAPTOR_TRAP_PORT="snmp-adaptor-trap-port"
SNMP_ADAPTOR_TRAP_PORT_ALTERNATIVE="snmp-adapter-trap-port"
COMMAND_STREAM_ADAPTOR_PORT="commandstream-adaptor-port"
COMMAND_STREAM_ADAPTOR_PORT_ALTERNATIVE="commandstream-adapter-port"
RETRIES="retries"
ENABLE="start.at.boot.enabled"

PMFADM=/usr/cluster/bin/pmfadm
PMF_LOCK="/var/cluster/run/pmfd.lock"
PMF_TIMEOUT=10

DEFAULT_PROCESS_USERNAME=noaccess

DAEMON_NAME=cacao

PID_FILE=${PID_DIR}/${DAEMON_NAME}.pid
RETRIES_FILE=${PID_DIR}/retries
CACAO_LOCK_FILE=${PID_DIR}/lock

# Flag set to 1 if PMF available
PMF=0
# Cacao's pid
PID=0

# Displays command line
displayHelp() {
    printMessage "${CACAOADM_USG10}"
    printMessage "${CACAOADM_USG11}"
    printMessage "${CACAOADM_USG20}"
    printMessage "${CACAOADM_USG30}"
    printMessage "${CACAOADM_USG31}"
    printMessage "${CACAOADM_USG40}"
    printMessage "${CACAOADM_USG41}"
    printMessage "${CACAOADM_USG42}"  
    printMessage "${CACAOADM_USG43}"
    printMessage "${CACAOADM_USG44}"
    printMessage "${CACAOADM_USG45}"
    printMessage "${CACAOADM_USG46}"
    printMessage "${CACAOADM_USG47}"
    printMessage "${CACAOADM_USG48}"
    printMessage "${CACAOADM_USG49}"
    printMessage "${CACAOADM_USG491}"
    printMessage "${CACAOADM_USG50}"
    printMessage "${CACAOADM_USG51}"
    printMessage "${CACAOADM_USG52}"
    printMessage "${CACAOADM_USG53}"
    printMessage "${CACAOADM_USG54}"
    printMessage "${CACAOADM_USG55}"
    printMessage "${CACAOADM_USG60}"
    printMessage "${CACAOADM_USG61}"
    printMessage "${CACAOADM_USG62}"
    printMessage "${CACAOADM_USG70}"
    printMessage "${CACAOADM_USG71}"
    printMessage "${CACAOADM_USG73}"
    printMessage "${CACAOADM_USG74}"
    printMessage "${CACAOADM_USG75}"
    printMessage "${CACAOADM_USG80}"
    printMessage "${CACAOADM_USG90}"
}

#
# Generate keys
#
#
generateKeys() {

    ${CHOWN} root ${SECURITY_DIR}
    ${CHMOD} go-w ${SECURITY_DIR}

    isCacaoRunning
    if [ $? -ne 0 ]; then
        printErrorMessage "${CANNOT_WHEN_RUNNING}"
        exit 1
    fi

    if [ ! -z "${CACAO_PROTO}" ]; then
	printErrorMessage "${MISSING_KEYS}"
	exit 1
    fi
    
    (export CACAO_JAVA_HOME JAVA NSS_LIB_HOME NSS_TOOLS_HOME ;\
     ${PRIVATE_BIN_DIR}/keygen ${SECURITY_DIR})
    
    return $?
}

################################################################################
#
# updateProperty
# Updates a property value
# $1 property name
# $2 new property value
#
################################################################################
updateProperty() {
    trap "${RM} -fr ${TMPFILE}; exit" 0 1 2 3 15 >/dev/null 2>&1

    if [ ! -z "${CACAO_PROTO}" ] ; then
	echo "updateProperty ignored - running in proto environment"
	return 0
    fi

    FILE=${PROPERTY_FILE}
    TMPFILE=${FILE}.$$
    perms=644
    ${RM} -f $TMPFILE >/dev/null 2>&1
    name=$1
    value=$2

    # escape slashes
    value=`${ECHO} ${value} | ${SED} -e 's?\/?\\\/?g'`
	
    # If the property exists, delete it.
    touch ${TMPFILE}
    ${SED} -e "s/^${name}=.*/${name}=${value}/g" ${FILE} >> $TMPFILE       
    # Insert property to file
    ${MV} $TMPFILE $FILE
    ${CHMOD} $perms $FILE
    ${RM} -f $TMPFILE >/dev/null 2>&1
}

################################################################################
#
# isRoot
#
# Check the user ID to see if it matches root's (0).
# Return 0 if the user is root. Exit with status 1 otherwise.
#
################################################################################

isRoot() {

    USERID=`${ID} -u`

    if [ $USERID -ne 0 ]; then
        printErrorMessage  "${NO_ROOT}"
        exit 1
    fi
    return 0

} ## end isRoot

################################################################################
#
# List all the child from a process from the father to the childs
#
###############################################################################
my_ptree () {
_PID=$1

${PS} -e -f | ${AWK} -v master_pid=$_PID 'BEGIN {print master_pid}     \
                    {procs[$2] = $3;max_idx=0}                                                                    \
		    END {                                                                               \
                      do {                                                              \
                       found = 0;                                                                        \
                       for (pid in procs) {                                                             \
                         if ((procs[pid] == master_pid) || (procs[pid] in pid_to_kill)) {               \
                           pid_to_kill[pid] = max_idx; max_idx++;                                                        \
                           found=1;                                                                     \
                            procs[pid] = 0;                                                             \
                         }                                                                              \
                       }                                                                                \
                      }  while (found == 1);                                                            \
		      idx=0;\
		      # Must kill processes from father to child
		      # Make sure we dump from the first entry to the last one
		      while (idx < max_idx) {\
			for (v in pid_to_kill)  {                                                          \
                             if (pid_to_kill[v] == idx) print v          \
			};\
			idx++;
	               
		      }\
                     }'
}

################################################################################
#
# Kill a process and its subprocesses
#
################################################################################
killProcesses() {
    _pid=$1
    child_pid_list=`my_ptree ${_pid}`
    ${PS} -p ${_pid} >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
	kill -USR2 ${_pid} >/dev/null 2>&1
    fi
    for p in ${child_pid_list}
    do
      ${PS} -p ${p} >/dev/null 2>&1
      if [ $? -eq 0 ]
      then
       kill -9 ${p} >/dev/null 2>&1
      fi 
    done 
}

###############################################################################
#
# Get a property value
# $1 property name
# $2 property file
# return the property value
#
###############################################################################
getProperty() {
    property_name=$1
    line=`${GREP} "^${property_name}=" ${PROPERTY_FILE}` 
    value=`${ECHO} ${line} | ${SED} "s/^${property_name}=//g"`
    ${ECHO} $value
}

###############################################################################
#
# Get param name for cacao.properties
# $1 param name in cacaoadm
# return the property name in cacao.properties
#
###############################################################################
getCacaoPropertiesParamName() {
    case $1 in
    "${JMXMP_PORT}")
	${ECHO} "${JMXMP_PORT_KEY}"
    ;;
    "${SNMP_ADAPTOR_PORT}" | "${SNMP_ADAPTOR_PORT_ALTERNATIVE}")
	${ECHO} "${SNMP_ADAPTOR_PORT_KEY}"
    ;;
    "${SNMP_ADAPTOR_TRAP_PORT}" | "${SNMP_ADAPTOR_TRAP_PORT_ALTERNATIVE}")
	${ECHO} "${SNMP_ADAPTOR_TRAP_PORT_KEY}"
    ;;
    "${COMMAND_STREAM_ADAPTOR_PORT}" | "${COMMAND_STREAM_ADAPTOR_ALTERNATIVE}")
	${ECHO} "${COMMAND_STREAM_ADAPTOR_PORT_KEY}"
    ;;
    "${RETRIES}")
	${ECHO} "${RETRIES_KEY}"
    ;;
    "${JAVA_FLAGS}")
	${ECHO} "${JAVA_FLAGS_KEY}"
    ;;
    *)
    	${ECHO} $1
    ;;
    esac
}

###############################################################################
#
# Get param list
# return all the parameter name
###############################################################################
getParamList() {
    ${ECHO} "${JAVA_FLAGS} ${JMXMP_PORT} ${SNMP_ADAPTOR_PORT} \
    ${SNMP_ADAPTOR_TRAP_PORT} ${COMMAND_STREAM_ADAPTOR_PORT} ${RETRIES}"
}

###############################################################################
#
# Check a property value for set/get operation
# $1 property name
# return 0 if ok otherwise 1
###############################################################################
checkParameter() {
    property_name=$1
    case "$1" in \
    "${JMXMP_PORT}" | \
    "${SNMP_ADAPTOR_PORT}" | \
    "${SNMP_ADAPTOR_PORT_ALTERNATIVE}" | \
    "${SNMP_ADAPTOR_TRAP_PORT}" | \
    "${SNMP_ADAPTOR_TRAP_PORT_ALTERNATIVE}" | \
    "${COMMAND_STREAM_ADAPTOR_PORT}" | \
    "${COMMAND_STREAM_ADAPTOR_ALTERNATIVE}" | \
    "${RETRIES}" | \
    "${JAVA_FLAGS}" | \
    "${ENABLE}" | \
    "${JAVA_DEBUG_FLAGS}")
	return 0
	;;
    *)
	return 1
	;;
    esac
}

###############################################################################
#
# Get param
# $1 is a param=value string
# return the param
###############################################################################
getParameter() {
    echo $1 | ${SED} 's/=.*//'
}

###############################################################################
#
# Get value
# $1 is a param=value string
# return the value
###############################################################################
getValue() {
    # Because option could contain =, we call getParameter
    param=`getParameter $1`
    echo $1 | ${SED} "s/${param}=//"
}

###############################################################################
#
# Display version tool
# $1 property name
#
###############################################################################
displayVersion() {
    getProperty cacao.version;
}

###############################################################################
#
# Utility to know if cacao is running
#
# Return code:
#   0 if cacao is NOT running
#   1 if cacao is running under default mechanism
#   2 if cacao is running under PMF
#
# Exit code:
#   1 if non recoverable error
#
###############################################################################
isCacaoRunning() {

    # If Cacao is running under default mechanism, its pid is stored in a file
    if [ -f "${PID_FILE}" ]; then
        # Check that pid file is valid
        PID=`${CAT} ${PID_FILE} 2>/dev/null`
        ${PS} -p ${PID} >/dev/null 2>&1
        if [ $? -eq 0 ]; then
           # Cacao is running under default mechanism
           return 1
        else
            # Remove non valid file
            ${RM} -f ${PID_FILE} 2>/dev/null
            if [ $? -ne 0 ]; then
                printErrorMessage ${FAIL_RM} ${PID_FILE}
                exit 1
            fi
        fi
    fi

    # Check for alternate mechanism: PMF
    PMFD_PID=`${PS} -ef | ${GREP} pmf | ${GREP} -v grep | ${AWK} '{print $2}'`
    if [ "x${PMFD_PID}" != "x" ]; then
        # PMF Deamon is running
        if [ -f ${PMF_LOCK} ]; then
            # RPC created a lock for PMF daemon
            HOST=`uname -n`
            RPCI=`${RPCINFO} -t ${HOST} 100248 2 >/dev/null 2>&1`
            if [ $? -eq 0 ]; then
                # Flag to indicate that PMF is available
                PMF=1
                # If Cacao is running, it is monitored by PMF
                ${PMFADM} -q ${DAEMON_NAME}
                if [ $? -eq 0 ]; then
                    return 2
                fi
            fi
        fi
    fi

    # Cacao is not running
    return 0
}

###############################################################################
#
# Check if a parameter must have as value an integer.
#
# $1 a parameter name
#
# Return code:
#   0 if it must has an integer
#   1 if it does not require an integer
###############################################################################
isIntegerRequired() {
 case "$1" in \
    "${JMXMP_PORT}" | \
    "${SNMP_ADAPTOR_PORT}" | \
    "${SNMP_ADAPTOR_TRAP_PORT}" | \
    "${COMMAND_STREAM_ADAPTOR_PORT}" | \
    "${RETRIES}")
	return 0
	;;
    *)
	return 1
	;;
    esac
}

###############################################################################
#
# Check if the value is an integer.
#
# $1 a value to check
# Return code:
#   0 if it is a valid integer
#   1 if it is not a valid integer
###############################################################################
isValidInteger() {
    value=$1
    if [ -z "$value" ]; then
	return 1
    fi

    result=`${ECHO} ${value} | ${SED} 's/[0-9][0-9]*//g'`
    if [ -z "${result}" ]; then
	return 0
    else
	return 1
    fi
}

###############################################################################
#
# Check if it is a valid input for set operation
#
# $1 input for set operation
# Return code:
#
#   0 if it is a valid input
#   1 if it is not a valid input
###############################################################################
isValidSetInput() {
    ${ECHO} $1 | ${GREP} "=" 2>&1 > /dev/null
    if [ $? -ne 0 ]; then
	return 1
    fi

    param=`getParameter $1`
    if [ -z "$param" ]; then
	return 1
    fi

    isIntegerRequired "${param}"
    if [ $? -ne 0 ]; then
	return 0
    fi

    value=`getValue $1`
    if [ -z "$value" ]; then
	return 1
    fi

    return 0
}

###############################################################################
#
# Print level description for logger
#
###############################################################################
printLevelDescription() {
    printMessage "${LOGGER_LEVEL1}" "ALL"
    printMessage "${LOGGER_LEVEL2}" "CONFIG"
    printMessage "${LOGGER_LEVEL3}" "FINE"
    printMessage "${LOGGER_LEVEL4}" "FINER"
    printMessage "${LOGGER_LEVEL5}" "FINEST"
    printMessage "${LOGGER_LEVEL6}" "INFO"
    printMessage "${LOGGER_LEVEL7}" "OFF"
    printMessage "${LOGGER_LEVEL8}" "SEVERE"
    printMessage "${LOGGER_LEVEL9}" "WARNING"
}

###############################################################################
#
# Print level description for logger
#
###############################################################################
printParamDescription() {
    printMessage "${PARAM_MSG1}" ${JMXMP_PORT}
    printMessage "${PARAM_MSG2}" ${SNMP_ADAPTOR_PORT}
    printMessage "${PARAM_MSG3}" ${SNMP_ADAPTOR_TRAP_PORT}
    printMessage "${PARAM_MSG4}" ${COMMAND_STREAM_ADAPTOR_PORT}
    printMessage "${PARAM_MSG5}" ${RETRIES}
    printMessage "${PARAM_MSG6}" ${JAVA_FLAGS}
}

###############################################################################
#
# Locate dependencies. Look into cacao.properties for already found 
# dependencies. Otherwise, find the with helper functions and update
# cacao.properties if ok.
#
###############################################################################
locateDependencies() {

    # dependencies already found ?
    DEPENDENCIES_OK=`getProperty ${DEPENDENCIES_OK_KEY}`
    
    if [ "${DEPENDENCIES_OK}" = "true" ]; then
        # load dependencies
	CACAO_JAVA_HOME=`getProperty ${JAVA_HOME_KEY}`
        # test validity of Java binary
        if [ ! -x "${CACAO_JAVA_HOME}/bin/java" ]; then
            findJava
            updateProperty "${JAVA_HOME_KEY}" "${CACAO_JAVA_HOME}"
        fi
        JDMK_HOME=`getProperty ${JDMK_HOME_KEY}`
        NSS_LIB_HOME=`getProperty ${NSS_LIB_HOME_KEY}`
        NSS_TOOLS_HOME=`getProperty ${NSS_TOOLS_HOME_KEY}`

    else
        # find dependencies
        findJava
        findJDMK
        findNSS
        
        # update cacao.properties
        updateProperty "${JAVA_HOME_KEY}" "${CACAO_JAVA_HOME}"
        updateProperty "${JDMK_HOME_KEY}" "${JDMK_HOME}"
        updateProperty "${NSS_LIB_HOME_KEY}" "${NSS_LIB_HOME}"
        updateProperty "${NSS_TOOLS_HOME_KEY}" "${NSS_TOOLS_HOME}"
        updateProperty "${DEPENDENCIES_OK_KEY}" "true"
    fi

    # set JAVA
    JAVA=${CACAO_JAVA_HOME}/bin/java

}

###############################################################################
#
# Get a lock
#
# Return:
#        0 if we get the lock.
#        1 if we cannot get the lock.
#
###############################################################################
lock() {
    # Create directory for lock
    umask 022
    ${MKDIR} -p ${PID_DIR}
    # Get lock (do not use PMF)
    if [ -f "${CACAO_LOCK_FILE}" ];
    then
	return 1
    fi

    ${ECHO} $$ >> "${CACAO_LOCK_FILE}"

    _pid=`${HEAD} -1 "${CACAO_LOCK_FILE}"`
    if [ $$ -ne "${_pid}" ]; then
	return 1
    fi
    trap "${RM} -fr "${CACAO_LOCK_FILE}"; exit 1" 3 1 2  15 >/dev/null 2>&1
    return 0
}

###############################################################################
#
# Main
#
# Script's entry point
#
###############################################################################


# set classpath
unset CLASSPATH

case "$1" in

    "--help" | "-?")

        displayHelp
	exit 0
        ;;


    "--version" | "-V")

        displayVersion
	exit 0
        ;;


    "enable")

	isRoot

	# We do not need dependency for this operation
	# but we do not want to allow this operation if
	# dependencies are wrong. It prevents failure 
	# at system boot
	locateDependencies

        updateProperty "${ENABLE_KEY}" true
	exit 0
	;;


    "disable")

	isRoot

	# We do not need dependency for this operation
	# but we do not want to allow this operation if
	# dependencies are wrong. We are symetric with enable
	locateDependencies
        updateProperty "${ENABLE_KEY}" false
	exit 0
	;;


    "get-param" | "set-param")

	if [ $# -gt 3 ]; then
	    printErrorMessage "${INVALID_COMMAND}"
	    displayHelp
	    exit 2   
	fi

	if [ "$1" = "get-param" ]; then
	    if [ $# -eq 2 ]; then
		checkParameter $2
		if [ $? -ne 0 ]; then
		    printErrorMessage "${INVALID_PARAMETER}"
		    exit 1
		fi
		
		_param=`getCacaoPropertiesParamName $2`
		PARAM_VALUE=`getProperty ${_param}`
		${ECHO} "$2=${PARAM_VALUE}"
	    else
		if [ "$2" = "-v" -o "$2" = "--value" ]; then
		    _param=`getCacaoPropertiesParamName $3`
		    getProperty ${_param}
		else
		    printErrorMessage "${INVALID_COMMAND}"
		    displayHelp
		    exit 2
		fi
	    fi	   
	else
	    isRoot
            isCacaoRunning
            if [ $? -ne 0 ]; then
                printErrorMessage "${CANNOT_WHEN_RUNNING}"
                exit 1
	    fi

	    isValidSetInput "$2"
	    if [ $? -ne 0 ]; then
		printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2   
	    fi

	    PARAMETER=`getParameter "$2"`
	    checkParameter "${PARAMETER}"
	    if [ $? -ne 0 ]; then
		printErrorMessage "${INVALID_PARAMETER}"
		exit 1
	    fi

	    PARAM_VALUE=`getValue "$2"`
	    isIntegerRequired "${PARAMETER}"
	    if [ $? -eq 0 ]; then
		isValidInteger "${PARAM_VALUE}"
		if [ $? -ne 0 ]; then
		    printErrorMessage "${INVALID_VALUE}" "${PARAM_VALUE}"
		    exit 1
		fi
	    fi

	    # Get real name for cacao.properties
	    PARAMETER=`getCacaoPropertiesParamName ${PARAMETER}`
	    updateProperty "${PARAMETER}" "${PARAM_VALUE}"
	fi
	exit 0
    ;;

    "list-params")
	if [ $# -gt 2 ];then
	    printErrorMessage "${INVALID_COMMAND}"
	    displayHelp
	    exit 2
	fi

	if [ $# -eq 2 ]; then
	    if [ $2 != "--description"  -a $2 != "-d" ]; then
		printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
	    fi
	    printParamDescription
	else

	    for p in `getParamList`
	    do
		_property=`getCacaoPropertiesParamName "$p"`
		_propertyVal=`getProperty "${_property}"`
		${ECHO} "$p=${_propertyVal}"
	    done
	fi
	exit 0
    ;;

    "status")
	isRoot
	MODULE_INFO=NO
	# check syntax
	case $# in
	    1)
		# We display all the info
	    ;;
	    2)
		MODULE_INFO=YES
	    ;;
	    *)
		printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
	    ;;
 	esac
	
	
	if [ "${MODULE_INFO}" != "YES" ]; then
	    value=`getProperty ${ENABLE_KEY}`
	    if [ "${value}" != "true" ]; then
		printMessage "${CACAO_DISABLE}"
	    else
		printMessage "${CACAO_ENABLE}"
	    fi

	    # Display the list of Cacao processes
	    isCacaoRunning
	    case $? in
		0)
		    # Cacao is not running
		    printMessage "${CACAOADM_NOT_RUNNING}"
		    exit 0
		    ;;
		1)
		    # Cacao is running under default mechanism, display pids
		    printMessage "${CACAO_PROCESSES}"
		    my_ptree ${PID}
		    ;;
		2)
		    # Cacao is running under PMF, display pids
		    set -- `${PMFADM} -l ${DAEMON_NAME} | ${GREP} pids`
		    shift
		    printMessage "${CACAO_PROCESSES}"
		    for i in ${*}; do
			    echo ${i}
		    done
		    ;;
	    esac

	   
	    # find dependencies
	    locateDependencies
	    CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	    CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}
	    CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}

	    # Get uptime
	    PARAMETERS="`${HOSTNAME}` uptime"
	    LAUNCH="${JAVA} \
			-classpath ${CLASSPATH} \
			-Dcacao.properties=${PROPERTY_FILE} \
			com.sun.cacao.admin.Administration ${PARAMETERS}"
	    MSG=`${LAUNCH} 2>&1`
	    case $? in
		0)
		    # Display uptime
		    echo "${MSG}"
		    exit 0
		    ;;
		3)
		    # Connection problem, cacao might be starting
		    printErrorMessage "${CACAOADM_NOT_CONNECT}"
		    exit 1
		    ;;
		*)
		    # Unexpected problem
		    printErrorMessage "${CACAOADM_UPTIME_FAIL}"
		    exit 1
		    ;;
	    esac
	fi

	isCacaoRunning
	if [ $? -eq 0 ]; then
	    # Cacao is not running
	    printErrorMessage "${CACAOADM_MUST_RUN}"
	    exit 1
	fi

	if [ "${MODULE_INFO}" = "YES" ]; then
	     # Get module list

	    # find dependencies
	    locateDependencies
	    CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	    CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}
	    CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}

	    PARAMETERS="`${HOSTNAME}` status $2"
	    LAUNCH="${JAVA} \
			-classpath ${CLASSPATH} \
			-Dcacao.properties=${PROPERTY_FILE} \
			com.sun.cacao.admin.Administration ${PARAMETERS}"
	    MSG=`${LAUNCH} 2>&1`
	    case $? in
		0)
		    # Display module list
		    echo "${MSG}"
		    exit 0
		    ;;
		3)
		    # Connection problem, cacao might be starting
		    printErrorMessage "${CACAOADM_NOT_CONNECT}"
		    exit 1
		    ;;
		*)
		    # Unexpected problem
		    printErrorMessage "${MSG}"
		    exit 1
		    ;;
	    esac
	fi
	;;

    "list-modules")
	   isRoot

	   isCacaoRunning
	   if [ $? -eq 0 ]; then
		# Cacao is not running
		printErrorMessage "${CACAOADM_MUST_RUN}"
		exit 1
	   fi

	   if [ $# != 1 ]; then
		printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
	   fi

	   # find dependencies
	   locateDependencies
	   CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	   CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	   # Get module list
	   CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}
	   PARAMETERS="`${HOSTNAME}` list"
	   LAUNCH="${JAVA} \
		-classpath ${CLASSPATH} \
		-Dcacao.properties=${PROPERTY_FILE} \
		com.sun.cacao.admin.Administration ${PARAMETERS}"
	   MSG=`${LAUNCH} 2>&1`
	   case $? in
	    0)
		# Display module list
		echo "${MSG}"
		exit 0
		;;
	    3)
		# Connection problem, cacao might be starting
		printErrorMessage "${CACAOADM_NOT_CONNECT}"
		exit 1
		;;
	    *)
		# Unexpected problem
		printErrorMessage "${MSG}"
		exit 1
		;;
	    esac
    ;;

    "list-filters")

	isRoot
        isCacaoRunning
        if [ $? -eq 0 ]; then
            # Cacao must be running
	    printErrorMessage "${CACAOADM_MUST_RUN}"
	    exit 1
	fi

	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}
	PARAMETERS="`${HOSTNAME}` logging"
	LAUNCH="${JAVA} \
		-classpath ${CLASSPATH} \
		-Dcacao.properties=${PROPERTY_FILE} \
		com.sun.cacao.admin.Administration ${PARAMETERS}"

	case $# in
            1)
                # Command line is: cacaoadm list-filters
                MSG=`${LAUNCH} 2>&1`
		case $? in
		    0)
			# Display result
			if [ -n "${MSG}" ]; then
			    echo "${MSG}"
			fi
			exit 0
		    ;;
		    3)
			# Connection problem, cacao might be starting
			printErrorMessage "${CACAOADM_NOT_CONNECT}"
			exit 1
		    ;;
		    *)
			# Unexpected problem
			printErrorMessage "${MISSING_LOGGER}"
			exit 1
		    ;;
		esac
		;;
            2)
                # Command line is: cacao list-filters --level
		if [ $2 != "--levels" -a $2 != "-l" ]; then
		    printErrorMessage "${INVALID_COMMAND}"
		    displayHelp
		    exit 2   
		fi
		printLevelDescription
		
                ;;
            *)
                # Invalid command line
                printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
                ;;
        esac
    ;;

    "get-filter")
	if [ $# -gt 3 ]; then
	    printErrorMessage "${INVALID_COMMAND}"
	    displayHelp
	    exit 2
	fi

	if [ $# -eq 3 ];then
	    if [ $2 != "--value" -a $2 != "-v" ]; then
		 printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2   
	    else
		_value="yes"
		_param=$3
	    fi
	else
	    _param=$2
	    _value="no"
	fi
    
	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}
	PARAMETERS="`${HOSTNAME}` logging ${_param}"
	LAUNCH="${JAVA} \
		-classpath ${CLASSPATH} \
		-Dcacao.properties=${PROPERTY_FILE} \
		com.sun.cacao.admin.Administration ${PARAMETERS}"
	_msg=`$LAUNCH`
	case $? in
	    0)
		if [ ${_value} = "yes" ]; then
		    ${ECHO} "${_msg}"
		else
		    ${ECHO} "${_param}=${_msg}"
		fi
		exit 0
		;;
	    3)
		# Connection problem, cacao might be starting
		printErrorMessage "${CACAOADM_NOT_CONNECT}"
		exit 1
		;;
	    *)
		# Unexpected problem
		printErrorMessage "${_msg}"
		exit 1
		;;
	 esac
    ;;

    "set-filter")
	isRoot
        isCacaoRunning
        if [ $? -eq 0 ]; then
            # Cacao must be running
	    printErrorMessage "${CACAOADM_MUST_RUN}"
	    exit 1
	fi

	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}
	PARAMETERS="`${HOSTNAME}` logging"
	LAUNCH="${JAVA} \
		-classpath ${CLASSPATH} \
		-Dcacao.properties=${PROPERTY_FILE} \
		com.sun.cacao.admin.Administration ${PARAMETERS}"

	case $# in
            2)
                # Command line is: cacaoadm set-filter param=value
		isValidSetInput $2
		if [ $? -ne 0 ]; then
		    printErrorMessage "${INVALID_COMMAND}"
		    displayHelp
		    exit 2   
		fi
		_param=`getParameter $2`
		_value=`getValue "$2"`
                MSG=`${LAUNCH} "${_param}" "${_value}"  2>&1`
                ;;
            *)
                # Invalid command line
                printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
                ;;
        esac
        case $? in
            0)
                # Display result
                if [ -n "${MSG}" ]; then
                    echo "${MSG}"
                fi
                exit 0
                ;;
            3)
                # Connection problem, cacao might be starting
                printErrorMessage "${CACAOADM_NOT_CONNECT}"
                exit 1
                ;;
            *)
                # Unexpected problem
                printErrorMessage "${MISSING_LOGGER}"
                exit 1
                ;;
        esac	
    ;;

    "restart")

	isRoot
	$0 stop
	if [ $? -ne 0 ]; then
		exit 1
	fi
	$0 start
	if [ $? -ne 0 ]; then
		exit 1
	fi
	exit 0
	;;


    "create")
	# Keep it for sun cluster 3.1U3 compatibility
	isRoot
	case $# in
	    2)
		if [ $2 != "key" ]; then
		    printErrorMessage "${INVALID_COMMAND}"
		    displayHelp
		    exit 2
		fi
		;;
	    3)
		if [ $2 != "-f"  -a $2 != "--force" -o $3 != "key" ]; then
		    printErrorMessage "${INVALID_COMMAND}"
		    displayHelp
		    exit 2
		fi
		;;
	    *)
		printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
		;;
	esac

	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	# Generate key if necessary
	if [ -d ${SECURITY_DIR} ]; then
	    if [ $2 != "-f" -a $2 != "--force" ]; then
		if [ ! -f ${SECURITY_DIR}/password ] ; then
		    generateKeys
		    if [ $? -ne 0 ]
		    then
			exit 1
		    fi
		fi
	    else 
		generateKeys
		if [ $? -ne 0 ]
		then
		    exit 1
		fi
	    fi

	else
	    printErrorMessage "${MISSING_PACKAGE}"
	    exit 1
	fi
    ;;

    create-keys)
	if [ $# -gt 2 ]; then
	    printErrorMessage "${INVALID_COMMAND}"
	    displayHelp
	    exit 2
	fi

	if [ $# -eq 2 ]; then
	    if [ "$2" != "-f" -a "$2" != "--force" ]; then
		printErrorMessage "${INVALID_COMMAND}"
		displayHelp
		exit 2
	    else
		_force="yes"
	    fi
	fi
	
	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	# Generate key if necessary
	if [ -d ${SECURITY_DIR} ]; then
	    if [ -z "${_force}" ]; then
		if [ ! -f ${SECURITY_DIR}/password ] ; then
		    generateKeys
		    if [ $? -ne 0 ]
		    then
			exit 1
		    fi
		fi
	    else 
		generateKeys
		if [ $? -ne 0 ]
		then
		    exit 1
		fi
	    fi

	else
	    printErrorMessage "${MISSING_PACKAGE}"
	    exit 1
	fi
    ;;
	
    "start" | "debug")

        if [ $1 = "start" ] ; then
	    isRoot

	fi

	umask 022
	${MKDIR} -p ${LOG_DIR}
	${MKDIR} -p ${PID_DIR}

	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	lock
	if [ $? -ne 0 ]; then
	    printErrorMessage "${CACAO_LOCK}"
	    printErrorMessage "${CACAO_LOCK2}" "${CACAO_LOCK_FILE}"
	    exit 1
	fi

        # Check if Cacao is running
        isCacaoRunning
        if [ $? -ne 0 ]; then
            # Only one instance of Cacao allowed
            if [ ${PID} -eq 0 ]; then
                printErrorMessage "${ALREADY_RUNNING}" $0
            else
                printErrorMessage "${ALREADY_RUNNING2}" $0 ${PID}
            fi
	    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
            exit 1
        fi


	$0 create-keys
	if [ $? -ne 0 ]
	then
	    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
	    exit 1
	fi 
	
	check_snmp_config
	if [ $? -ne 0 ]; then
           printErrorMessage "${INVALID_JDMK_SNMP_CONFIG}"
	   ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
           exit 1;
	fi
	

	if [ -z "${CACAO_PROTO}" ]; then
	    if [ $1 = "start"  ]; then
		${CHOWN} -R noaccess ${VAR_DIR}
	    fi
	fi
	
	JAVA_FLAGS=`getProperty ${JAVA_FLAGS_KEY}`
	JAVA_DEBUG_FLAGS=`getProperty ${JAVA_DEBUG_FLAGS_KEY}`
	LAUNCH="${JAVA} ${JAVA_FLAGS} ${JAVA_DEBUG_FLAGS} \
		-classpath ${CLASSPATH}	\
		-Djavax.management.builder.initial=com.sun.jdmk.JdmkMBeanServerBuilder \
		-Djava.util.logging.config.class=com.sun.cacao.logging.LoggingInit \
		-Dcacao.properties=${PROPERTY_FILE} \
		com.sun.cacao.container.Container"

	# Check if we are in debug or start
	if [ $1 = "debug" ]; then
	    ${CAT} ${PASSWD_FILE} | ${LAUNCH}
	    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
	    exit 0;
 	fi

	PROCESS_USERNAME=`getProperty "${PROCESS_USERNAME_KEY}"`
	if [ -z "${PROCESS_USERNAME}" ]; then
	    PROCESS_USERNAME=${DEFAULT_PROCESS_USERNAME}
	fi

	${ID} ${PROCESS_USERNAME} >/dev/null 2>&1
	if [ $? -ne 0 ] ; then
	    printErrorMessage "${INVALID_INDENTITY}" ${PROCESS_USERNAME}
	    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
	    exit 1
	fi

	RETRIES=`getProperty "${RETRIES_KEY}"`
	if [ -z "${RETRIES}" ]; then
		RETRIES=1
	fi
	
	# Check if PMF is available
        if [ ${PMF} -eq 1 ]; then
            # Run Cacao PMF
            # Number of retries set to RETRIES and a two minute failure period.
            # If there are more than 1 failures in a two minute period, the pmf
            # will stop attempting to restart the daemon.
            ${PMFADM} -c ${DAEMON_NAME} -C 2 -t 2 -n ${RETRIES} -- \
		${PRIVATE_BIN_DIR}/launch -w "${CACAO_ROOT}" -f -U ${PROCESS_USERNAME} -G ${PROCESS_USERNAME} -i ${PASSWD_FILE} -- ${LAUNCH}
 
	    
            if [ $? -ne 0 ]; then
                printSyslogErrorMessage "Error: Can't register cacao agent in PMF."
            else
		${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                exit 0;
            fi
        fi

	${RM} -f "${RETRIES_FILE}" 2>/dev/null
	RETRIES=`expr ${RETRIES} + 1`
	echo "${RETRIES}" > ${RETRIES_FILE}
	# Run Cacao under default mechanism
	${PRIVATE_BIN_DIR}/launch -w "${CACAO_ROOT}" -r "${RETRIES_FILE}" -s 1 -U ${PROCESS_USERNAME} -G ${PROCESS_USERNAME} -i ${PASSWD_FILE} -R ${PID_FILE} -- ${LAUNCH}
	${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
	exit 0
	;;


    "deploy" | "undeploy" | "lock" | "unlock")
	isRoot

	if [ $# -ne 2 ]; then
	    displayHelp
	    exit 2
	fi

	isCacaoRunning
	if [ $? -eq 0 ]; then
	    # Cacao must be running
	    printErrorMessage "${CACAOADM_MUST_RUN}"
	    exit 1
	fi

	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}
	PARAMETERS="`${HOSTNAME}` $1"
	LAUNCH="${JAVA} \
		-Dcacao.properties=${PROPERTY_FILE} \
		-classpath ${CLASSPATH} \
		com.sun.cacao.admin.Administration ${PARAMETERS}"
	MSG=`${LAUNCH} $2 2>&1`
	case $? in
	    0)
		# Display result
		if [ -n "${MSG}" ]; then
		    echo "${MSG}"
		fi
		exit 0
		;;
	    3)
		# Connection problem, cacao might be starting
		printErrorMessage "${CACAOADM_NOT_CONNECT}"
		exit 1
		;;
	    *)
		# Unexpected problem
		printErrorMessage "${MSG}"
		exit 1
		;;
	 esac
	;;
    "stop")

	isRoot
	COMMAND=stop

	if [ $# -gt 2 ]; then
	    displayHelp
	    exit 2
	fi
	
	if [ $# -eq 2 ]; then
	    if [ "$2" = "-f" -o "$2" = "--force" ]; then
		COMMAND=abort
		# The following code should be removed when BUG 5099553 
		# is fixed
		lock
		if [ $? -ne 0 ]; then
		    printErrorMessage "${CACAO_LOCK}"
		    printErrorMessage "${CACAO_LOCK2}" "${CACAO_LOCK_FILE}"
		    exit 1
		fi

		isCacaoRunning
		case $? in 
		0)
		     # Cacao is not running
		    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
		    exit 0
		    ;;
		1)
		    killProcesses ${PID}
		    while [ ! -z "${PID}" ] ; do
			if ${PS} -p ${PID} >/dev/null ; then
			    ${SLEEP} 1
			else
			    break
			fi
		    done
		    ${RM} -f ${PID_FILE} 2>/dev/null
		    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
		    exit 0
		    ;;
		2)
		    # Cacao is running under PMF
		    ${PMFADM} -w ${PMF_TIMEOUT} -s ${DAEMON_NAME} KILL \
			>/dev/null 2>&1
		    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
		    exit 0
		    ;;
		 *)
		    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
		    ;;
		esac
	    else
		displayHelp
		exit 2	
	    fi
	fi

	# find dependencies
	locateDependencies
	CLASSPATH=`${ECHO} ${JDMK_HOME}/lib/*.jar|${SED} 's+  *+:+g'`
	CLASSPATH=${JAR_DIR}/cacao_cacao.jar:${CLASSPATH}

	lock
	if [ $? -ne 0 ]; then
	    printErrorMessage "${CACAO_LOCK}"
	    printErrorMessage "${CACAO_LOCK2}" "${CACAO_LOCK_FILE}"
	    exit 1
	fi

        isCacaoRunning
        case $? in
            0)
                # Cacao is not running
		${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                exit 0
	        ;;
            1)
                # Cacao is running under default mechanism
                if [ -d "${SECURITY_DIR}" ]; then
                     CLASSPATH=${JAR_DIR}/cacao_admin.jar:${CLASSPATH}
                     PARAMETERS="`${HOSTNAME}` ${COMMAND}"
                     LAUNCH="${JAVA} \
                         -Dcacao.properties=${PROPERTY_FILE} \
                         -classpath ${CLASSPATH} \
                         com.sun.cacao.admin.Administration ${PARAMETERS}"
                     # Run the command (stop or abort)
                     ${LAUNCH} >/dev/null 2>&1
                     if [ $? -eq 0 ]; then
			# Empty the PID_FILE
                        ${RM} -f ${PID_FILE} 2>/dev/null
                        if [ $? -ne 0 ]; then
			    printErrorMessage ${FAIL_RM} ${PID_FILE}
			    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                            exit 1
                        fi
			${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                        exit 0
                  
		     fi
                fi
		# We have an error, we kill the agent
		killProcesses ${PID}
                while [ ! -z "${PID}" ] ; do
                    if ${PS} -p ${PID} >/dev/null ; then
                        ${SLEEP} 1
                    else
                        break
                fi
                done
                # Empty the PID_FILE
                ${RM} -f ${PID_FILE} 2>/dev/null
                if [ $? -ne 0 ]; then
                    printErrorMessage ${FAIL_RM} ${PID_FILE}
		    ${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                    exit 1
                fi

		# Clean lock file
		${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                exit 0
	        ;;
            2)
                # Cacao is running under PMF
                ${PMFADM} -w ${PMF_TIMEOUT} -s ${DAEMON_NAME} KILL \
                    >/dev/null 2>&1
		${RM} "${CACAO_LOCK_FILE}" 2>/dev/null
                exit 0
	        ;;
        esac
        ;;


    *)

	displayHelp
	exit 2
        ;;
esac
