#
# Script for initializing variables used elsewhere in sample Tcl scripts and procedures
# 
# Get and set an array of attributes for the specified object
#
proc getAttrs {name array args} {
    upvar $array a
    regexp {.*/([^:]*):} $name unused type
    foreach attr [$type show $name -attribute $args] {array set a $attr}
}


proc setAttrs {name array} {
    upvar $array a
    regexp {.*/([^:]*):} $name unused type
    foreach key [array names a] {append attrs "{$key {$a($key)}}"}
    $type modify $name -attribute $attrs
}


#
# Get a system property
#
proc getProperty {name} {
    global PROPERTIES
    if {! [info exists PROPERTIES]} {
	set PROPERTIES [java::call System getProperties]
    }
    $PROPERTIES getProperty $name
}


#
# Return the full path for an executable file found in java.library.path
#
proc which {name} {
    global FILE_SEPARATOR PATH_SEPARATOR
    if {! [info exists FILE_SEPARATOR]} {
	set FILE_SEPARATOR [getProperty file.separator]
    }

    set PATH [getProperty java.library.path]
    while {[string length $PATH] > 0} {
	set end [string first $PATH_SEPARATOR $PATH]
	if {$end > 0} {
	    set DIR [string range $PATH 0 [expr $end - 1]]
	} else {
	    set DIR $PATH
	}
	set file "$DIR$FILE_SEPARATOR$name"
	if [file executable $file] {return $file}

	if {$end > 0} {
	    set PATH [string range $PATH [expr $end + 1] [string length $PATH]]
	} else {
	    set PATH ""
	}
    }
}


#
# Parse command-line arguments
#
proc parseArguments {} {
    global argc argv HOSTNAME HOST_IP INET_ADDR NODE VERBOSE
    for {set i 0} {$i < $argc} {incr i} {
	if {[string compare [lindex $argv $i] "-node"] == 0} {
	    set NODE [lindex $argv [incr i]]
	} elseif {[string compare [lindex $argv $i] "-verbose"] == 0} {
	    set VERBOSE [lindex $argv [incr i]]
	}
    }
    if {! [info exists HOSTNAME]} {
	set HOSTNAME [getProperty com.ibm.CORBA.BootstrapHost]
    }
    if {! [info exists INET_ADDR]} {
	set INET_ADDR [java::call java.net.InetAddress getByName $HOSTNAME]
	set HOST_IP   [$INET_ADDR getHostAddress]
    }
    if {! [info exists NODE]} {set NODE $HOSTNAME}
    if {[string first "/" $NODE] != 0} {set NODE "/Node:$NODE/"}
}


#
# Initialize constants
#
# Note that this procedure initializes the variable COMMANDS to the names of
# all wscp commands (it relies on the fact that the commands begin
# with a capital letter).  If you create custom procedures that begin with
# a capital letter, this can create problems if you source init.tcl after
# loading the custom procedures. When naming procedures, use the
# convention of beginning the first word of the procedure with a lowercase letter
# and subsequent words with an uppercase letter.
# 
proc initConstants {} {
    global ACTIONS COMMANDS OBJECTS PORT STATUS VERBOSE
    global  EXE FILE_SEPARATOR OS_NAME PATH_SEPARATOR SH USERDIR
    global DB2_HOME IBMDEBUG_HOME WAS_HOME
    if [info exists ACTIONS]  {unset ACTIONS}
    if [info exists COMMANDS] {unset COMMANDS}
    if [info exists OBJECTS]  {unset OBJECTS}
    if [info exists STATUS]   {unset STATUS}
    set USERDIR [getProperty user.dir]

    ;# Initialize the list of wscp commands
    set COMMANDS [info commands {[A-Z]*}]

    ;# Initialize the lists of objects and actions
    set NONOBJECTS {Context DrAdmin Remote XMLConfig}
    foreach o $COMMANDS {
	if [string compare $o Help] {
	    set ACTIONS($o) [$o operations]
	    if [expr [lsearch -exact $NONOBJECTS $o] == -1] {
		lappend OBJECTS $o
	    }
	}
    }

    ;# Initialize the status constants and mapping array
    foreach s [java::info fields -static com.ibm.ejs.sm.ejscp.WscpStatus] {
	set s [string trimleft $s]
	if [string match {[A-Z]*} $s] {
	    set v [java::field com.ibm.ejs.sm.ejscp.WscpStatus $s]
	    set STATUS($s) $v
	}
    }
    set STATUS(NONE) NONE

    if {! [info exists OS_NAME]} {set OS_NAME [getProperty os.name]}
    if [string match Windows* $OS_NAME] {
	set EXE .exe; set SH .bat
    } else {
	set EXE ""; set SH ""
    }
    
    if {! [info exists VERBOSE]}  {set VERBOSE 0}
    set FILE_SEPARATOR [getProperty file.separator]
    set PATH_SEPARATOR [getProperty path.separator]
    if {! [info exists WAS_HOME]} {
	set WAS_HOME [which setupCmdLine$SH]
	regexp -nocase {(.*)[/\\]BIN} $WAS_HOME ignored WAS_HOME
    }
    if {! [info exists DB2_HOME]} {
	set DB2_HOME [which db2$EXE]
	regexp -nocase {(.*)[/\\]BIN} $DB2_HOME ignored DB2_HOME
    }
    if {! [info exists IBMDEBUG_HOME]} {
	set IBMDEBUG_HOME [which irmtdbgj$EXE]
	regexp -nocase {(.*)[/\\]BIN} $IBMDEBUG_HOME ignored IBMDEBUG_HOME
    }
    set file "${WAS_HOME}${FILE_SEPARATOR}logs${FILE_SEPARATOR}tracefile"
    if {[catch {open $file r} trace] == 0} {
	while {![eof $trace]} {
	    gets $trace line
	    if [regexp {DrAdmin available on port ([0-9,]*)} \
		    $line ignored port] {regsub -all {,} $port {} PORT}
	}
    } else {
	set PORT -1
    }
}


#
# Shows an object of the specified type (by default, the first object listed)
#
proc showObject {object {index 0}} {
    $object show [lindex [$object list] $index]
}


#
# Converts a wscp status to its corresponding string translation
#
proc statusToString {{status -1}} {
    global errorCode
    if {$status == -1 && $errorCode != "NONE"} {set status $errorCode}
    java::call com.ibm.ejs.sm.ejscp.WscpStatus statusToString $status
}


#
# Tests whether $errorCode matches the expected status value
#
proc checkStatus {expectedStatus} {
    global STATUS errorCode
    if {$errorCode == $STATUS($expectedStatus)} {return 1} {return 0}
}


#
# Performs initialization routines
#
parseArguments
initConstants