| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Hessian::Tiny::Client; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
50064
|
use warnings; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
60
|
|
|
4
|
2
|
|
|
2
|
|
12
|
use strict; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
72
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
require 5.006; |
|
7
|
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
1846
|
use URI (); |
|
|
2
|
|
|
|
|
34121
|
|
|
|
2
|
|
|
|
|
54
|
|
|
9
|
2
|
|
|
2
|
|
2249
|
use IO::File (); |
|
|
2
|
|
|
|
|
26618
|
|
|
|
2
|
|
|
|
|
50
|
|
|
10
|
2
|
|
|
2
|
|
2483
|
use LWP::UserAgent (); |
|
|
2
|
|
|
|
|
178225
|
|
|
|
2
|
|
|
|
|
56
|
|
|
11
|
2
|
|
|
2
|
|
25
|
use HTTP::Headers (); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
31
|
|
|
12
|
2
|
|
|
2
|
|
9
|
use HTTP::Request (); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
28
|
|
|
13
|
2
|
|
|
2
|
|
15997
|
use File::Temp (); |
|
|
2
|
|
|
|
|
73347
|
|
|
|
2
|
|
|
|
|
65
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
2
|
|
|
2
|
|
2066
|
use Hessian::Tiny::ConvertorV1 (); |
|
|
2
|
|
|
|
|
11
|
|
|
|
2
|
|
|
|
|
60
|
|
|
16
|
2
|
|
|
2
|
|
1423
|
use Hessian::Tiny::ConvertorV2 (); |
|
|
2
|
|
|
|
|
8
|
|
|
|
2
|
|
|
|
|
3049
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Hessian::Tiny::Client - Hessian RPC Client implementation in pure Perl |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 VERSION |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
Version 0.12 |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=cut |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
our $VERSION = '0.12'; |
|
29
|
|
|
|
|
|
|
our $Error; |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
use Hessian::Tiny::Client; |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my $foo = Hessian::Tiny::Client->new( |
|
37
|
|
|
|
|
|
|
url => 'http://hessian.service.com/serviceName', |
|
38
|
|
|
|
|
|
|
version => 2, # hessian protocol version |
|
39
|
|
|
|
|
|
|
); |
|
40
|
|
|
|
|
|
|
my($stat,$res) = $foo->call('add',2,4); |
|
41
|
|
|
|
|
|
|
if($stat == 0){ # success |
|
42
|
|
|
|
|
|
|
print "2 + 4 = $res"; |
|
43
|
|
|
|
|
|
|
}else{ |
|
44
|
|
|
|
|
|
|
print "error: $Hessian::Tiny::Client::Error"; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
Hessian is a compact binary protocol for web communication in form of client/server RPC. |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
This module allows you to write Hessian clients in Perl. |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
This module supports Hessian Protocol 1.0 and 2.0 |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Perl 5.6.0 or later is required to install this modle. |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 new |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
my $foo = Hessian::Tiny::Client->new( |
|
62
|
|
|
|
|
|
|
url => 'http://hessian.service.com/serviceName', # mandatory |
|
63
|
|
|
|
|
|
|
version => 2, # default is 1 |
|
64
|
|
|
|
|
|
|
debug => 1, # add some debugging output (to STDERR) |
|
65
|
|
|
|
|
|
|
auth => [$http_user,$http_pass], # http basic auth, if needed |
|
66
|
|
|
|
|
|
|
hessian_flag => 1, # if you need strong typing in return value |
|
67
|
|
|
|
|
|
|
); |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=over |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=item 'url' |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
hessian server url, need to be a valid url, otherwise the constructor will return undef. |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item 'version' |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
hessian protocol version, 1 or 2. |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item 'debug' |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
for debugging, you probably don't need to set this flag. |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item 'auth' |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
if http server requires authentication. (passed on to LWP request) |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=item 'hessian_flag' |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
default off, that means return value are automatically converted into native perl data; |
|
90
|
|
|
|
|
|
|
if set to true, you will get Hessian::Type::* object as return. |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=back |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=cut |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub new { |
|
97
|
2
|
|
|
2
|
1
|
889
|
my($class,@params) = @_; |
|
98
|
2
|
|
|
|
|
8
|
my $self = {@params}; |
|
99
|
2
|
|
|
|
|
20
|
my $u = URI->new($self->{url}); |
|
100
|
2
|
50
|
33
|
|
|
9772
|
unless(defined $u and $u->scheme and $u->scheme =~ /^http/){ |
|
|
|
|
33
|
|
|
|
|
|
101
|
0
|
|
|
|
|
0
|
$Error = qq[Hessian url not valid: '$$self{url}']; |
|
102
|
0
|
|
|
|
|
0
|
return; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
2
|
|
50
|
|
|
247
|
$self->{version} ||= 1; #default v1.0 |
|
105
|
2
|
|
|
|
|
25
|
return bless $self, $class; |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head2 call |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# for convinience, simple types can be passed directly |
|
112
|
|
|
|
|
|
|
($stat,$res) = $foo->call('addInt',1,2); |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# or use Hessian::Type::* for precise typing |
|
115
|
|
|
|
|
|
|
($stat,$res) = $foo->call('method1', |
|
116
|
|
|
|
|
|
|
Hessian::Type::Date( Math::BigInt->new( $milli_sec ) ), |
|
117
|
|
|
|
|
|
|
Hessian::Type::Double( 3.14 ), |
|
118
|
|
|
|
|
|
|
Hessian::Type::List( length=>2, |
|
119
|
|
|
|
|
|
|
data=>[ |
|
120
|
|
|
|
|
|
|
Hessian::Type::String->new('unicode_stream'), |
|
121
|
|
|
|
|
|
|
Hessian::Type::Binary->new('bytes') |
|
122
|
|
|
|
|
|
|
] ); |
|
123
|
|
|
|
|
|
|
Hessian::Type::Map( type=>'Car', |
|
124
|
|
|
|
|
|
|
data=>{ |
|
125
|
|
|
|
|
|
|
'Make' => 'Toto', |
|
126
|
|
|
|
|
|
|
'Modle' => 'XYZ' |
|
127
|
|
|
|
|
|
|
} ); |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
); # end call |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
if($stat == 0){ |
|
132
|
|
|
|
|
|
|
# success |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
}elsif($stat == 1){ |
|
135
|
|
|
|
|
|
|
# Hessian Fault |
|
136
|
|
|
|
|
|
|
print "Exception: $res->{code}, $res->{message}"; |
|
137
|
|
|
|
|
|
|
}else{ |
|
138
|
|
|
|
|
|
|
# communication failure |
|
139
|
|
|
|
|
|
|
print "error: $res"; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=over |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=item return values: |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
B<$stat>: 0 for success, 1 for Hessian level Fault, 2 for other errors such as http communication error or parsing anomaly; |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
B<$res>: will hold the hessian call result if call was successful, or will hold error (Hessian::Fault or string) in case of unsuccessful call; |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
normally Hessian types are converted to perl data directly, if you want strong typing in return value, you can set (hessian_flag => 1) in the constructor call new(). |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=cut |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub call { |
|
155
|
183
|
|
|
183
|
1
|
450839
|
my($self,$method_name,@hessian_params) = @_; |
|
156
|
|
|
|
|
|
|
|
|
157
|
183
|
|
|
|
|
807
|
$Error = ''; # reset, probably not needed |
|
158
|
|
|
|
|
|
|
# open fh to write call |
|
159
|
183
|
|
|
|
|
1180
|
my $call_fh = File::Temp::tempfile(); |
|
160
|
183
|
50
|
|
|
|
327351
|
return 2, $self->_elog("call, open temp call file failed $!") unless defined $call_fh; |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# write call to fh |
|
163
|
183
|
50
|
|
|
|
515
|
eval{ |
|
164
|
183
|
|
|
|
|
1336
|
my $wtr = Hessian::Tiny::Type::_make_writer($call_fh); |
|
165
|
183
|
50
|
33
|
|
|
2793
|
if( $self->{version} and $self->{version} == 2 ){ |
|
166
|
0
|
|
|
|
|
0
|
Hessian::Tiny::ConvertorV2::write_call($wtr,$method_name,@hessian_params); |
|
167
|
|
|
|
|
|
|
}else{ |
|
168
|
183
|
|
|
|
|
1163
|
Hessian::Tiny::ConvertorV1::write_call($wtr,$method_name,@hessian_params); |
|
169
|
|
|
|
|
|
|
} |
|
170
|
183
|
|
|
|
|
681
|
1; |
|
171
|
|
|
|
|
|
|
}or return 2, $self->_elog("write_call: $@"); |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# write call successful, rewind & read |
|
174
|
183
|
|
|
|
|
11940
|
$call_fh->flush(); |
|
175
|
183
|
|
|
|
|
1603
|
seek $call_fh,0,0; |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# make LWP client |
|
178
|
183
|
|
|
|
|
2471
|
my $ua = LWP::UserAgent->new; |
|
179
|
183
|
|
|
|
|
71519
|
$ua->agent("Perl Hessian::Tiny::Client $$self{version}"); |
|
180
|
183
|
|
|
|
|
11105
|
my $header = HTTP::Headers->new(); |
|
181
|
|
|
|
|
|
|
|
|
182
|
183
|
0
|
33
|
|
|
3327
|
if('ARRAY' eq ref $self->{auth} and |
|
|
|
|
33
|
|
|
|
|
|
183
|
|
|
|
|
|
|
length $self->{auth}->[0] > 0 and |
|
184
|
|
|
|
|
|
|
length $self->{auth}->[1] > 0 |
|
185
|
|
|
|
|
|
|
){ |
|
186
|
0
|
|
|
|
|
0
|
$header->authorization; |
|
187
|
0
|
|
|
|
|
0
|
$header->authorization_basic($self->{auth}->[0],$self->{auth}->[1]); |
|
188
|
|
|
|
|
|
|
} |
|
189
|
183
|
|
|
|
|
504
|
my $buf = ''; |
|
190
|
183
|
|
|
|
|
1673
|
binmode $call_fh,':bytes'; |
|
191
|
|
|
|
|
|
|
my $http_request = HTTP::Request->new(POST => $self->{url}, $header,sub{ |
|
192
|
374
|
|
|
374
|
|
17589416
|
read $call_fh,$buf,255; $buf |
|
|
374
|
|
|
|
|
1882
|
|
|
193
|
183
|
|
|
|
|
3000
|
}); |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# send http request |
|
196
|
183
|
|
|
|
|
62958
|
my $reply_fh = File::Temp::tempfile(); |
|
197
|
183
|
50
|
|
|
|
212361
|
return 2, $self->_elog("call, open temp reply file failed $!") unless defined $reply_fh; |
|
198
|
183
|
|
|
|
|
6067
|
binmode $reply_fh,':bytes'; |
|
199
|
|
|
|
|
|
|
my $http_response = $ua->request($http_request, sub{ |
|
200
|
209
|
|
|
209
|
|
17139910
|
my($chunk,$res,$lwp) = @_; print $reply_fh $chunk; |
|
|
209
|
|
|
|
|
3158
|
|
|
201
|
183
|
|
|
|
|
3244
|
}); |
|
202
|
183
|
|
|
|
|
144775
|
$call_fh->close; |
|
203
|
|
|
|
|
|
|
|
|
204
|
183
|
50
|
|
|
|
305603
|
unless($http_response->is_success){ # http level failure |
|
205
|
0
|
|
|
|
|
0
|
$reply_fh->close; |
|
206
|
0
|
|
|
|
|
0
|
return 2, $self->_elog('Hessian http response unsuccessful: ', |
|
207
|
|
|
|
|
|
|
$http_response->status_line, $http_response->error_as_HTML) |
|
208
|
|
|
|
|
|
|
; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
183
|
|
|
|
|
4889
|
my($st,$re); |
|
212
|
183
|
|
|
|
|
23441
|
$reply_fh->flush(); |
|
213
|
183
|
|
|
|
|
2052
|
seek $reply_fh,0,0; |
|
214
|
183
|
50
|
|
|
|
6319
|
eval{ |
|
215
|
183
|
|
|
|
|
2458
|
($st,$re) = _read_reply( Hessian::Tiny::Type::_make_reader($reply_fh),$self->{hessian_flag}); |
|
216
|
183
|
|
|
|
|
1875
|
1; |
|
217
|
|
|
|
|
|
|
} or return 2, $self->_elog("Hessian parse reply: $@"); |
|
218
|
183
|
100
|
100
|
|
|
1301
|
$self->_elog("Fault: $re->{code}; $re->{message}") if $st && 'Hessian::Type::Fault' eq ref $re; |
|
219
|
183
|
100
|
|
|
|
677
|
$self->_elog($re) if $st == 2; |
|
220
|
183
|
|
|
|
|
166664
|
return $st,$re; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
|
|
223
|
3
|
50
|
|
3
|
|
33
|
sub _elog { my $self=shift;$Error=join'',@_;print STDERR @_,"\n" if $self->{debug}; join '',@_ } |
|
|
3
|
|
|
|
|
15
|
|
|
|
3
|
|
|
|
|
15
|
|
|
|
3
|
|
|
|
|
7
|
|
|
224
|
|
|
|
|
|
|
sub _read_reply { |
|
225
|
183
|
|
|
183
|
|
772
|
my($reader,$hessian_flag) = @_; |
|
226
|
183
|
|
|
|
|
804
|
my $buf = $reader->(3); |
|
227
|
183
|
|
|
|
|
347
|
my($or,$m,$obj); |
|
228
|
183
|
50
|
|
|
|
2394
|
if($buf =~ /^(f|r\x01\x00)/){ # 1.0 reply |
|
|
|
0
|
|
|
|
|
|
|
229
|
183
|
|
|
|
|
1784
|
$or = Hessian::Tiny::ConvertorV1::_make_object_reader($hessian_flag); |
|
230
|
183
|
100
|
|
|
|
453
|
eval{ |
|
231
|
183
|
50
|
|
|
|
971
|
if($buf =~ /^f/){ # 2.0 compatible mode return fault directly |
|
232
|
0
|
|
|
|
|
0
|
$reader->(-3); # rewind |
|
233
|
0
|
|
|
|
|
0
|
$obj = $or->($reader,0); |
|
234
|
0
|
|
|
|
|
0
|
bless $obj,'Hessian::Type::Fault'; |
|
235
|
|
|
|
|
|
|
}else{ # pure 1.0 reply |
|
236
|
183
|
|
|
|
|
300
|
do{$obj = $or->($reader)} |
|
|
183
|
|
|
|
|
717
|
|
|
237
|
|
|
|
|
|
|
while('Hessian::Type::Header' eq ref $obj); # discard headers |
|
238
|
|
|
|
|
|
|
} |
|
239
|
181
|
|
|
|
|
3066
|
1; |
|
240
|
|
|
|
|
|
|
} or return 2, $@; |
|
241
|
181
|
100
|
|
|
|
1728
|
return ('Hessian::Type::Fault' eq ref $obj ? 1 : 0), $obj; |
|
242
|
|
|
|
|
|
|
}elsif($buf =~ /^H\x02\x00/){ # 2.0 reply |
|
243
|
0
|
|
|
|
|
|
$m = $reader->(1); |
|
244
|
0
|
|
|
|
|
|
$or = Hessian::Tiny::ConvertorV2::_make_object_reader($hessian_flag); |
|
245
|
0
|
0
|
|
|
|
|
eval{ |
|
246
|
0
|
0
|
|
|
|
|
if($m eq 'R'){ |
|
|
|
0
|
|
|
|
|
|
|
247
|
0
|
|
|
|
|
|
$obj = $or->($reader); |
|
248
|
|
|
|
|
|
|
}elsif($m eq 'F'){ |
|
249
|
0
|
|
|
|
|
|
$obj = $or->($reader,0); |
|
250
|
0
|
|
|
|
|
|
bless $obj,'Hessian::Type::Fault'; |
|
251
|
|
|
|
|
|
|
}else{ # others not implemented |
|
252
|
0
|
0
|
|
|
|
|
die "response is neither H2 Reply nor H2 Fault: $m" unless $m =~ /^[RF]/; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
0
|
|
|
|
|
|
1; |
|
255
|
|
|
|
|
|
|
} or return 2, $@; |
|
256
|
0
|
0
|
|
|
|
|
return ('Hessian::Type::Fault' eq ref $obj ? 1 : 0), $obj; |
|
257
|
|
|
|
|
|
|
}else{ # anomaly |
|
258
|
0
|
|
|
|
|
|
return 2,"_read_reply: unexpected beginning($buf)"; |
|
259
|
|
|
|
|
|
|
} |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=back |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head1 HESSIAN DATA TYPES |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head2 Null |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
$foo->call('argNull', Hessian::Type::Null->new() ); |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
As return value, by default, you will get undef; |
|
271
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::Null. |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head2 True/False |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
$foo->call('argTrue', Hessian::Type::True->new() ); |
|
276
|
|
|
|
|
|
|
$foo->call('argFalse', Hessian::Type::False->new() ); |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
As return value, by default, you will get 1 (true) or undef (false); |
|
279
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::True |
|
280
|
|
|
|
|
|
|
or Hessian::Type::False as return value. |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head2 Integer |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
$foo->call('argInt', 250 ); |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
No extra typing for Integer type. |
|
287
|
|
|
|
|
|
|
Note, if the number passed in falls outside the range of signed 32-bit integer, |
|
288
|
|
|
|
|
|
|
it will be passed as a Long type parameter (64-bit) instead. |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=head2 Long |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
$foo->call('argLong', Math::BigInt->new(100000) ); # core module |
|
293
|
|
|
|
|
|
|
$foo->call('argLong', Hessian::Type::Long->new('100000') ); # same as above |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
As return value, by default, you will get string representation of the number; |
|
296
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Math::BigInt. |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=head2 Double |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
$foo->call('argDouble', -2.50 ); # pass directly, if looks like floating point number |
|
301
|
|
|
|
|
|
|
$foo->call('argDouble', Hessian::Type::Double(-2.50) ); # equivalent |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
As return value, by default, you will get the number directly; |
|
304
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::Double. |
|
305
|
|
|
|
|
|
|
Note, floating point numbers may appear slightly inaccurate, due to the binary nature of machines (not the fault of protocol itself, or Perl even). |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head2 Date |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
$foo->call('argDate', Hessian::Type::Date->new($milli_sec) ); |
|
310
|
|
|
|
|
|
|
$foo->call('argDate', DateTime->now() ); # if you have this module installed |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
As return value, by default, you will get epoch seconds; |
|
313
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::Date (milli sec inside). |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=head2 Binary/String |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
$foo->call('argBinary', Hessian::Type::Binary->new("hello world\n") ); |
|
318
|
|
|
|
|
|
|
$foo->call('argString', Hessian::Type::String->new("hello world\n") ); |
|
319
|
|
|
|
|
|
|
$foo->call('argString', Unicode::String->new("hello world\n") ); |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
As return value, by default, you will get the perl string; |
|
322
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::Binary or |
|
323
|
|
|
|
|
|
|
Hessian::Type::String object. (Binary means byte stream, while String is UTF-8) |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=head2 XML |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
$foo->call('argXML', Hessian::Type::XML->new( $xml_string ) ); |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
As return value, by default, you will get xml string; |
|
330
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::XML. |
|
331
|
|
|
|
|
|
|
Note, XML type is removed from Hessian 2.0 spec. |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head2 List |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
$foo->call('argList', [1,2,3] ); # untyped fixed length list |
|
336
|
|
|
|
|
|
|
$foo->call('argList', Hessian::Type::List->new([1,2,3]); # same as above |
|
337
|
|
|
|
|
|
|
$foo->call('argList', Hessian::Type::List->new(length=>3,data=>[1,2,3],type=>'Triplet'); |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
As return value, by default, you will get array ref; |
|
340
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::List. |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=head2 Map |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
$foo->call('argMap', {a=>1,b=>2,c=>3} ); # untyped map |
|
345
|
|
|
|
|
|
|
$foo->call('argMap', Hessian::Type::Map->new({a=>1,b=>2,c=>3} ); # same as above |
|
346
|
|
|
|
|
|
|
$foo->call('argMap', Hessian::Type::Map->new(type=>'HashTable',data=>{a=>1,b=>2,c=>3} ); # typed |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
As return value, by default, you will get hash ref (Tie::RefHash is used to allow non-string keys); |
|
349
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::Map. |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 Object |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
my $x = Hessian::Type::Object->new( |
|
354
|
|
|
|
|
|
|
type => 'my.package.LinkedList', |
|
355
|
|
|
|
|
|
|
data => {_value => 1, _rest => undef} |
|
356
|
|
|
|
|
|
|
); |
|
357
|
|
|
|
|
|
|
my $y = Hessian::Type::Object->new( |
|
358
|
|
|
|
|
|
|
type => 'my.package.LinkedList', |
|
359
|
|
|
|
|
|
|
data => {_value => 2, _rest => $x} |
|
360
|
|
|
|
|
|
|
); |
|
361
|
|
|
|
|
|
|
$foo->call('argObject',$y); |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
As return value, by default, you will get hash_ref (Tie::RefHash is used to allow non-string keys); |
|
364
|
|
|
|
|
|
|
when 'hessian_flag' is set to true, you will get Hessian::Type::Object. |
|
365
|
|
|
|
|
|
|
Note, Object is essentially a typed Map. |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=head1 AUTHOR |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Ling Du, C<< >> |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=head1 BUGS |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
|
374
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
|
375
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=head1 TODO |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Hessian::Tiny::Server, not sure if anyone will need to use the server part, except for testing maybe. |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=head1 SUPPORT |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
perldoc Hessian::Tiny::Client |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
For information on the wonderful protocol itself, take a look at: |
|
390
|
|
|
|
|
|
|
http://hessian.caucho.com/ |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=over 4 |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
L |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
L |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=item * CPAN Ratings |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
L |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=item * Search CPAN |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
L |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=back |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
Algo LLC. |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
Copyright 2010 Ling Du. |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
422
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
|
423
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=cut |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
1; # End of Hessian::Tiny::Client |