package require javatutein your tclsh or wish.
jdkProperties
This Tcl proc expands on the java::call proc to print all JDK system properties:
proc jdkProperties {} { set props [java::call System getProperties] set names [$props propertyNames] while { [$names hasMoreElements] } { set name [$names nextElement] puts "$name=[$props getProperty $name]" } }
jdkVersion
This Tcl proc prints Tcl and Java version information:
proc jdkVersion {} { global tcl_version tcl_patchLevel puts "jdk version: [java::call System getProperty "java.version"] \ Tcl Blend patch level: $::java::patchLevel" puts "tcl version: $tcl_version \ tcl patch level: $tcl_patchLevel" puts "java package: [package versions java] \ info loaded: [info loaded]" }
jdkCapture
This Tcl proc executes Tcl code, but captures any output produced into Java's standard output and writes it into the variable given by the second argument. It is a good illustration of how to capture output from Java:
proc jdkCapture {script varName} { upvar $varName output set stream [java::new java.io.ByteArrayOutputStream] set printStream [java::new \ {java.io.PrintStream java.io.OutputStream} $stream] set stdout [java::field System out] java::call System setOut $printStream set result [uplevel $script] java::call System setOut $stdout $printStream flush set output [$stream toString] return $result }Most of this code is tedious but straight-forward. What we are doing is creating a new output stream and assigning it to the out field of System. We then execute the Tcl script argument, and get anything printed to the output stream and assign it to the Tcl variable given by varName. Finally, we restore the output stream to the value it originally had, and return the result of evaluating the Tcl script.
Here is an example that illustrates the use of this procedure. What we are doing is asking the System properties object to print itself to the System output, which is then returned by our call to jdkCapture:
jdkCapture {[java::call System getProperties] \ {list java.io.PrintStream} [java::field System out]} props puts $props(This example is a little forced, since we had to find somewhere in the standard Java libraries that prints to standard output. This is more likely to be useful once you start writing your own Java code.)
jdkStackTrace
If you call Java and there is an error in the Java code, Tcl Blend doesn't directly give you a way to access the Java stack trace. Fortunately, the Java exception is referenced in the errorCode global variable, so we can get the stack trace from it. Here is a little Tcl proc that prints the Java stack trace from the most recent exception:
proc jdkStackTrace {} { global errorCode errorInfo if { [string match {JAVA*} $errorCode] } { set exception [lindex $errorCode 1] set stream [java::new java.io.ByteArrayOutputStream] set printWriter [java::new \ {java.io.PrintWriter java.io.OutputStream} $stream] $exception {printStackTrace java.io.PrintWriter} $printWriter $printWriter flush puts "[$exception getMessage]" puts " while executing" puts "[$stream toString]" puts " while executing" } puts $errorInfo }Here is a small piece of Tcl Blend code to illustrate its use:
set s [java::new {String java.lang.String} "123"] if { [catch {$s charAt 4}]} { jdkStackTrace }