RPC-XML
view release on metacpan or search on metacpan
lib/RPC/XML/Procedure.pm view on Meta::CPAN
# namespace hierarchy.
$new_proc->{namespace} =~ s/[.]/::/g;
# Next step is to munge away any actual subroutine name so that the eval
# yields an anonymous sub. Also insert the namespace declaration.
($codetext = $new_proc->{code}) =~
s/sub\s+(?:[\w:]+)?\s*[{]/sub \{ package $new_proc->{namespace}; /;
$code = eval $codetext; ## no critic (ProhibitStringyEval)
return "$me: Error creating anonymous sub: $@" if $@;
$new_proc->{code} = $code;
# Add the file's mtime for when we check for stat-based reloading, name
# for reloading, and init the "called" counter to 0.
$new_proc->{mtime} = (stat $file)[9];
$new_proc->{file} = $file;
$new_proc->{called} = 0;
return ($new_proc, $class);
}
###############################################################################
#
# Sub Name: call
#
# Description: Encapsulates the invocation of the code block that the
# object is abstracting. Manages parameters, signature
# checking, etc.
#
# Arguments: NAME IN/OUT TYPE DESCRIPTION
# $self in ref Object of this class
# $srv in ref An object derived from the
# RPC::XML::Server class
# @params_in in list The params for the call itself
#
# Globals: None.
#
# Environment: None.
#
# Returns: Success: value
# Failure: RPC::XML::fault object
#
###############################################################################
sub call
{
my ($self, $srv, @params_in) = @_;
my (@paramtypes, @params, $signature, $resptype, $response, $name);
$name = $self->name;
# Create the param list.
# The type for the response will be derived from the matching signature
@paramtypes = map { $_->type } @params_in;
@params = map { $_->value } @params_in;
$signature = join q{ } => @paramtypes;
$resptype = $self->match_signature($signature);
# Since there must be at least one signature with a return value (even
# if the param list is empty), this tells us if the signature matches:
if (! $resptype)
{
return $srv->server_fault(
badsignature =>
"method $name has no matching signature for the argument list: " .
"[$signature]"
);
}
elsif ($resptype eq 'dateTime.iso8601')
{
$resptype = 'datetime_iso8601';
}
# Set these in case the server object is part of the param list
local $srv->{signature} = ## no critic (ProhibitLocalVars)
[ $resptype, @paramtypes ];
local $srv->{method_name} = $name; ## no critic (ProhibitLocalVars)
# For RPC::XML::Method (and derivatives), pass the server object
if ($self->isa('RPC::XML::Method'))
{
unshift @params, $srv;
}
# Now take a deep breath and call the method with the arguments
if (! eval { $response = $self->{code}->(@params); 1; })
{
# On failure, propagate user-generated RPC::XML::fault exceptions, or
# transform Perl-level error/failure into such an object
if (blessed $@ and $@->isa('RPC::XML::fault'))
{
return $@;
}
else
{
return $srv->server_fault(
execerror => "Method $name returned error: $@"
);
}
}
# Increment the 'called' key on the proc UNLESS the proc is named
# 'system.status' and has a boolean-true as the first param.
if (! (($name eq 'system.status') &&
@params_in &&
($paramtypes[0] eq 'boolean') &&
$params[0]))
{
$self->{called}++;
}
# Create a suitable return value
if (! ref $response)
{
if ($resptype eq 'scalar')
{
# Server code from the RPC::XML::Function class doesn't use
# signatures, so if they didn't encode the returned value
# themselves they're trusting smart_encode() to get it right.
$response = smart_encode($response);
}
else
{
# We checked that this was valid earlier, so no need for further
# tests here.
$response = "RPC::XML::$resptype"->new($response);
( run in 1.576 second using v1.01-cache-2.11-cpan-71847e10f99 )