# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8

######################################################################
# Gestion des processus

function wo_pidof() {
    # obtenir le(s) pid de l'instance $1

    # attention! on doit avoir un ps non legacy (cf sysinc/system_caps)
    ps_all | grep "\-[W]OApplicationName $1 " | awk '{ print $1 }'

    # note: on met [W] entre crochet pour que le processus associé à grep ne
    # soit pas pris dans la liste

    # note: on met un espace après le nom de l'application pour ne matcher que
    # celle-là.
}

######################################################################
# Services basés sur le parcours du fichier SiteConfig.xml

AWK_FUNCTIONS='
function get_value(line) {
    match(line, /^[^<]*<[^<>]*>/); line = substr(line, RSTART + RLENGTH)
    match(line, /<.*$/); line = substr(line, 1, RSTART - 1)
    return line
}

function get_attr_value(attr, line) {
    match(line, attr "=\""); line = substr(line, RSTART + RLENGTH)
    match(line, /".*$/); line = substr(line, 1, RSTART - 1)
    return line
}
'

function siteconf_dump_hosts() {
    # Retourner la liste des hôtes configurés
    # Chaque ligne est de la forme:
    #     host type
    [ -f "$WOCONFIGURATION/SiteConfig.xml" ] || return 1

    awk <"$WOCONFIGURATION/SiteConfig.xml" "$AWK_FUNCTIONS"'
BEGIN {
    in_hosts = 0
}

!in_hosts && $0 ~ /<hostArray / { in_hosts = 1 }
in_hosts && $0 ~ /<\/hostArray>/ { in_hosts = 0 }

in_hosts && $0 ~ /<element / {
    name = ""
    type = ""
}
in_hosts && $0 ~ /<\/element>/ {
    print name " " type
}

in_hosts && $0 ~ /<name / { name = get_value($0) }
in_hosts && $0 ~ /<type / { type = get_value($0) }
'
}

function get_pathName() {
    local system pathName
    for system in Linux SunOS; do
        [ "$system" == "$SYSTEM_NAME" ] && pathName=unixPath
    done
    for system in Darwin; do
        [ "$system" == "$SYSTEM_NAME" ] && pathName=macPath
    done
    for system in Cygwin Mingw; do
        [ "$system" == "$SYSTEM_NAME" ] && pathName=windowsPath
    done
    [ -n "$pathName" ] && echo "$pathName"
}

function siteconf_dump_applications() {
    # Retourner la liste des mapplications configurées
    # Chaque ligne est de la forme:
    #     name autoRecover debuggingEnabled path
    [ -f "$WOCONFIGURATION/SiteConfig.xml" ] || return 1

    pathName="$(get_pathName)"
    awk -v pathName="$pathName" <"$WOCONFIGURATION/SiteConfig.xml" "$AWK_FUNCTIONS"'
BEGIN {
    in_applications = 0
}


!in_applications && $0 ~ /<applicationArray / { in_applications = 1 }
in_applications && $0 ~ /<\/applicationArray>/ { in_applications = 0 }

in_applications && $0 ~ /<element / {
    name = ""
    autoRecover = ""
    debuggingEnabled = ""
    path = ""
}
in_applications && $0 ~ /<\/element>/ {
    print name " " autoRecover " " debuggingEnabled " " path
}

in_applications && $0 ~ /<name / { name = get_value($0) }
in_applications && $0 ~ /<autoRecover / { autoRecover = get_value($0) }
in_applications && $0 ~ /<debuggingEnabled / { debuggingEnabled = get_value($0) }
in_applications && $0 ~ "<" pathName " " { path = get_value($0) }
'
}

function siteconf_dump_instances() {
    # Retourner la liste des minstances configurées
    # Chaque ligne est de la forme:
    #     applicationName id hostName port autoRecover debuggingEnabled path
    [ -f "$WOCONFIGURATION/SiteConfig.xml" ] || return 1

    awk -v pathName="$pathName" <"$WOCONFIGURATION/SiteConfig.xml" "$AWK_FUNCTIONS"'
BEGIN {
    in_instances = 0
}


!in_instances && $0 ~ /<instanceArray / { in_instances = 1 }
in_instances && $0 ~ /<\/instanceArray>/ { in_instances = 0 }

in_instances && $0 ~ /<element / {
    applicationName = ""
    id = ""
    hostName = ""
    port = ""
    autoRecover = ""
    debuggingEnabled = ""
    path = ""
}
in_instances && $0 ~ /<\/element>/ {
    print applicationName " " id " " hostName " " port " " autoRecover " " debuggingEnabled " " path
}

in_instances && $0 ~ /<applicationName / { applicationName = get_value($0) }
in_instances && $0 ~ /<id / { id = get_value($0) }
in_instances && $0 ~ /<hostName / { hostName = get_value($0) }
in_instances && $0 ~ /<port / { port = get_value($0) }
in_instances && $0 ~ /<autoRecover / { autoRecover = get_value($0) }
in_instances && $0 ~ /<debuggingEnabled / { debuggingEnabled = get_value($0) }
in_instances && $0 ~ /<path / { path = get_value($0) }
'
}

function get_instances_for_woa() {
    # lister les instances qui correspondent à l'application $1
    # $1 peut être de la forme App.woa ou /path/to/App.woa
    if [[ "$1" == /* ]]; then
        local path="$1"
    else
        local path="$WOAPPLICATIONS/$(basename "$1")"
    fi
    local app="$(basename "$path")"
    local appname="$(basename "$app" .woa)"
    local appscript="$path/$appname"

    siteconf_dump_applications | uawk -v appscript="$appscript" '$4 == appscript { print $1 }' 
}

function get_instances_for_framework() {
    # lister les instances qui correspondent aux applications qui utilisent le framework $1
    # $1 doit être de la forme Fw.framework
    local fwname="$(basename "$1")" fwnames appnames appname app
    appnames="$(list_dirs "$WOAPPLICATIONS" "*.woa")"
    while next_arg appnames appname; do
        app="$WOAPPLICATIONS/$appname"
        array_from_lines fwnames "$(dump_frameworks "$app")"
        if array_contains fwnames "$fwname"; then
            get_instances_for_woa "$app"
        fi
    done
}

function siteconf_get_monitor_password() {
    # Lire le mot de passe dans le fichier SiteConfig.xml
    [ -f "$WOCONFIGURATION/SiteConfig.xml" ] || return 1

    awk <"$WOCONFIGURATION/SiteConfig.xml" '
$0 ~ /<password/ {
    #print gensub("^.*>([^<]*)<.*$", "\\1", 1)
    match($0, /^[^<]*<[^<>]*>/); $0 = substr($0, RSTART + RLENGTH)
    match($0, /<.*$/); $0 = substr($0, 1, RSTART - 1)
    print
}
'
}

function siteconf_get_instance_data_for_updateWotaskd() {
    # obtenir les informations au format XML pour les instances données, à
    # utiliser avec <updateWotaskd>
    # Les informations sont retournées pour chaque minstance, une par ligne.
    [ -f "$WOCONFIGURATION/SiteConfig.xml" ] || return 1
    [ -n "$*" ] || return 1

    script='
BEGIN {
    found_instances = 0
    found_element = 0
}

$0 ~ /<instanceArray/ {
    found_instances = 1
}

found_instances && $0 ~ /<element/ {
    found_element = 1
    name = ""
    data = ""
    next
}

found_element && $0 ~ /<applicationName/ {
    #name = gensub("^.*>([^<]*)<.*$", "\\1", 1)
    name = $0
    match(name, /^[^<]*<[^<>]*>/); name = substr(name, RSTART + RLENGTH)
    match(name, /<.*$/); name = substr(name, 1, RSTART - 1)
}

found_element && $0 ~ /<\/element/ {
    if ('

    local instance notfirst=
    for instance in "$@"; do
        script="$script${notfirst:+|| }name == \"$(quote_awk "$instance")\""
        notfirst=1
    done
    script="$script"') {
        print data
    }
    found_element = 0
    next
}

found_element {
    match($0, /^[\t]*/)
    $0 = substr($0, RSTART + RLENGTH)
    data = data $0
}

found_instances && $0 ~ /<\/instanceArray/ {
    found_element = 0
    found_instances = 0
}
'

    awk <"$WOCONFIGURATION/SiteConfig.xml" "$script"
}

function siteconf_get_instance_data_for_commandWotaskd() {
    # obtenir les informations au format XML pour les instances données, à
    # utiliser avec <commandWotaskd>
    # Les informations sont retournées pour chaque minstance, une par ligne.
    [ -f "$WOCONFIGURATION/SiteConfig.xml" ] || return 1

    script='
BEGIN {
    found_instances = 0
    found_element = 0
}

$0 ~ /<instanceArray/ {
    found_instances = 1
}

found_instances && $0 ~ /<element/ {
    found_element = 1
    id = ""
    port = ""
    name = ""
    hostName = ""
    next
}

found_element && $0 ~ /<id/ {
    #id = gensub("^.*>([^<]*)<.*$", "\\1", 1)
    id = $0
    match(id, /^[^<]*<[^<>]*>/); id = substr(id, RSTART + RLENGTH)
    match(id, /<.*$/); id = substr(id, 1, RSTART - 1)
}
found_element && $0 ~ /<port/ {
    #port = gensub("^.*>([^<]*)<.*$", "\\1", 1)
    port = $0
    match(port, /^[^<]*<[^<>]*>/); port = substr(port, RSTART + RLENGTH)
    match(port, /<.*$/); port = substr(port, 1, RSTART - 1)
}
found_element && $0 ~ /<applicationName/ {
    #name = gensub("^.*>([^<]*)<.*$", "\\1", 1)
    name = $0
    match(name, /^[^<]*<[^<>]*>/); name = substr(name, RSTART + RLENGTH)
    match(name, /<.*$/); name = substr(name, 1, RSTART - 1)
}
found_element && $0 ~ /<hostName/ {
    #hostName = gensub("^.*>([^<]*)<.*$", "\\1", 1)
    hostName = $0
    match(hostName, /^[^<]*<[^<>]*>/); hostName = substr(hostName, RSTART + RLENGTH)
    match(hostName, /<.*$/); hostName = substr(hostName, 1, RSTART - 1)
}

found_element && $0 ~ /<\/element/ {
    if ('

    local instance notfirst=
    for instance in "$@"; do
        script="$script${notfirst:+|| }name == \"$(quote_awk "$instance")\""
        notfirst=1
    done
    script="$script"') {
        print "<id type=\"NSNumber\">" id "</id><port type=\"NSNumber\">" port "</port><applicationName type=\"NSString\">" name "</applicationName><hostName type=\"NSString\">" hostName "</hostName>"
    }
    found_element = 0
    next
}

found_element {
    match($0, /^[\t]*/)
    $0 = substr($0, RSTART + RLENGTH)
    data = data $0
}

found_instances && $0 ~ /<\/instanceArray/ {
    found_element = 0
    found_instances = 0
}
'

    awk <"$WOCONFIGURATION/SiteConfig.xml" "$script"
}

function get_autostart() {
    # Afficher le chemin vers le fichier $WOCONFIGURATION/AutoStart.txt
    echo "$WOCONFIGURATION/AutoStart.txt"
}

function apply_autostart_order() {
    # Reordonner les instances du tableau $1 selon la liste données dans le
    # fichier $WOCONFIGURATION/AutoStart.txt
    local autostart_="$(get_autostart)"
    [ -r "$autostart_" ] || return

    local -a oinsts_ srcname_ dest_
    local oinst_
    array_from_lines oinsts_ "$(<"$autostart_" filter_conf)"

    srcname_="$1"
    for oinst_ in "${oinsts_[@]}"; do
        if array_contains "$srcname_" "$oinst_"; then
            array_add dest_ "$oinst_"
            array_del "$srcname_" "$oinst_"
        fi
    done
    array_extend dest_ "$srcname_"

    array_copy "$srcname_" dest_
}

######################################################################
# Services basés sur wotaskd, sans mot de passe

function wotaskd_dump_woconfig() {
    # afficher la configuration de wotaskd sur l'hôte $1 (par défaut
    # $FQDNHOST). Il s'agit de la liste, pour chacune des instances, des
    # minstances qui tournent actuellement.
    # cette fonction n'a pas besoin de mot de passe pour fonctionner.
    local host="${1:-$FQDNHOST}"
    dumpurl -X "http://$host:1085/cgi-bin/WebObjects/wotaskd.woa/wa/woconfig"
}

function wotaskd_dump_running_instances() {
    wotaskd_dump_woconfig | awk "$AWK_FUNCTIONS"'
BEGIN {
    in_application = 0
}

!in_application && $0 ~ /<application / {
    in_application = 1
    name = get_attr_value("name", $0)
    id = ""
    port = ""
    host = ""
}
in_application && $0 ~ /<\/application>/ { in_application = 0 }

in_application && $0 ~ /<instance / {
    id = get_attr_value("id", $0)
    port = get_attr_value("port", $0)
    host = get_attr_value("host", $0)
    print name " " id " " port " " host
}'
}

function wotaskd_get_running_instances() {
    # Obtenir la liste des instances (une par ligne) qui tournent actuellement
    # sur l'hôte $1 (par défaut $FQDNHOST).
    # cette fonction n'a pas besoin de mot de passe pour fonctionner.
    wotaskd_dump_woconfig "$1" | awk '
$0 ~ /<application/ {
    #print gensub("^.*name=\"([^\"]*)\".*$", "\\1", 1)
    match($0, /^.*name="/); $0 = substr($0, RSTART + RLENGTH)
    match($0, /".*$/); $0 = substr($0, 1, RSTART - 1)
    print
}
'
}

######################################################################
# Services basés sur wotaskd, avec mot de passe
# note: pour le fonctions de cette section, si un mot de passe est configuré
# pour le moniteur, la fonction doit être appelée avec le bon mot de passe
# (option -P). Pour obtenir le mot de passe, on peut utiliser la fonction
# siteconf_get_monitor_password()

function _getopt_host_and_password() {
    # obtenir du code qui initialise l'hôte et le mot de passe à partir des
    # arguments de la ligne de commande. Il faut utiliser ce code de cette
    # manière:
    #    eval "$(_getopt_host_and_password)"
    # l'option -h permet de spécifier l'hôte ($FQDNHOST par défaut)
    # l'option -P permet de spécifier le mot de passe
    # l'option -o permet de spécifier un fichier de sortie

    echo '
local done= host="$FQDNHOST" password="$(siteconf_get_monitor_password)" outputfile="/dev/null"
while [ -n "$1" ]; do
    case "$1" in
    --)
        shift
        done=1
        ;;

    -h)
        shift
        host="$1"
        ;;

    -P)
        shift
        password="$1"
        ;;

    -o)
        shift
        outputfile="$1"
        ;;

    -*)
        #ewarn "option non reconnue: $1"
        ;;

    *)
        done=1
        ;;
    esac
    [ -n "$done" ] && break
    shift
done
'
}

function wotaskd_command() {
    # lancer une commande wotask $1 avec le mot de passe $2 sur l'hôte $3
    dumpurl -X -m POST "$1" ${2:+-H password "$2"} "http://$3:1085/cgi-bin/WebObjects/wotaskd.woa/wa/monitorRequest" ||
    echo "ERROR: mot de passe incorrect ou dumpurl non disponible"
}

function wotaskd_dump_instances() {
    # afficher la configuration des mapplications (instances) de wotaskd sur un
    # hôte. Il s'agit de la liste des instances qui sont configurées.
    eval "$(_getopt_host_and_password)"
    wotaskd_command '<monitorRequest type="NSDictionary"><queryWotaskd type="NSString">APPLICATION</queryWotaskd></monitorRequest>' "$password" "$host"
}

function wotaskd_dump_minstances() {
    # afficher la configuration des minstances de wotaskd sur un hôte. Il
    # s'agit de la liste des instances qui sont configurées
    eval "$(_getopt_host_and_password)"
    wotaskd_command '<monitorRequest type="NSDictionary"><queryWotaskd type="NSString">INSTANCE</queryWotaskd></monitorRequest>' "$password" "$host"
}

function dump_minstances_stats_from_stdin() {
    # Afficher les statistiques pour les instances de la ligne de commande à
    # partir de la sortie de wotaskd_dump_minstances
    # Les lignes affichées sont de la forme:
    #   applicationName id port runningState activeSessions transactions startedAt avgTransactionTime averageIdlePeriod
    script="$AWK_FUNCTIONS"'
BEGIN {
    in_instances = 0
}

!in_instances && $0 ~ /<instanceResponse / { in_instances = 1 }
in_instances && $0 ~ /<\/instanceResponse>/ { in_instances = 0 }

in_instances && $0 ~ /<element / {
    applicationName = ""
    id = ""
    port = ""
    runningState = ""
    activeSessions = ""
    transactions = ""
    startedAt = ""
    avgTransactionTime = ""
    averageIdlePeriod = ""
}
in_instances && $0 ~ /<\/element>/ {
    if (applicationName != ""'
    local mapp filter
    for mapp in "$@"; do
        filter="${filter:+$filter || }applicationName == \"$mapp\""
    done
    [ -n "$filter" ] && filter="&& ($filter)"
    script="$script$filter"') {
        print applicationName " " id " " port " " runningState " " activeSessions " " transactions " " startedAt " " avgTransactionTime " " averageIdlePeriod
    }
}

in_instances && $0 ~ /<applicationName / { applicationName = get_value($0) }
in_instances && $0 ~ /<id / { id = get_value($0) }
in_instances && $0 ~ /<port / { port = get_value($0) }
in_instances && $0 ~ /<runningState / { runningState = get_value($0) }
in_instances && $0 ~ /<activeSessions / { activeSessions = get_value($0) }
in_instances && $0 ~ /<transactions / { transactions = get_value($0) }
in_instances && $0 ~ /<startedAt / { startedAt = get_value($0) }
in_instances && $0 ~ /<avgTransactionTime / { avgTransactionTime = get_value($0) }
in_instances && $0 ~ /<averageIdlePeriod / { averageIdlePeriod = get_value($0) }
'
    uawk -v minst="$1" "$script"
}

function wotaskd_get_configured_instances() {
    # afficher la liste des instances configurées sur un hôte.
    eval "$(_getopt_host_and_password)"

    wotaskd_dump_instances -h "$host" -P "$password" | awk '
$0 ~ /<name/ {
    #print gensub("^.*>([^<]*)<.*$", "\\1", 1)
    match($0, /^[^<]*<[^<>]*>/); $0 = substr($0, RSTART + RLENGTH)
    match($0, /<.*$/); $0 = substr($0, 1, RSTART - 1)
    print
}
'
}

function wotaskd_command_instances_from_stdin() {
    # lancer une commande pour les instances avec les lignes lues sur stdin
    eval "$(_getopt_host_and_password)"

    local COMMAND="$1"; shift
    wotaskd_command "$(
echo '<monitorRequest type="NSDictionary"><commandWotaskd type="NSArray"><element type="NSString">'"$COMMAND"'</element>'
while read element; do
    echo '<element type="NSDictionary">'"$element"'</element>'
done
echo '</commandWotaskd></monitorRequest>'
)" "$password" "$host" >&"$outputfile"
}

function wotaskd_update_instances_from_stdin() {
    # Metttre à jour les instances avec les lignes lues sur stdin
    eval "$(_getopt_host_and_password)"

    wotaskd_command "$(
echo '<monitorRequest type="NSDictionary"><updateWotaskd type="NSDictionary"><configure type="NSDictionary"><instanceArray type="NSArray">'
while read element; do
    echo '<element type="NSDictionary">'"$element"'</element>'
done
echo '</instanceArray></configure></updateWotaskd></monitorRequest>'
)" "$password" "$host" >&"$outputfile"
}