line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Hessian::Client; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
706155
|
use strict; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
106
|
|
4
|
3
|
|
|
3
|
|
17
|
use warnings; |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
86
|
|
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
3521
|
use LWP::UserAgent; |
|
3
|
|
|
|
|
198835
|
|
|
3
|
|
|
|
|
109
|
|
7
|
3
|
|
|
3
|
|
31
|
use HTTP::Request; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
72
|
|
8
|
3
|
|
|
3
|
|
1512
|
use Contextual::Return; |
|
3
|
|
|
|
|
15861
|
|
|
3
|
|
|
|
|
30
|
|
9
|
3
|
|
|
3
|
|
4367
|
use Hessian::Exception; |
|
3
|
|
|
|
|
14
|
|
|
3
|
|
|
|
|
132
|
|
10
|
3
|
|
|
3
|
|
1917
|
use Hessian::Translator; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use Class::Std; |
12
|
|
|
|
|
|
|
{ |
13
|
|
|
|
|
|
|
my %service : ATTR(:name<service>); |
14
|
|
|
|
|
|
|
my %version : ATTR(:get<version> :init_arg<version>); |
15
|
|
|
|
|
|
|
my %hessian_translator : ATTR(:get<translator> :set<translator>); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub BUILD { #{{{ |
18
|
|
|
|
|
|
|
my ( $self, $id, $args ) = @_; |
19
|
|
|
|
|
|
|
my $hessian = Hessian::Translator->new( version => $args->{version} ); |
20
|
|
|
|
|
|
|
$self->set_translator($hessian); |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub AUTOMETHOD { #{{{ |
24
|
|
|
|
|
|
|
my ( $self, $id, @args ) = @_; |
25
|
|
|
|
|
|
|
my $method_name = $_; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
return sub { |
28
|
|
|
|
|
|
|
my $datastructure = { |
29
|
|
|
|
|
|
|
call => { |
30
|
|
|
|
|
|
|
method => $method_name, |
31
|
|
|
|
|
|
|
arguments => \@args |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
}, |
34
|
|
|
|
|
|
|
}; |
35
|
|
|
|
|
|
|
return $self->_call_remote($datastructure); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub _call_remote { #{{{ |
41
|
|
|
|
|
|
|
my ( $self, $datastructure ) = @_; |
42
|
|
|
|
|
|
|
my $service = $self->get_service(); |
43
|
|
|
|
|
|
|
ServiceException->throw( error => "No service defined." ) |
44
|
|
|
|
|
|
|
unless $service; |
45
|
|
|
|
|
|
|
my $request = HTTP::Request->new( 'POST', $service ); |
46
|
|
|
|
|
|
|
my $hessian = $self->get_translator(); |
47
|
|
|
|
|
|
|
$hessian->serializer(); |
48
|
|
|
|
|
|
|
my $hessian_string = $hessian->serialize_message($datastructure); |
49
|
|
|
|
|
|
|
$request->content($hessian_string); |
50
|
|
|
|
|
|
|
my $agent = LWP::UserAgent->new(); |
51
|
|
|
|
|
|
|
my $response = $agent->request($request); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
if ( $response->is_success() ) { |
54
|
|
|
|
|
|
|
my $content = $response->content(); |
55
|
|
|
|
|
|
|
$hessian->input_string($content); |
56
|
|
|
|
|
|
|
my $processed = $hessian->process_message(); |
57
|
|
|
|
|
|
|
return $processed; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
ServiceException->throw( error => "No reponse from " . $service ); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
"one, but we're not the same"; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
__END__ |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head1 NAME |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Hessian::Client - RPC via Hessian with a remote server. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head1 SYNOPSIS |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
use Hessian::Client; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
my $client = Hessian::Client->new( |
80
|
|
|
|
|
|
|
version => 1, |
81
|
|
|
|
|
|
|
service => 'http://some.hessian.service/.....' |
82
|
|
|
|
|
|
|
); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Alternatively |
85
|
|
|
|
|
|
|
my $client = Hessian::Client->new( |
86
|
|
|
|
|
|
|
version => 2, |
87
|
|
|
|
|
|
|
service => 'http://some.hessian.service/.....' |
88
|
|
|
|
|
|
|
); |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# RPC |
92
|
|
|
|
|
|
|
my $response = $hessian->remoteCall($arg1, $arg2, $arg3, ...); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head1 DESCRIPTION |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
The goal of Hessian::Client and all associated classes in this namespace is to |
97
|
|
|
|
|
|
|
provide support for communication via the Hessian protocol in Perl. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Hessian is a binary protocol optimized for communication in situations where |
100
|
|
|
|
|
|
|
it is necessary to preserve bandwidth such as in mobile web services. Due to |
101
|
|
|
|
|
|
|
the concise nature of the API, implementations of the Hessian protocol can be |
102
|
|
|
|
|
|
|
found in several languages including Java, Python, Ruby, Erlang and PHP. For some |
103
|
|
|
|
|
|
|
reason, till now there has been no implementation in Perl. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
For a more detailed introduction into the Hessian protocol, see the main |
106
|
|
|
|
|
|
|
project documentation at http://www.caucho.com/resin-3.1/doc/hessian.xtp and |
107
|
|
|
|
|
|
|
http://hessian.caucho.com/doc/hessian-ws.html. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
Hessian::Client implements basic RPC for Hessian. Although currently only |
110
|
|
|
|
|
|
|
tested with version 1, communication with version 2.0 servers should also |
111
|
|
|
|
|
|
|
work. I am currently looking for publicly available or otherwise accesible |
112
|
|
|
|
|
|
|
Hessian services for testing. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
I probably should note that although the package was submitted under the name |
116
|
|
|
|
|
|
|
L<Hessian::Client>, the real work is actually done in |
117
|
|
|
|
|
|
|
L<Hessian::Translator|Hessian::Translator> and its associated subclasses and |
118
|
|
|
|
|
|
|
roles. In fact, I will most likely change the package name to |
119
|
|
|
|
|
|
|
C<Hessian::Translator> and submit this as a separate module at |
120
|
|
|
|
|
|
|
some point in the near future. |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 INTERFACE |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=head2 new |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=over 2 |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item |
130
|
|
|
|
|
|
|
Arguments |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=over 3 |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=item |
136
|
|
|
|
|
|
|
version |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
B<C<1>> or B<C<2>> representing the respective version of Hessian the client |
139
|
|
|
|
|
|
|
should speak. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item |
143
|
|
|
|
|
|
|
service |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
A url representing the location of a Hessian server. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=back |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=back |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head2 BUILD |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Not part of the public interface. See L<Class::Std|Class::Std/"BUILD"> documentation. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head2 AUTOMETHOD |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Not part of the public interface. See L<Class::Std|Class::Std/"AUTOMETHOD"> |
158
|
|
|
|
|
|
|
documentation. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
I<Note:> Any method called on the client that is not defined in the public |
161
|
|
|
|
|
|
|
interface (so anything other than L</"new">) will be processed into a Hessian |
162
|
|
|
|
|
|
|
call and posted to the service. |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=head1 TODO |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=over 2 |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=item * |
171
|
|
|
|
|
|
|
Testing with a Hessian 2.0 service. If anyone out there would be interested in |
172
|
|
|
|
|
|
|
helping with this I would be very grateful. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item * |
176
|
|
|
|
|
|
|
Work on messaging. RPC is only part of the Hessian protocol. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=item * |
179
|
|
|
|
|
|
|
Make a POE filter for this perhaps. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=back |