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
}