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 |