# $Id: Invoker.xotcl,v 1.4 2006/09/14 06:36:02 neumann Exp $ package provide xotcl::actiweb::invoker 0.8 package require XOTcl namespace eval ::xotcl::actiweb::invoker { namespace import ::xotcl::* Class AbstractInvoker AbstractInvoker abstract instproc invokeCall {o method arguments} AbstractInvoker abstract instproc eval {obj method arguments} # # error types are: tclError, invocationError # AbstractInvoker abstract instproc callError {type msg obj arguments} Class Invoker -superclass AbstractInvoker -parameter {{place [self]}} Invoker instproc handleException {response} { if {[my isExceptionObject $response]} { set exceptionObj $response switch [$exceptionObj info class] { ::RedirectException { set obj [$exceptionObj obj] set method [$exceptionObj method] set arguments [$exceptionObj arguments] set response [my eval $obj $method $arguments] } ::ErrorException { set response [$exceptionObj set errorText] } } $exceptionObj destroy } return $response } Invoker instproc invokeCall {o s method arguments} { upvar [self callinglevel] $o obj $s status my instvar place set response "" if {[$place isExportedObj $obj]} { # if method is not given -> call default on the object if {$method eq ""} { set method default } if {[$obj isExportedProc $method]} { #puts stderr "ExportedProcs of $obj: [$obj exportedProcs]" #puts stderr "Call: $obj -- $method -- $arguments" set response [my eval $obj $method $arguments] } else { #puts stderr "ExportedProcs of $obj: [$obj exportedProcs]" set response [my callError invocationError [$place startingObj] \ "Method not found or not exported" \ "$obj $method $arguments"] set status 405 } } else { set called $obj set obj [$place startingObj] set response [my callError invocationError $obj \ "Object '$called' unknown" ""] set status 404 } return [my handleException $response] } # # tests whether "name" is an exception object or not # Invoker instproc isExceptionObject name { if {[Object isobject $name] && [$name istype Exception]} { return 1 } return 0 } # # central eval -- all remote call # are invoked through this method # Invoker instproc eval {obj method arguments} { puts stderr "[clock format [clock seconds] \ -format %Y/%m/%d@%H:%M:%S] \ Eval Call: $obj $method $arguments" if {[catch { set r [::eval $obj $method $arguments] } ei]} { set r [my callError tclError $obj $ei "$obj $method $::errorInfo"] } return $r } Invoker instproc callError {type obj msg arguments} { [my set place]::error $type $obj $msg $arguments } Class ErrorMgr ErrorMgr instproc isHtml o { if {[my isobject $o]} { if {[$o exists contentType]} { if {[$o set contentType] eq "text/html"} { return 1 } } } return 0 } ErrorMgr instproc invocationError {obj msg arguments} { my showCall set ee [ErrorException [self]::[my autoname ee]] $ee instvar errorText if {[my isHtml $obj]} { set errorText "

invocation error: $msg" if {[llength $arguments] > 0} { append errorText ":\n

object: '[lindex $arguments 0]' \n" } else { append errorText \n } if {[llength $arguments] > 1} { append errorText "

call: '[lrange $arguments 1 end]' \n" } } else { set errorText "invocation error: $msg $arguments" } return $ee } ErrorMgr instproc tclError {obj msg arguments} { set ee [ErrorException [self]::[my autoname ee]] if {[my isHtml $obj]} { $ee errorText "

tcl error: '$msg' \n

$arguments
" } else { $ee errorText "tcl error: '$msg'\n$::errorInfo" } return $ee } # # exceptions in invocation behavior # Class Exception # # Execpetion that tells the invoker to redirect the call to # parameters # Class RedirectException -superclass Exception -parameter { {obj ""} {method ""} {arguments ""} } Class ErrorException -superclass Exception -parameter { {errorText ""} } namespace export AbstractInvoker \ Invoker ErrorMgr Exception \ RedirectException ErrorException } namespace import ::xotcl::actiweb::invoker::*