File Coverage

blib/lib/Hessian/Translator.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Hessian::Translator;
2              
3             ## no critic
4             our $VERSION = '1.06';
5             $VERSION = eval $VERSION;
6             ## use critic
7             #
8 44     44   4208497 use Moose;
  0            
  0            
9              
10             use Module::Load;
11             use YAML;
12             use List::MoreUtils qw/any/;
13             use Config;
14             #use Smart::Comments;
15              
16             use Hessian::Exception;
17              
18             has 'is_big_endian' => ( is => 'rw', isa => 'Bool', default => 0 );
19             has 'original_position' => ( is => 'rw', isa => 'Int', default => 0 );
20             has 'class_definitions' => ( is => 'rw', default => sub { [] } );
21             has 'type_list' => ( #{{{
22             is => 'rw',
23             isa => 'ArrayRef',
24             lazy => 1,
25             default => sub { [] }
26             );
27             has 'reference_list' => ( is => 'rw', default => sub { [] } );
28             has 'input_string' => ( #{{{
29             is => 'rw',
30             isa => 'Str',
31             );
32             has 'version' => ( is => 'ro', isa => 'Int' );
33             has 'binary_mode' => ( is => 'ro', isa => 'Bool', default => 0 );
34             has 'chunked' => ( is => 'ro', isa => 'Bool', default => 0 );
35             has 'serializer' => (
36             is => 'rw',
37             isa => 'Bool',
38             );
39             has 'in_interior' => ( is => 'rw', isa => 'Bool', default => 0 );
40              
41             before 'input_string' => sub { #{{{
42             my $self = shift;
43             if ( not $self->does('Hessian::Deserializer') ) {
44             load 'Hessian::Deserializer';
45             Hessian::Deserializer->meta()->apply($self);
46             }
47             $self->version();
48             };
49              
50             sub append_input_buffer { #{{{
51             my ( $self, $hessian_string ) = @_;
52             if ( $self->{input_string} ) {
53             my $fh_pos = tell $self->input_handle();
54             my $input_string = substr $self->{input_string}, $fh_pos;
55              
56             my $entire_string = $input_string . $hessian_string;
57             $self->input_string($entire_string);
58             }
59             else {
60             $self->input_string($hessian_string);
61             }
62             }
63              
64             before 'serializer' => sub { #{{{
65             my $self = shift;
66             if ( !$self->does('Hessian::Serializer') ) {
67             load 'Hessian::Serializer';
68             Hessian::Serializer->meta()->apply($self);
69             }
70             $self->version();
71             };
72              
73             after 'version' => sub { #{{{
74             my ($self) = @_;
75             my $version = $self->{version};
76             PROCESSVERSION: {
77             last PROCESSVERSION unless $version;
78             Parameter::X->throw( error => "Version should be either 1 or 2." )
79             if $version !~ /^(?:1|2)$/;
80             last PROCESSVERSION
81             if $self->does('Hessian::Translator::V1')
82             or $self->does('Hessian::Translator::V2');
83             last PROCESSVERSION
84             if not( $self->does('Hessian::Serializer')
85             or $self->does('Hessian::Deserializer') );
86             my $version_role = 'Hessian::Translator::V' . $version;
87             load $version_role;
88             $version_role->meta()->apply($self);
89             } #PROCESSVERSION
90             };
91              
92             sub read_from_inputhandle { #{{{
93             my ( $self, $read_length ) = @_;
94             ### Reading from input handle: $read_length;
95              
96             my $input_handle = $self->input_handle();
97             binmode( $input_handle, 'bytes' );
98             my $original_pos = $self->original_position();
99             my $current_position = ( tell $input_handle ) - 1;
100             my $sub_string = $self->{input_string};
101             my $remaining_string_buffer = substr $self->{input_string},
102             $current_position;
103              
104             my $remaining_length = length $remaining_string_buffer;
105             ### remaining: $remaining_length
106             my $result;
107             if ( $read_length > $remaining_length ) {
108              
109             # Set filehandle back to the original position
110             my $message =
111             "Input buffer does not contain"
112             . " a complete message.\n$remaining_string_buffer\n"
113             . "Current position $current_position\n"
114             . "read length: $read_length\nremaining: $remaining_length\n"
115             . "string: "
116             . $self->{input_string} . ".\n";
117              
118             # print $message;
119              
120             # seek $input_handle, $original_pos, 0;
121             # Throw an exception that will be caught by the caller
122             MessageIncomplete::X->throw( error => $message );
123             }
124             else {
125             read $self->input_handle(), $result, $read_length;
126             }
127             return $result;
128              
129             }
130              
131             sub set_current_position { #{{{
132             my ( $self, $offset ) = @_;
133             my $input_handle = $self->input_handle();
134             my $current_position = ( tell $input_handle ) + $offset;
135             $self->original_position($current_position);
136             }
137              
138             sub BUILD { #{{{
139             my ( $self, $params ) = @_;
140             load 'Hessian::Translator::Composite';
141             Hessian::Translator::Composite->meta()->apply($self);
142             if ( any { defined $params->{$_} } qw/input_string input_handle/ ) {
143             load 'Hessian::Deserializer';
144             Hessian::Deserializer->meta()->apply($self);
145              
146             }
147              
148             if ( any { defined $params->{$_} } qw/service/ ) {
149             load 'Hessian::Serializer';
150             Hessian::Serializer->meta()->apply($self);
151             }
152             $self->version();
153             my $byteorder = $Config{byteorder};
154             $self->is_big_endian(1) if $byteorder =~ /4321/;
155              
156             }
157              
158             "one, but we're not the same";
159              
160             __END__
161              
162              
163             =head1 NAME
164              
165             Hessian::Translator - Base class for Hessian serialization/deserialization.
166              
167             =head1 SYNOPSIS
168              
169             my $translator = Hessian::Translator->new( version => 1 );
170              
171             my $hessian_string = "S\x00\x05hello";
172             $translator->input_string($hessian_string);
173             my $output = $translator->deserialize_message();
174              
175              
176             # Apply serialization methods to the object.
177             Hessian::Serializer->meta()->apply($translator);
178              
179             =head1 DESCRIPTION
180              
181             B<Hessian::Translator> and associated subclasses and roles provides
182             serialization/deserialization of data and Perl datastructures into Hessian
183             protocol.
184              
185             On its own, this class really only provides some of the more basic functions
186             required for Hessian processing such as the I<type list> for datatypes, the
187             I<reference list> for maps, objects and arrays; and the I<object class
188             definition list>. Integration of the respective serialization and
189             deserialization behaviours only takes place when needed. Depending on how
190             the translator is initialized and which methods are called on the object, it
191             is possibly to specialize the object for either Hessian 1.0 or Hessian 2.0
192             processing and to selectively include methods for serialization and or
193             deserialization.
194              
195              
196              
197             =head1 INTERFACE
198              
199              
200             =head2 BUILD
201              
202             Not to be called directly. Pod::Coverage complains if I don't have it in here
203             though.
204              
205              
206             =head2 new
207              
208              
209             =over 2
210              
211             =item
212             version
213              
214             Allowed values are B<1> or B<2> and correspond to the respective Hessian
215             protocol version.
216              
217              
218             =back
219              
220              
221             =head2 input_string
222              
223             =over 2
224              
225             =item
226             string
227              
228             The Hessian encoded string to be decoded. This may represent an entire
229             message or a simple scalar or datastructure. Note that the first application
230             of this method causes the L<Hessian::Deserializer> role to be applied to this
231             class.
232              
233              
234             =back
235              
236              
237             =head2 version
238              
239             Retrieves the current version for which this client was initialized. See
240             L</"new">.
241              
242             =head2 append_input_buffer
243              
244             Appends the string parameter to the filehandle.
245              
246              
247             =head2 class_definitions
248              
249             Provides access to the internal class definition list.
250              
251              
252             =head2 type_list
253              
254             Provides access to the internal type list.
255              
256             =head2 reference_list
257              
258             Provides access to the internal list of references.
259              
260              
261             =head2 serializer
262              
263             Causes the L<Hessian::Serializer|Hessian::Serializer> methods to be applied to
264             the current object.
265              
266             =head2 read_from_inputhandle
267              
268             Reads a specified number of bytes from an input stream.
269              
270             =head2 set_current_position
271              
272             Set/reset the current position in an input stream.
273              
274              
275             =head1 DEPENDENCIES
276              
277              
278              
279             =over 2
280              
281              
282             =item
283             L<Moose|Moose>
284              
285              
286              
287             =back