##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ## Gestion des services de webobjects (démarrage/arrêt), et de leur configuration ##@cooked nocomments ##@require base ##@require sysinfos ##@require javaproperties uprovide webobjects urequire base sysinfos javaproperties ################################################################################ # Préfixes __webobjects_prefixes= function __compute_webobjects_prefixes() { [ -n "$__webobjects_prefixes" ] && return if check_sysinfos -s darwin; then # valeurs par défaut de NEXT_ROOT, WOROOT et LOCALROOT sur MacOS X DEFAULT_NEXT_ROOT= function get_default_woroot_prefix() { echo "$NEXT_ROOT/System"; } function get_default_localroot_prefix() { echo "$NEXT_ROOT"; } else # valeurs par défaut de NEXT_ROOT, WOROOT et LOCALROOT sur les autres Unix DEFAULT_NEXT_ROOT=/opt/Apple function get_default_woroot_prefix() { echo "$NEXT_ROOT"; } function get_default_localroot_prefix() { echo "$NEXT_ROOT/Local"; } fi NEXT_ROOT="${NEXT_ROOT:-$DEFAULT_NEXT_ROOT}" WOROOT="${WOROOT:-$(get_default_woroot_prefix)}" LOCALROOT="${LOCALROOT:-$(get_default_localroot_prefix)}" SYSTEMFRAMEWORKS="$WOROOT/Library/Frameworks" WOEXTENSIONS="$LOCALROOT/Library/WebObjects/Extensions" WOFRAMEWORKS="$LOCALROOT/Library/WebObjects/Applications/Frameworks" WOAPPLICATIONS="$LOCALROOT/Library/WebObjects/Applications" WOCONFIGURATION="$LOCALROOT/Library/WebObjects/Configuration" WOAUTOSTART="$WOCONFIGURATION/AutoStart.txt" WOLOGS="/var/log/WebObjects" local versionfile="$SYSTEMFRAMEWORKS/JavaWebObjects.framework/Resources/version.plist" [ -f "$versionfile" ] && WOVERSION="$(grep -A 1 CFBundleShortVersionString "$versionfile" | tail -1 | sed 's/^.*\(.*\)<\/string>.*$/\1/')" || WOVERSION= __webobjects_prefixes=1 } UTOOLS_PREFIXES=("${UTOOLS_PREFIXES[@]}" NEXT_ROOT WOROOT LOCALROOT SYSTEMFRAMEWORKS WOEXTENSIONS WOFRAMEWORKS WOAPPLICATIONS WOCONFIGURATION WOAUTOSTART WOLOGS WOVERSION) function compute_webobjects_prefixes() { __compute_webobjects_prefixes } function recompute_webobjects_prefixes() { __webobjects_prefixes= __compute_webobjects_prefixes } function get_NEXT_ROOT_prefix() { __compute_webobjects_prefixes echo "$NEXT_ROOT" } function get_WOROOT_prefix() { __compute_webobjects_prefixes echo "$WOROOT" } function get_LOCALROOT_prefix() { __compute_webobjects_prefixes echo "$LOCALROOT" } function get_SYSTEMFRAMEWORKS_prefix() { __compute_webobjects_prefixes echo "$SYSTEMFRAMEWORKS" } function get_WOEXTENSIONS_prefix() { __compute_webobjects_prefixes echo "$WOEXTENSIONS" } function get_WOFRAMEWORKS_prefix() { __compute_webobjects_prefixes echo "$WOFRAMEWORKS" } function get_WOAPPLICATIONS_prefix() { __compute_webobjects_prefixes echo "$WOAPPLICATIONS" } function get_WOCONFIGURATION_prefix() { __compute_webobjects_prefixes echo "$WOCONFIGURATION" } function get_WOAUTOSTART_prefix() { __compute_webobjects_prefixes echo "$WOAUTOSTART" } function get_WOLOGS_prefix() { __compute_webobjects_prefixes echo "$WOLOGS" } function get_WOVERSION_prefix() { __compute_webobjects_prefixes echo "$WOVERSION" } ################################################################################ # Bundles function is_wobundle() { # Tester si $1 a un nom de bundle valide, c'est à dire avec l'extension .woa # ou .framework local bundle="$(basename "$(abspath "$1")")" [ "${bundle%.woa}" != "$bundle" -o "${bundle%.framework}" != "$bundle" ] } function is_woappdir() { # Tester si $1 est un répertoire d'application webobjects. Le test est # effectué sur le contenu du bundle, pas sur le nom (utiliser is_wobundle() # pour cela) # existence du répertoire [ -d "$1" ] || return 1 # répertoires de resources [ -d "$1/Contents/Resources" ] || return 1 # répertoires de classpath [ -d "$1/Contents/UNIX" ] || return 1 [ -d "$1/Contents/MacOS" ] || return 1 [ -d "$1/Contents/Windows" ] || return 1 # fin des tests return 0 } function is_wofwkdir() { # Tester si $1 est un répertoire de framework webobjects. Le test est # effectué sur le contenu du bundle, pas sur le nom (utiliser is_wobundle() # pour cela) # existence du répertoire [ -d "$1" ] || return 1 # répertoires de resource [ -d "$1/Resources" -o -d "$1/WebServerResources" ] || return 1 # fin des tests return 0 } function get_app_winclspth() { # calculer la valeur de Contents/Windows/CLSSPATH.txt pour l'application $1 local found if [ ! -f "$1/Contents/Windows/CLSSPATH.txt" ]; then local clspth array_from_lines clspth "$(list_files "$1/Contents/Windows" | grep -i clsspath.txt)" if [ ${#clspth[*]} -eq 1 ]; then echo "Contents/Windows/$clspth" found=1 fi fi # pas trouvé, prendre la valeur par défaut [ -n "$found" ] || echo Contents/Windows/CLSSPATH.txt } function get_infofile() { # Obtenir le chemin vers le fichier Info.plist dans le répertoire de # resource du bundle $1 local bundle="$(abspath "$1")" resdir if endswith "$bundle" .woa; then resdir="$bundle/Contents" elif endswith "$bundle" .framework; then resdir="$bundle/Resources" else # on a donné directement resdir resdir="$bundle" fi echo "$resdir/Info.plist" } function read_infofile() { # Lire la version et le numéro de release dans le fichier $1 (chemin vers # Info.plist) et les placer dans les variables $2(=version) et $3(=release) # Retourner 1 si un erreur s'est produite, par exemple si le fichier $1 # n'existe pas ou n'est pas accessible en lecture [ -f "$1" -a -r "$1" ] || return 1 set_var "${2:-version}" "$(grep -A 1 CFBundleShortVersionString "$1" | tail -1 | sed 's/^.*\(.*\)<\/string>.*$/\1/')" set_var "${3:-release}" "$(grep -A 1 CFBundleVersion "$1" | tail -1 | sed 's/^.*\(.*\)<\/string>.*$/\1/')" } function write_infofile() { # Ecrire $2 (la version) et $3 (le numéro de release) dans le fichier $1 # (chemin vers Info.plist) # Retourner 1 si un erreur s'est produite, par exemple si le fichier $1 # n'existe pas local status tmpfile ac_set_tmpfile tmpfile <"$1" >"$tmpfile" cawkrun version="$2" release="$3" ' /CFBundleShortVersionString<\/key>/ { print; getline sub(/.*<\/string>/, "" version "") print; next } /CFBundleVersion<\/key>/ { print; getline sub(/.*<\/string>/, "" release "") print; next } { print } ' && cat "$tmpfile" >"$1" status=$? ac_clean "$tmpfile" return $status } function get_jawotoolsfile() { # Obtenir le chemin vers le fichier jawotools.properties dans le bundle $1 local default="$1/jawotools.properties" file for file in "$default" "$1/build_infos.txt"; do if [ -f "$file" ]; then echo "$file" return fi done echo "$default" } function read_jawotoolsfile() { # lire le fichier de propriété $1 et placer les valeurs dans les variables # $2(=version), $3(=releaseDate), $4(=description) local filename="$(basename "$1")" if [ "$filename" == "build_infos.txt" ]; then # legacy read_property "$1" version "${2:-version}" read_property "$1" date "${3:-releaseDate}" read_property "$1" desc "${4:-description}" else read_property "$1" version "${2:-version}" read_property "$1" releaseDate "${3:-releaseDate}" read_property "$1" description "${4:-description}" fi } function save_jawotoolsfile() { # écrire le fichier de propriété $1 avec les valeurs version ($2), # releaseDate ($3) et description ($4) [ -e "$1" ] || touch "$1" write_property "$1" version "$2" write_property "$1" releaseDate "$3" write_property "$1" description "$4" } function get_versionfile() { # Obtenir le chemin vers le fichier VERSION.txt dans le répertoire de # resource du bundle $1 local bundle="$(abspath "$1")" resdir if endswith "$bundle" .woa; then resdir="$bundle/Contents/Resources" elif endswith "$bundle" .framework; then resdir="$bundle/Resources" else # on a donné directement resdir resdir="$bundle" fi local default="$resdir/VERSION.txt" file for file in "$default" "$1/version.txt"; do if [ -f "$file" ]; then echo "$file" return fi done echo "$default" } function get_configfile() { # obtenir le chemin vers le fichier de configuration du répertoire de # resource du bundle # $1=bundle ou resdir (appdir/Contents/Resources ou fwkdir/Resources) local bundle="$(abspath "$1")" resdir if endswith "$bundle" .woa; then resdir="$bundle/Contents/Resources" elif endswith "$bundle" .framework; then resdir="$bundle/Resources" else # on a donné directement resdir resdir="$bundle" fi local configs array_lsfiles configs "$resdir" "*.config" if [ ${#configs[*]} -eq 0 ]; then array_lsfiles configs "$resdir" "config.xml" fi echo "${configs:-$resdir/Properties}" } function searchreplace_classpath() { # Dans les fichiers classpath de l'application $1, remplacer $2 par $3. Si # $3 est vide, la ligne est supprimée local bundle="$1" search="$2" replace="$3" scriptunx scriptwin clspth [ -n "$search" ] || return 1 search="${search//\//\\/}"; replace="${replace//\//\\/}" if [ -n "$replace" ]; then scriptunx="s/${search}/${replace}/g" else scriptunx="/${search}/d" fi search="${search//\\\//\\\\}"; replace="${replace//\\\//\\\\}" if [ -n "$replace" ]; then scriptwin="s/${search}/${replace}/g" else scriptwin="/${search}/d" fi clspth="$bundle/Contents/UNIX/UNIXClassPath.txt" nl2lf "$clspth"; sedi "$scriptunx" "$clspth" clspth="$bundle/Contents/MacOS/MacOSClassPath.txt" nl2lf "$clspth"; sedi "$scriptunx" "$clspth" clspth="$bundle/$(get_app_winclspth "$bundle")" nl2lf "$clspth"; sedi "$scriptwin" "$clspth"; nl2crlf "$clspth" } function dump_jars() { # Afficher les jars des frameworks utilisés par l'application $1 local clspth if [ "$UNAME_SYSTEM" == "Darwin" ]; then clspth="Contents/MacOS/MacOSClassPath.txt" else clspth="Contents/UNIX/UNIXClassPath.txt" fi cat "$1/$clspth" | _nl2lf | grep '\.framework' | grep -v "^#" | grep -v "APPROOT/" | grep -v "WOROOT/" | awk '{ if (match($0, /[^\/]*\.framework/) != 0) { print } }' | sort -u } function dump_frameworks() { # Afficher les frameworks utilisés par l'application $1 dump_jars "$1" | awk '{ if (match($0, /[^\/]*\.framework/) != 0) { print substr($0, RSTART, RLENGTH) } }' } function remove_framework() { # supprimer le framework $2 (nom de base) des fichiers de classpath du # bundle d'application $1 local bundle="$1" framework="$2" frameworks endswith "$framework" .framework || framework="$framework.framework" array_from_lines frameworks "$(dump_frameworks "$bundle")" if array_contains frameworks "$framework"; then searchreplace_classpath "$bundle" "^LOCALROOT/.*/$framework/" fi } function add_framework() { # s'il n'y existe pas déjà, ajouter le framework $2 (nom de base ou chemin # absolu) aux fichiers de classpath du bundle d'application $1 local bundle="$1" framework="$2" frameworks jars jar line local winclspth="$(get_app_winclspth "$bundle")" endswith "$framework" .framework || framework="$framework.framework" array_from_lines frameworks "$(dump_frameworks "$bundle")" if ! array_contains frameworks "$framework"; then if beginswith "$framework" /; then # on a donné un chemin absolu array_lsfiles jars "$framework/Resources/Java" "*.jar" if [ -z "${jars[*]}" ]; then eerror "Impossible de trouver les fichiers du framework $framework dans $WOFRAMEWORKS" return 1 else for jar in "${jars[@]}"; do echo "$jar" >>"$bundle/Contents/UNIX/UNIXClassPath.txt" echo "$jar" >>"$bundle/Contents/MacOS/MacOSClassPath.txt" echo "${jar//\//\\}" >>"$bundle/$winclspth" done fi else # on a donné juste le nom du framework array_from_lines jars "$(list_files "$WOFRAMEWORKS/$framework/Resources/Java" "*.jar")" if [ -z "${jars[*]}" ]; then eerror "Impossible de trouver les fichiers du framework $framework dans $WOFRAMEWORKS" return 1 else for jar in "${jars[@]}"; do line="LOCALROOT/Library/WebObjects/Applications/Frameworks/$framework/Resources/Java/$jar" echo "$line" >>"$bundle/Contents/UNIX/UNIXClassPath.txt" echo "$line" >>"$bundle/Contents/MacOS/MacOSClassPath.txt" echo "${line//\//\\}" >>"$bundle/$winclspth" done fi fi fi } function fix_jars_case() { # Vérifier que la casse des jars de tous les frameworks utilisés par # l'application $1 est conforme au système de fichier local bundle="$1" clspth jars jar fwkdir fwkname jarname jarnamefs if [ "$UNAME_SYSTEM" == "Darwin" ]; then clspth="Contents/MacOS/MacOSClassPath.txt" else clspth="Contents/UNIX/UNIXClassPath.txt" fi array_from_lines jars "$(dump_jars "$bundle")" for jar in "${jars[@]}"; do { endswith "$jar" .jar || endswith "$jar" .zip; } || continue if beginswith "$jar" LOCALROOT; then fwkname="${jar##*/Frameworks/}"; fwkname="${fwkname%%/*}" fwkdir="$WOFRAMEWORKS" else fwkdir="${jar%/*.framework/*}" fwkname="${jar##/*.framework/}"; fwkname="${jar:0:$((${#jar}-${#fwkname}-1))}"; fwkname="${fwkname##*/}" fi jarname="${jar##*/}" if [ ! -d "$fwkdir/$fwkname" ]; then eerror "$(basename "$bundle"): $fwkname: ce framework n'existe pas" continue fi array_from_lines jarnamefs "$(list_files "$fwkdir/$fwkname/Resources/Java" "*.jar" | grep -i "^$jarname")" if [ ${#jarnamefs[*]} -eq 0 ]; then eerror "$(basename "$bundle"): $fwkname: $jarname n'existe pas" elif [ ${#jarnamefs[*]} -gt 1 ]; then eerror "$(basename "$bundle"): $fwkname: il existe plusieurs jars $jarname" else if [ "$jarname" != "$jarnamefs" ]; then einfo "$(basename "$bundle"): $fwkname: $jarnamefs" searchreplace_classpath "$bundle" "$fwkname/Resources/Java/$jarname" "$fwkname/Resources/Java/$jarnamefs" fi fi done } function verifix_bundle() { # vérifier et corriger le bundle $1. Pour une application, on vérifie que le # script est exécutable. Pour un framework, on vérifie que le framework est # conforme au modèle des framework générés par WebObjects. local bundle="$1" if is_woappdir "$bundle"; then local script="$bundle/$(basename "$bundle" .woa)" if [ ! -x "$script" ]; then chmod +x "$script" fi elif is_wofwkdir "$bundle"; then [ -L "$bundle/Resources" ] && return local filename if [ ! -L "$bundle/Resources" ]; then rm -rf "$bundle/Versions/A/Resources" cpdir "$bundle/Resources" "$bundle/Versions/A/Resources" rm -rf "$bundle/Resources" fi if [ ! -L "$bundle/WebServerResource" ]; then rm -rf "$bundle/Versions/A/WebServerResources" cpdir "$bundle/WebServerResources" "$bundle/Versions/A/WebServerResources" rm -rf "$bundle/WebServerResources" fi local cwd="$(pwd)" cd "$bundle/Versions" if [ -e Current ]; then if [ ! -L Current -a -d Current ]; then rm -rf Current else rm -f Current fi fi ln -s A Current cd .. ln -s Versions/Current/Resources Resources ln -s Versions/Current/WebServerResources WebServerResources cd "$cwd" fi } function compute_fapps() { # Placer dans le tableau $1(=fappnames) la liste des noms de bundle # d'applications qui dépendent du framework $2 # Cette opération est faite à partir des informations sur le système de # fichier. Elle ne peut donc concerner qu'une installation locale. local -a __cf_fappnames local __cf_fwknames __cf_fwkname __cf_appnames __cf_appname __cf_fwkname="$2" [ "${__cf_fwkname%.framework}" != "$__cf_fwkname" ] || __cf_fwkname="$__cf_fwkname.framework" __cf_fwkname="$(basename "$__cf_fwkname")" array_from_lines __cf_appnames "$(list_dirs "$WOAPPLICATIONS" "*.woa")" for __cf_appname in "${__cf_appnames[@]}"; do array_from_lines __cf_fwknames "$(dump_frameworks "$WOAPPLICATIONS/$__cf_appname")" if array_contains __cf_fwknames "$__cf_fwkname"; then array_set __cf_fappnames "$__cf_appname" fi done array_copy "${1:-fappnames}" __cf_fappnames } ################################################################################ # Applications et instances WORAURL_USE_PROXY= # faut-il passer par un proxy? WORAURL_DATA= function woraurl() { # Faire une requête avec la méthode $1 sur l'url $2 avec le payload $3 (par # exemple pour la méthode POST). la réponse est disponible dans le fichier # $WORAURL_DATA, $4(=http_code) contient le code de réponse. # Retourner 0 en cas de succès, ou une valeur différente de zéro si un # erreur se produit (typiquement, 3 pour une erreur du serveur, 1 pour une # réponse applicative, comme par exemple si l'application n'existe pas) # Les codes de réponse 2xx et 417 sont des succès # Les autres codes (à priori 4xx ou 5xx) sont des erreurs # note: le code 417 est utilisé par le moniteur pour répondre "Non", par # opposition à 200 utilisé pour répondre "OUI" local _status _http_code _args [ -n "$WORAURL_DATA" ] || ac_set_tmpfile WORAURL_DATA _args=(-s -X "${1:-GET}" ${3:+-d "$3"} -w '%{http_code}' -o "$WORAURL_DATA") [ -z "$WORAURL_USE_PROXY" ] && _args=("${_args[@]}" -x "") _http_code="$(curl "${_args[@]}" "$2")" case "$_http_code" in 2*|417) _status=0;; 4*) _status=1;; 5*) _status=3;; *) _status=11;; esac set_var "${4:-http_code}" "$_http_code" return $_status } function wogeturl() { woraurl GET "$@"; } function splitins() { # Analyser le nom $1, qui peut être de forme '', 'Name.woa', # 'Name.framework', 'App' ou 'Instance-N' (où N est un nombre), et # initialiser les variables $2(=type) et $3(=name) # Si $1=="", type=all et name="" # Si $1==Name.woa, type=woa et name=Name.woa # Si $1==Name.framework, type=fwk et name=Name.framework # Si $1==App, type=app et name=App # si $1==App-N, type=ins et name=App-N if [ -z "$1" ]; then set_var "${2:-type}" all set_var "${3:-name}" elif [ "${1%.woa}" != "$1" ]; then set_var "${2:-type}" woa set_var "${3:-name}" "$1" elif [ "${1%.framework}" != "$1" ]; then set_var "${2:-type}" fwk set_var "${3:-name}" "$1" elif [[ "$1" == *-* ]]; then local __si_name __si_num __si_name="${1%-*}" __si_num="${1##*-}" if [ -z "${__si_num//[0-9]/}" ]; then set_var "${2:-type}" ins set_var "${3:-name}" "$1" else set_var "${2:-type}" app set_var "${3:-name}" "$1" fi elif [ -n "$1" ]; then set_var "${2:-type}" app set_var "${3:-name}" "$1" fi } ################################################################################ # Environnement function create_wodirs_maybe() { mkdir -p "$WOAPPLICATIONS" mkdir -p "$WOFRAMEWORKS" } function check_autostart() { # vérifier la présence du fichier $WOAUTOSTART. Si ce n'est pas le cas, le # créer avec le contenu du tableau $1 if [ ! -f "$WOAUTOSTART" -a -n "$1" ]; then array_to_lines "$1" | csort >"$WOAUTOSTART" || return 1 enote "Le fichier $(ppath "$WOAUTOSTART") a été créé avec la liste suivante: $(<"$WOAUTOSTART")" fi } function get_autostart_order() { # Initialiser le tableau $1 avec la liste donnée dans le fichier # $WOAUTOSTART array_from_lines "$1" "$(<"$WOAUTOSTART" filter_comment)" } function apply_autostart_order() { # Réordonner les valeurs $3..* selon la liste donnée dans le tableau $2, # puis placer le résultat dans le tableau $1. $2 doit être construit avec # get_autostart_order(). Si $2 n'est pas spécifié, la liste est construite # localement. # Si le tableau contient des lignes de délai @N, replacer les délais après # les applications appropriées local __aa_reverse if [ "$1" == "-r" ]; then __aa_reverse=1 shift fi local -a __aa_oapps __aa_src local __aa_dest="$1" __aa_oapp; shift local __found if [ -n "$1" ]; then array_copy __aa_oapps "$1" else get_autostart_order __aa_oapps fi shift set_array __aa_src @ "$@" array_new "$__aa_dest" for __aa_oapp in "${__aa_oapps[@]}"; do if [[ "$__aa_oapp" == @* ]]; then # Si on trouve une ligne @N, et que la précédente ligne a été # sélectionnée, alors inclure le délai aussi dans la liste des # valeurs à prendre en compte [ -n "$__aa_found" ] && array_add "$__aa_dest" "$__aa_oapp" __aa_found= elif array_contains __aa_src "$__aa_oapp"; then array_add "$__aa_dest" "$__aa_oapp" array_del __aa_src "$__aa_oapp" __aa_found=1 else __aa_found= fi done array_extend "$__aa_dest" __aa_src [ -n "$__aa_reverse" ] && array_reverse "$__aa_dest" } function __unix_woservices() { if [ -x /etc/init.d/WOServices ]; then /etc/init.d/WOServices "$@" else eerror "Ce script ne sait pas piloter wotaskd/javamonitor sur cette plateforme" return 1 fi } SERVICE_OVERRIDE_wotaskd_stop=wotaskd_stop function wotaskd_stop() { if [ "$UNAME_SYSTEM" == "Darwin" ]; then launchctl unload /System/Library/LaunchDaemons/com.apple.wotaskd.plist else __unix_woservices stop fi } SERVICE_OVERRIDE_wotaskd_start=wotaskd_start function wotaskd_start() { if [ "$UNAME_SYSTEM" == "Darwin" ]; then launchctl load /System/Library/LaunchDaemons/com.apple.wotaskd.plist else __unix_woservices start fi } SERVICE_OVERRIDE_javamonitor_stop=javamonitor_stop SERVICE_OVERRIDE_womonitor_stop=javamonitor_stop function javamonitor_stop() { if [ "$UNAME_SYSTEM" == "Darwin" ]; then launchctl unload /System/Library/LaunchDaemons/com.apple.womonitor.plist else __unix_woservices stop fi } function womonitor_stop() { javamonitor_stop "$@"; } SERVICE_OVERRIDE_javamonitor_start=javamonitor_start SERVICE_OVERRIDE_womonitor_start=javamonitor_start function javamonitor_start() { if [ "$UNAME_SYSTEM" == "Darwin" ]; then launchctl load /System/Library/LaunchDaemons/com.apple.womonitor.plist else __unix_woservices start fi } function womonitor_start() { javamonitor_start "$@"; } SERVICE_OVERRIDE_woservices_stop=woservices_stop function woservices_stop() { if [ "$UNAME_SYSTEM" == "Darwin" ]; then javamonitor_stop wotaskd_stop else __unix_woservices stop fi } SERVICE_OVERRIDE_woservices_start=woservices_start function woservices_start() { if [ "$UNAME_SYSTEM" == "Darwin" ]; then wotaskd_start javamonitor_start else __unix_woservices start fi }