| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Copyrights 2007-2019 by [Mark Overmeer ]. |
|
2
|
|
|
|
|
|
|
# For other contributors see ChangeLog. |
|
3
|
|
|
|
|
|
|
# See the manual pages for details on the licensing terms. |
|
4
|
|
|
|
|
|
|
# Pod stripped from pm file by OODoc 2.02. |
|
5
|
|
|
|
|
|
|
# This code is part of distribution XML-Compile-SOAP. Meta-POD processed |
|
6
|
|
|
|
|
|
|
# with OODoc into POD and HTML manual-pages. See README.md |
|
7
|
|
|
|
|
|
|
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package XML::Compile::SOAP; |
|
10
|
7
|
|
|
7
|
|
1280
|
use vars '$VERSION'; |
|
|
7
|
|
|
|
|
16
|
|
|
|
7
|
|
|
|
|
380
|
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.26'; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
7
|
|
|
7
|
|
39
|
use warnings; |
|
|
7
|
|
|
|
|
14
|
|
|
|
7
|
|
|
|
|
185
|
|
|
15
|
7
|
|
|
7
|
|
30
|
use strict; |
|
|
7
|
|
|
|
|
33
|
|
|
|
7
|
|
|
|
|
161
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
7
|
|
|
7
|
|
36
|
use Log::Report 'xml-compile-soap'; |
|
|
7
|
|
|
|
|
27
|
|
|
|
7
|
|
|
|
|
51
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
7
|
|
|
7
|
|
5160
|
use XML::Compile (); |
|
|
7
|
|
|
|
|
195352
|
|
|
|
7
|
|
|
|
|
255
|
|
|
20
|
7
|
|
|
|
|
474
|
use XML::Compile::Util qw(SCHEMA2001 SCHEMA2001i pack_type |
|
21
|
7
|
|
|
7
|
|
55
|
unpack_type type_of_node); |
|
|
7
|
|
|
|
|
14
|
|
|
22
|
7
|
|
|
7
|
|
3558
|
use XML::Compile::Cache (); |
|
|
7
|
|
|
|
|
840802
|
|
|
|
7
|
|
|
|
|
243
|
|
|
23
|
7
|
|
|
7
|
|
2642
|
use XML::Compile::SOAP::Util qw/:xop10 SOAP11ENC/; |
|
|
7
|
|
|
|
|
18
|
|
|
|
7
|
|
|
|
|
1023
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
7
|
|
|
7
|
|
4057
|
use Time::HiRes qw/time/; |
|
|
7
|
|
|
|
|
10892
|
|
|
|
7
|
|
|
|
|
36
|
|
|
26
|
7
|
|
|
7
|
|
1187
|
use MIME::Base64 qw/decode_base64/; |
|
|
7
|
|
|
|
|
15
|
|
|
|
7
|
|
|
|
|
428
|
|
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# XML::Compile::WSA::Util often not installed |
|
29
|
7
|
|
|
7
|
|
40
|
use constant WSA10 => 'http://www.w3.org/2005/08/addressing'; |
|
|
7
|
|
|
|
|
9
|
|
|
|
7
|
|
|
|
|
3786
|
|
|
30
|
|
|
|
|
|
|
|
|
31
|
11
|
|
|
11
|
|
58
|
sub _xop_enabled() { exists $INC{'XML/Compile/XOP.pm'} } |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub new($@) |
|
35
|
6
|
|
|
6
|
1
|
14
|
{ my $class = shift; |
|
36
|
|
|
|
|
|
|
|
|
37
|
6
|
50
|
|
|
|
24
|
error __x"you can only instantiate sub-classes of {class}", class => $class |
|
38
|
|
|
|
|
|
|
if $class eq __PACKAGE__; |
|
39
|
|
|
|
|
|
|
|
|
40
|
6
|
|
|
|
|
52
|
(bless {}, $class)->init( {@_} ); |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub init($) |
|
44
|
6
|
|
|
6
|
0
|
20
|
{ my ($self, $args) = @_; |
|
45
|
6
|
|
50
|
|
|
131
|
$self->{XCS_mime} = $args->{media_type} || 'application/soap+xml'; |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my $schemas = $self->{XCS_schemas} = $args->{schemas} |
|
48
|
6
|
|
33
|
|
|
107
|
|| XML::Compile::Cache->new(allow_undeclared => 1 |
|
49
|
|
|
|
|
|
|
, any_element => 'ATTEMPT', any_attribute => 'ATTEMPT'); |
|
50
|
|
|
|
|
|
|
|
|
51
|
6
|
50
|
|
|
|
2685
|
UNIVERSAL::isa($schemas, 'XML::Compile::Cache') |
|
52
|
|
|
|
|
|
|
or panic "schemas must be a Cache object"; |
|
53
|
|
|
|
|
|
|
|
|
54
|
6
|
|
|
|
|
15
|
$self; |
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub _initSOAP($) |
|
58
|
6
|
|
|
6
|
|
17
|
{ my ($thing, $schemas) = @_; |
|
59
|
|
|
|
|
|
|
return $thing |
|
60
|
6
|
50
|
|
|
|
24
|
if $schemas->{did_init_SOAP}++; # ugly |
|
61
|
|
|
|
|
|
|
|
|
62
|
6
|
|
|
|
|
29
|
$schemas->addPrefixes(xsd => SCHEMA2001, xsi => SCHEMA2001i); |
|
63
|
|
|
|
|
|
|
|
|
64
|
6
|
|
|
|
|
676
|
$thing; |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
{ my (%registered, %envelope); |
|
69
|
|
|
|
|
|
|
sub register($) |
|
70
|
7
|
|
|
7
|
1
|
38
|
{ my ($class, $uri, $env, $opclass) = @_; |
|
71
|
7
|
|
|
|
|
22
|
$registered{$uri} = $class; |
|
72
|
7
|
50
|
|
|
|
56
|
$envelope{$env} = $opclass if $env; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
0
|
|
|
0
|
0
|
0
|
sub plugin($) { $registered{$_[1]} } |
|
75
|
0
|
|
|
0
|
0
|
0
|
sub fromEnvelope($) { $envelope{$_[1]} } |
|
76
|
0
|
|
|
0
|
0
|
0
|
sub registered($) { values %registered } |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
#-------------------- |
|
80
|
|
|
|
|
|
|
|
|
81
|
0
|
|
|
0
|
1
|
0
|
sub version() {panic "not implemented"} |
|
82
|
0
|
|
|
0
|
1
|
0
|
sub mediaType() {shift->{XCS_mime}} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub schemas() { |
|
86
|
7
|
|
|
7
|
|
54
|
use Carp 'cluck'; |
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
32024
|
|
|
87
|
193
|
50
|
|
193
|
1
|
6023
|
ref $_[0] or cluck; |
|
88
|
193
|
|
|
|
|
720
|
shift->{XCS_schemas}} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
#-------------------- |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub compileMessage($@) |
|
93
|
11
|
|
|
11
|
1
|
44
|
{ my ($self, $direction, %args) = @_; |
|
94
|
11
|
|
50
|
|
|
35
|
$args{style} ||= 'document'; |
|
95
|
|
|
|
|
|
|
|
|
96
|
11
|
50
|
|
|
|
106
|
$direction eq 'SENDER' ? $self->_sender(%args) |
|
|
|
100
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
: $direction eq 'RECEIVER' ? $self->_receiver(%args) |
|
98
|
|
|
|
|
|
|
: error __x"message direction is 'SENDER' or 'RECEIVER', not `{dir}'" |
|
99
|
|
|
|
|
|
|
, dir => $direction; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub messageStructure($) |
|
104
|
1
|
|
|
1
|
1
|
1697
|
{ my ($thing, $xml) = @_; |
|
105
|
1
|
50
|
|
|
|
13
|
my $env = $xml->isa('XML::LibXML::Document') ? $xml->documentElement :$xml; |
|
106
|
|
|
|
|
|
|
|
|
107
|
1
|
|
|
|
|
3
|
my (@header, @body, $wsa_action); |
|
108
|
1
|
50
|
|
|
|
5
|
if(my ($header) = $env->getChildrenByLocalName('Header')) |
|
109
|
1
|
100
|
|
|
|
47
|
{ @header = map { $_->isa('XML::LibXML::Element') ? type_of_node($_) : ()} |
|
|
3
|
|
|
|
|
48
|
|
|
110
|
|
|
|
|
|
|
$header->childNodes; |
|
111
|
|
|
|
|
|
|
|
|
112
|
1
|
50
|
|
|
|
5
|
if(my $wsa = ($header->getChildrenByTagNameNS(WSA10, 'Action'))[0]) |
|
113
|
0
|
|
|
|
|
0
|
{ $wsa_action = $wsa->textContent; |
|
114
|
0
|
|
|
|
|
0
|
for($wsa_action) { s/^\s+//; s/\s+$//; s/\s{2,}/ /g } |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
1
|
50
|
|
|
|
30
|
if(my ($body) = $env->getChildrenByLocalName('Body')) |
|
119
|
1
|
100
|
|
|
|
12
|
{ @body = map { $_->isa('XML::LibXML::Element') ? type_of_node($_) : () } |
|
|
3
|
|
|
|
|
31
|
|
|
120
|
|
|
|
|
|
|
$body->childNodes; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
1
|
|
|
|
|
4
|
+{ header => \@header |
|
124
|
|
|
|
|
|
|
, body => \@body |
|
125
|
|
|
|
|
|
|
, wsa_action => $wsa_action |
|
126
|
|
|
|
|
|
|
}; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
#------------------------------------------------ |
|
130
|
|
|
|
|
|
|
# Sender |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub _sender(@) |
|
133
|
5
|
|
|
5
|
|
30
|
{ my ($self, %args) = @_; |
|
134
|
|
|
|
|
|
|
|
|
135
|
5
|
50
|
|
|
|
21
|
error __"option 'role' only for readers" if $args{role}; |
|
136
|
5
|
50
|
|
|
|
20
|
error __"option 'roles' only for readers" if $args{roles}; |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
my $hooks = $args{hooks} # make copy of calling hook-list |
|
139
|
5
|
50
|
|
|
|
21
|
= $args{hooks} ? [ @{$args{hooks}} ] : []; |
|
|
0
|
|
|
|
|
0
|
|
|
140
|
|
|
|
|
|
|
|
|
141
|
5
|
|
|
|
|
11
|
my @mtom; |
|
142
|
5
|
100
|
|
|
|
28
|
push @$hooks, $self->_writer_xop_hook(\@mtom) |
|
143
|
|
|
|
|
|
|
if _xop_enabled; |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
my ($body, $blabels) = $args{create_body} |
|
146
|
5
|
50
|
|
|
|
73
|
? $args{create_body}->($self, %args) |
|
147
|
|
|
|
|
|
|
: $self->_writer_body(\%args); |
|
148
|
5
|
|
|
|
|
47
|
my ($faults, $flabels) = $self->_writer_faults(\%args, $args{faults}); |
|
149
|
|
|
|
|
|
|
|
|
150
|
5
|
|
|
|
|
54
|
my ($header, $hlabels) = $self->_writer_header(\%args); |
|
151
|
5
|
|
|
|
|
37
|
push @$hooks, $self->_writer_hook($self->envType('Header'), @$header); |
|
152
|
|
|
|
|
|
|
|
|
153
|
5
|
|
50
|
|
|
25
|
my $style = $args{style} || 'none'; |
|
154
|
5
|
50
|
|
|
|
21
|
if($style eq 'document') |
|
|
|
0
|
|
|
|
|
|
|
155
|
5
|
|
|
|
|
28
|
{ push @$hooks, $self->_writer_hook($self->envType('Body') |
|
156
|
|
|
|
|
|
|
, @$body, @$faults); |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
elsif($style eq 'rpc') |
|
159
|
|
|
|
|
|
|
{ my $procedure = $args{procedure} || $args{body}{procedure} |
|
160
|
0
|
0
|
0
|
|
|
0
|
or error __x"sending operation requires procedure name with RPC"; |
|
161
|
|
|
|
|
|
|
|
|
162
|
0
|
|
0
|
|
|
0
|
my $use = $args{use} || $args{body}{use} || 'literal'; |
|
163
|
0
|
|
|
|
|
0
|
my $bt = $self->envType('Body'); |
|
164
|
0
|
0
|
|
|
|
0
|
push @$hooks, $use eq 'literal' |
|
165
|
|
|
|
|
|
|
? $self->_writer_body_rpclit_hook($bt, $procedure, $body, $faults) |
|
166
|
|
|
|
|
|
|
: $self->_writer_body_rpcenc_hook($bt, $procedure, $body, $faults); |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
else |
|
169
|
0
|
|
|
|
|
0
|
{ error __x"unknown style `{style}'", style => $style; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# |
|
173
|
|
|
|
|
|
|
# Pack everything together in one procedure |
|
174
|
|
|
|
|
|
|
# |
|
175
|
|
|
|
|
|
|
|
|
176
|
5
|
|
|
|
|
20
|
my $envelope = $self->_writer($self->envType('Envelope'), %args); |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub |
|
179
|
10
|
100
|
|
10
|
|
9104
|
{ my ($values, $charset) = ref $_[0] eq 'HASH' ? @_ : ( {@_}, undef); |
|
180
|
10
|
|
|
|
|
46
|
my %copy = %$values; # do not destroy the calling hash |
|
181
|
|
|
|
|
|
|
my $doc = delete $copy{_doc} |
|
182
|
10
|
|
33
|
|
|
413
|
|| XML::LibXML::Document->new('1.0', $charset || 'UTF-8'); |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
my %data = ( |
|
185
|
|
|
|
|
|
|
Body => delete $copy{Body} || {}, |
|
186
|
|
|
|
|
|
|
Header => delete $copy{Header}, |
|
187
|
10
|
|
50
|
|
|
114
|
); |
|
188
|
|
|
|
|
|
|
|
|
189
|
10
|
|
|
|
|
37
|
foreach my $label (@$hlabels) |
|
190
|
4
|
100
|
|
|
|
11
|
{ exists $copy{$label} or next; |
|
191
|
3
|
|
33
|
|
|
18
|
$data{Header}{$label} ||= delete $copy{$label}; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
10
|
|
|
|
|
32
|
foreach my $label (@$blabels, @$flabels) |
|
195
|
20
|
100
|
|
|
|
56
|
{ exists $copy{$label} or next; |
|
196
|
8
|
|
33
|
|
|
54
|
$data{Body}{$label} ||= delete $copy{$label}; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
10
|
50
|
66
|
|
|
43
|
if(@$blabels==2 && !keys %{$data{Body}} ) # ignore 'Fault' |
|
|
7
|
50
|
|
|
|
61
|
|
|
200
|
|
|
|
|
|
|
{ # even when no params, we fill at least one body element |
|
201
|
0
|
|
|
|
|
0
|
$data{Body}{$blabels->[0]} = \%copy; |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
elsif(keys %copy) |
|
204
|
0
|
|
|
|
|
0
|
{ trace __x"available blocks: {blocks}", |
|
205
|
|
|
|
|
|
|
blocks => [ sort @$hlabels, @$blabels, @$flabels ]; |
|
206
|
0
|
|
|
|
|
0
|
error __x"call data not used: {blocks}", blocks => [keys %copy]; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
|
|
209
|
10
|
|
|
|
|
26
|
@mtom = (); # filled via hook |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
#use Data::Dumper; |
|
212
|
|
|
|
|
|
|
#warn "REPROCESSED: ", Dumper \%data; |
|
213
|
10
|
50
|
|
|
|
39
|
my $root = $envelope->($doc, \%data) |
|
214
|
|
|
|
|
|
|
or return; |
|
215
|
|
|
|
|
|
|
|
|
216
|
10
|
|
|
|
|
1343
|
$doc->setDocumentElement($root); |
|
217
|
|
|
|
|
|
|
|
|
218
|
10
|
100
|
|
|
|
135
|
return ($doc, \@mtom) |
|
219
|
|
|
|
|
|
|
if wantarray; |
|
220
|
|
|
|
|
|
|
|
|
221
|
8
|
50
|
|
|
|
35
|
@mtom == 0 |
|
222
|
|
|
|
|
|
|
or error __x"{nr} XOP objects lost in sender" |
|
223
|
|
|
|
|
|
|
, nr => scalar @mtom; |
|
224
|
8
|
|
|
|
|
37
|
$doc; |
|
225
|
5
|
|
|
|
|
30094
|
}; |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub _writer_hook($$@) |
|
229
|
10
|
|
|
10
|
|
95
|
{ my ($self, $type, @do) = @_; |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
my $code = sub |
|
232
|
13
|
|
|
13
|
|
816
|
{ my ($doc, $data, $path, $tag) = @_; |
|
233
|
13
|
50
|
|
|
|
48
|
UNIVERSAL::isa($data, 'XML::LibXML::Element') |
|
234
|
|
|
|
|
|
|
and return $data; |
|
235
|
|
|
|
|
|
|
|
|
236
|
13
|
|
|
|
|
48
|
my %data = %$data; |
|
237
|
13
|
|
|
|
|
35
|
my @h = @do; |
|
238
|
13
|
|
|
|
|
18
|
my @childs; |
|
239
|
13
|
|
|
|
|
36
|
while(@h) |
|
240
|
23
|
|
|
|
|
1002
|
{ my ($k, $c) = (shift @h, shift @h); |
|
241
|
23
|
100
|
|
|
|
74
|
if(my $v = delete $data{$k}) |
|
242
|
11
|
|
|
|
|
37
|
{ push @childs, $c->($doc, $v); |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
|
|
246
|
13
|
50
|
|
|
|
873
|
if(keys %data) |
|
247
|
0
|
|
|
|
|
0
|
{ warning __x"unused values {names}", names => [keys %data]; |
|
248
|
0
|
|
|
|
|
0
|
my @h = @do; my @keys; |
|
|
0
|
|
|
|
|
0
|
|
|
249
|
0
|
|
|
|
|
0
|
while(@h) { push @keys, shift @h; shift @h} |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
250
|
0
|
|
|
|
|
0
|
trace "expected: ". join ' ', @keys; |
|
251
|
|
|
|
|
|
|
} |
|
252
|
|
|
|
|
|
|
|
|
253
|
13
|
|
|
|
|
67
|
my $node = $doc->createElement($tag); |
|
254
|
13
|
|
|
|
|
113
|
$node->appendChild($_) for @childs; |
|
255
|
13
|
|
|
|
|
211
|
$node; |
|
256
|
10
|
|
|
|
|
73
|
}; |
|
257
|
|
|
|
|
|
|
|
|
258
|
10
|
|
|
|
|
80
|
+{ type => $type, replace => $code }; |
|
259
|
|
|
|
|
|
|
} |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub _writer_body_rpclit_hook($$$$$) |
|
262
|
0
|
|
|
0
|
|
0
|
{ my ($self, $type, $procedure, $params, $faults) = @_; |
|
263
|
0
|
|
|
|
|
0
|
my @params = @$params; |
|
264
|
0
|
|
|
|
|
0
|
my @faults = @$faults; |
|
265
|
0
|
|
|
|
|
0
|
my $schemas = $self->schemas; |
|
266
|
|
|
|
|
|
|
|
|
267
|
0
|
|
|
|
|
0
|
my $proc = $schemas->prefixed($procedure); |
|
268
|
0
|
|
|
|
|
0
|
my ($prefix) = split /\:/, $proc; |
|
269
|
0
|
|
|
|
|
0
|
my $prefdef = $schemas->prefix($prefix); |
|
270
|
0
|
|
|
|
|
0
|
my $proc_ns = $prefdef->{uri}; |
|
271
|
0
|
|
|
|
|
0
|
$prefdef->{used} = 0; |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
my $code = sub |
|
274
|
0
|
|
|
0
|
|
0
|
{ my ($doc, $data, $path, $tag) = @_; |
|
275
|
0
|
0
|
|
|
|
0
|
UNIVERSAL::isa($data, 'XML::LibXML::Element') |
|
276
|
|
|
|
|
|
|
and return $data; |
|
277
|
|
|
|
|
|
|
|
|
278
|
0
|
|
|
|
|
0
|
my %data = %$data; |
|
279
|
0
|
|
|
|
|
0
|
my @f = @faults; |
|
280
|
0
|
|
|
|
|
0
|
my (@fchilds, @pchilds); |
|
281
|
0
|
|
|
|
|
0
|
while(@f) |
|
282
|
0
|
|
|
|
|
0
|
{ my ($k, $c) = (shift @f, shift @f); |
|
283
|
0
|
|
|
|
|
0
|
my $v = delete $data{$k}; |
|
284
|
0
|
0
|
|
|
|
0
|
push @fchilds, $c->($doc, $v) if defined $v; |
|
285
|
|
|
|
|
|
|
} |
|
286
|
0
|
|
|
|
|
0
|
my @p = @params; |
|
287
|
0
|
|
|
|
|
0
|
while(@p) |
|
288
|
0
|
|
|
|
|
0
|
{ my ($k, $c) = (shift @p, shift @p); |
|
289
|
0
|
|
|
|
|
0
|
my $v = delete $data{$k}; |
|
290
|
0
|
0
|
|
|
|
0
|
push @pchilds, $c->($doc, $v) if defined $v; |
|
291
|
|
|
|
|
|
|
} |
|
292
|
0
|
0
|
|
|
|
0
|
warning __x"unused values {names}", names => [keys %data] |
|
293
|
|
|
|
|
|
|
if keys %data; |
|
294
|
|
|
|
|
|
|
|
|
295
|
0
|
|
|
|
|
0
|
my $proc = $doc->createElement($proc); |
|
296
|
0
|
|
|
|
|
0
|
$proc->setNamespace($proc_ns, $prefix, 0); |
|
297
|
0
|
|
|
|
|
0
|
$proc->setAttribute("SOAP-ENV:encodingStyle", SOAP11ENC); |
|
298
|
|
|
|
|
|
|
|
|
299
|
0
|
|
|
|
|
0
|
$proc->appendChild($_) for @pchilds; |
|
300
|
|
|
|
|
|
|
|
|
301
|
0
|
|
|
|
|
0
|
my $node = $doc->createElement($tag); |
|
302
|
0
|
|
|
|
|
0
|
$node->appendChild($proc); |
|
303
|
0
|
|
|
|
|
0
|
$node->appendChild($_) for @fchilds; |
|
304
|
0
|
|
|
|
|
0
|
$node; |
|
305
|
0
|
|
|
|
|
0
|
}; |
|
306
|
|
|
|
|
|
|
|
|
307
|
0
|
|
|
|
|
0
|
+{ type => $type, replace => $code }; |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
*_writer_body_rpcenc_hook = \&_writer_body_rpclit_hook; |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub _writer_header($) |
|
313
|
5
|
|
|
5
|
|
17
|
{ my ($self, $args) = @_; |
|
314
|
5
|
|
|
|
|
52
|
my (@rules, @hlabels); |
|
315
|
|
|
|
|
|
|
|
|
316
|
5
|
|
100
|
|
|
34
|
my $header = $args->{header} || []; |
|
317
|
5
|
|
|
|
|
21
|
my $soapenv = $self->envelopeNS; |
|
318
|
|
|
|
|
|
|
|
|
319
|
5
|
50
|
|
|
|
114
|
foreach my $h (ref $header eq 'ARRAY' ? @$header : $header) |
|
320
|
2
|
|
|
|
|
8
|
{ my $part = $h->{parts}[0]; |
|
321
|
2
|
|
|
|
|
6
|
my $label = $part->{name}; |
|
322
|
2
|
|
|
|
|
5
|
my $code = $part->{writer}; |
|
323
|
2
|
50
|
|
|
|
8
|
if($part->{element}) |
|
|
|
0
|
|
|
|
|
|
|
324
|
2
|
|
33
|
|
|
69
|
{ $code ||= $self->_writer_part_element($args, $part); |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
elsif(my $type = $part->{type}) |
|
327
|
0
|
|
0
|
|
|
0
|
{ $code ||= $self->_writer_part_type($args, $part); |
|
328
|
0
|
|
|
|
|
0
|
$label = (unpack_type $part->{name})[1]; |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
else |
|
331
|
0
|
|
|
|
|
0
|
{ error __x"header part {name} has neither `element' nor `type'" |
|
332
|
|
|
|
|
|
|
, name => $label; |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
|
|
335
|
2
|
|
|
|
|
55
|
push @rules, $label => $code; |
|
336
|
2
|
|
|
|
|
7
|
push @hlabels, $label; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
|
|
339
|
5
|
|
|
|
|
23
|
(\@rules, \@hlabels); |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
sub _writer_body($) |
|
343
|
5
|
|
|
5
|
|
17
|
{ my ($self, $args) = @_; |
|
344
|
5
|
|
|
|
|
22
|
my (@rules, @blabels); |
|
345
|
|
|
|
|
|
|
|
|
346
|
5
|
|
33
|
|
|
22
|
my $body = $args->{body} || $args->{fault}; |
|
347
|
5
|
|
100
|
|
|
24
|
my $use = $body->{use} || 'literal'; |
|
348
|
|
|
|
|
|
|
# $use eq 'literal' |
|
349
|
|
|
|
|
|
|
# or error __x"RPC encoded not supported by this version"; |
|
350
|
|
|
|
|
|
|
|
|
351
|
5
|
|
50
|
|
|
18
|
my $parts = $body->{parts} || []; |
|
352
|
5
|
|
|
|
|
9
|
my $style = $args->{style}; |
|
353
|
5
|
|
33
|
|
|
35
|
local $args->{is_rpc_enc} = $style eq 'rpc' && $use eq 'encoded'; |
|
354
|
|
|
|
|
|
|
|
|
355
|
5
|
|
|
|
|
17
|
foreach my $part (@$parts) |
|
356
|
9
|
|
|
|
|
21
|
{ my $label = $part->{name}; |
|
357
|
9
|
|
|
|
|
12
|
my $code; |
|
358
|
9
|
50
|
|
|
|
24
|
if($part->{element}) |
|
|
|
0
|
|
|
|
|
|
|
359
|
9
|
|
|
|
|
44
|
{ $code = $self->_writer_part_element($args, $part); |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
elsif(my $type = $part->{type}) |
|
362
|
0
|
|
|
|
|
0
|
{ $code = $self->_writer_part_type($args, $part); |
|
363
|
0
|
|
|
|
|
0
|
$label = (unpack_type $part->{name})[1]; |
|
364
|
|
|
|
|
|
|
} |
|
365
|
|
|
|
|
|
|
else |
|
366
|
0
|
|
|
|
|
0
|
{ error __x"body part {name} has neither `element' nor `type'" |
|
367
|
|
|
|
|
|
|
, name => $label; |
|
368
|
|
|
|
|
|
|
} |
|
369
|
|
|
|
|
|
|
|
|
370
|
9
|
|
|
|
|
122
|
push @rules, $label => $code; |
|
371
|
9
|
|
|
|
|
22
|
push @blabels, $label; |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
|
|
374
|
5
|
|
|
|
|
27
|
(\@rules, \@blabels); |
|
375
|
|
|
|
|
|
|
} |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub _writer_part_element($$) |
|
378
|
11
|
|
|
11
|
|
29
|
{ my ($self, $args, $part) = @_; |
|
379
|
11
|
|
|
|
|
24
|
my $element = $part->{element}; |
|
380
|
11
|
|
|
|
|
58
|
my $soapenv = $self->envelopeNS; |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
$part->{writer} ||= $self->_writer |
|
383
|
|
|
|
|
|
|
( $element, %$args |
|
384
|
30
|
100
|
|
30
|
|
11518
|
, include_namespaces => sub {$_[0] ne $soapenv && $_[2]} |
|
385
|
|
|
|
|
|
|
, xsi_type_everywhere => $args->{is_rpc_enc} |
|
386
|
11
|
|
66
|
|
|
114
|
); |
|
387
|
|
|
|
|
|
|
} |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
sub _writer_part_type($$) |
|
390
|
0
|
|
|
0
|
|
0
|
{ my ($self, $args, $part) = @_; |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
$args->{style} eq 'rpc' |
|
393
|
|
|
|
|
|
|
or error __x"part {name} uses `type', only for rpc not {style}" |
|
394
|
0
|
0
|
|
|
|
0
|
, name => $part->{name}, style => $args->{style}; |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
return $part->{writer} |
|
397
|
0
|
0
|
|
|
|
0
|
if $part->{writer}; |
|
398
|
|
|
|
|
|
|
|
|
399
|
0
|
|
|
|
|
0
|
my $soapenv = $self->envelopeNS; |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
$part->{writer} = $self->schemas->compileType |
|
402
|
|
|
|
|
|
|
( WRITER => $part->{type}, %$args, element => $part->{name} |
|
403
|
0
|
0
|
|
0
|
|
0
|
, include_namespaces => sub {$_[0] ne $soapenv && $_[2]} |
|
404
|
|
|
|
|
|
|
, xsi_type_everywhere => $args->{is_rpc_enc} |
|
405
|
0
|
|
|
|
|
0
|
); |
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
|
|
408
|
0
|
|
|
0
|
|
0
|
sub _writer_faults($) { ([], []) } |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub _writer_xop_hook($) |
|
411
|
1
|
|
|
1
|
|
3
|
{ my ($self, $xop_objects) = @_; |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
my $collect_objects = sub { |
|
414
|
4
|
|
|
4
|
|
252
|
my ($doc, $val, $path, $tag, $r) = @_; |
|
415
|
4
|
100
|
|
|
|
27
|
return $r->($doc, $val) |
|
416
|
|
|
|
|
|
|
unless UNIVERSAL::isa($val, 'XML::Compile::XOP::Include'); |
|
417
|
|
|
|
|
|
|
|
|
418
|
1
|
|
|
|
|
7
|
my $node = $val->xmlNode($doc, $path, $tag); |
|
419
|
1
|
|
|
|
|
14
|
push @$xop_objects, $val; |
|
420
|
1
|
|
|
|
|
51
|
$node; |
|
421
|
1
|
|
|
|
|
5
|
}; |
|
422
|
|
|
|
|
|
|
|
|
423
|
1
|
|
|
|
|
5
|
+{ extends => 'xsd:base64Binary', replace => $collect_objects }; |
|
424
|
|
|
|
|
|
|
} |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
#------------------------------------------------ |
|
427
|
|
|
|
|
|
|
# Receiver |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
sub _receiver(@) |
|
430
|
6
|
|
|
6
|
|
23
|
{ my ($self, %args) = @_; |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
error __"option 'destination' only for writers" |
|
433
|
6
|
50
|
|
|
|
27
|
if $args{destination}; |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
error __"option 'mustUnderstand' only for writers" |
|
436
|
6
|
50
|
|
|
|
22
|
if $args{understand}; |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# roles are not checked (yet) |
|
439
|
|
|
|
|
|
|
# my $roles = $args{roles} || $args{role} || 'ULTIMATE'; |
|
440
|
|
|
|
|
|
|
# my @roles = ref $roles eq 'ARRAY' ? @$roles : $roles; |
|
441
|
|
|
|
|
|
|
|
|
442
|
6
|
|
|
|
|
56
|
my $header = $self->_reader_header(\%args); |
|
443
|
|
|
|
|
|
|
|
|
444
|
6
|
|
|
|
|
13
|
my $xops; # forward backwards pass-on |
|
445
|
6
|
|
|
|
|
54
|
my $body = $self->_reader_body(\%args, \$xops); |
|
446
|
|
|
|
|
|
|
|
|
447
|
6
|
|
50
|
|
|
28
|
my $style = $args{style} || 'document'; |
|
448
|
6
|
|
50
|
|
|
39
|
my $kind = $args{kind} || 'request-response'; |
|
449
|
6
|
50
|
|
|
|
34
|
if($style eq 'rpc') |
|
|
|
50
|
|
|
|
|
|
|
450
|
0
|
|
0
|
|
|
0
|
{ my $procedure = $args{procedure} || $args{body}{procedure}; |
|
451
|
0
|
0
|
0
|
|
|
0
|
keys %{$args{body}}==0 || $procedure |
|
|
0
|
|
|
|
|
0
|
|
|
452
|
|
|
|
|
|
|
or error __x"receiving operation requires procedure name with RPC"; |
|
453
|
|
|
|
|
|
|
|
|
454
|
0
|
|
0
|
|
|
0
|
my $use = $args{use} || $args{body}{use} || 'literal'; |
|
455
|
0
|
0
|
|
|
|
0
|
$body = $use eq 'literal' |
|
456
|
|
|
|
|
|
|
? $self->_reader_body_rpclit_wrapper($procedure, $body) |
|
457
|
|
|
|
|
|
|
: $self->_reader_body_rpcenc_wrapper($procedure, $body); |
|
458
|
|
|
|
|
|
|
} |
|
459
|
|
|
|
|
|
|
elsif($style ne 'document') |
|
460
|
0
|
|
|
|
|
0
|
{ error __x"unknown style `{style}'", style => $style; |
|
461
|
|
|
|
|
|
|
} |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# faults are always possible |
|
464
|
6
|
|
|
|
|
83
|
push @$body, $self->_reader_fault_reader; |
|
465
|
|
|
|
|
|
|
|
|
466
|
6
|
50
|
|
|
|
31336
|
my @hooks = @{$self->{hooks} || []}; |
|
|
6
|
|
|
|
|
60
|
|
|
467
|
6
|
|
|
|
|
36
|
push @hooks |
|
468
|
|
|
|
|
|
|
, $self->_reader_hook($self->envType('Header'), $header) |
|
469
|
|
|
|
|
|
|
, $self->_reader_hook($self->envType('Body'), $body ); |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# |
|
472
|
|
|
|
|
|
|
# Pack everything together in one procedure |
|
473
|
|
|
|
|
|
|
# |
|
474
|
|
|
|
|
|
|
|
|
475
|
6
|
|
|
|
|
28
|
my $envelope = $self->_reader($self->envType('Envelope') |
|
476
|
|
|
|
|
|
|
, %args, hooks => \@hooks); |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
# add simplified fault information |
|
479
|
6
|
|
|
|
|
32643
|
my $faultdec = $self->_reader_faults(\%args, $args{faults}); |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
sub |
|
482
|
9
|
|
|
9
|
|
7529
|
{ (my $xml, $xops) = @_; |
|
483
|
9
|
|
|
|
|
37
|
my $data = $envelope->($xml); |
|
484
|
9
|
100
|
|
|
|
61
|
my @pairs = ( %{delete $data->{Header} || {}} |
|
485
|
9
|
50
|
|
|
|
1097
|
, %{delete $data->{Body} || {}}); |
|
|
9
|
|
|
|
|
57
|
|
|
486
|
9
|
|
|
|
|
39
|
while(@pairs) |
|
487
|
10
|
|
|
|
|
30
|
{ my $k = shift @pairs; |
|
488
|
10
|
|
|
|
|
32
|
$data->{$k} = shift @pairs; |
|
489
|
|
|
|
|
|
|
} |
|
490
|
|
|
|
|
|
|
|
|
491
|
9
|
|
|
|
|
38
|
$faultdec->($data); |
|
492
|
9
|
|
|
|
|
55
|
$data; |
|
493
|
6
|
|
|
|
|
104
|
}; |
|
494
|
|
|
|
|
|
|
} |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
sub _reader_hook($$) |
|
497
|
12
|
|
|
12
|
|
132
|
{ my ($self, $type, $do) = @_; |
|
498
|
12
|
|
|
|
|
69
|
my %trans = map +($_->[1] => [ $_->[0], $_->[2] ]), @$do; # we need copies |
|
499
|
12
|
|
|
|
|
40
|
my $envns = $self->envelopeNS; |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
my $code = sub |
|
502
|
12
|
|
|
12
|
|
4962
|
{ my ($xml, $trans, $path, $label) = @_; |
|
503
|
12
|
|
|
|
|
25
|
my %h; |
|
504
|
12
|
|
|
|
|
34
|
foreach my $child ($xml->childNodes) |
|
505
|
23
|
100
|
|
|
|
173
|
{ next unless $child->isa('XML::LibXML::Element'); |
|
506
|
10
|
|
|
|
|
38
|
my $type = type_of_node $child; |
|
507
|
10
|
100
|
|
|
|
203
|
if(my $t = $trans{$type}) |
|
508
|
9
|
|
|
|
|
28
|
{ my ($label, $code) = @$t; |
|
509
|
9
|
50
|
|
|
|
30
|
my $v = $code->($child) or next; |
|
510
|
9
|
50
|
|
|
|
1923
|
if(!defined $v) { } |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
511
|
9
|
|
|
|
|
29
|
elsif(!exists $h{$label}) { $h{$label} = $v } |
|
512
|
0
|
|
|
|
|
0
|
elsif(ref $h{$label} eq 'ARRAY') { push @{$h{$label}}, $v } |
|
|
0
|
|
|
|
|
0
|
|
|
513
|
0
|
|
|
|
|
0
|
else { $h{$label} = [ $h{$label}, $v ] } |
|
514
|
9
|
|
|
|
|
28
|
next; |
|
515
|
|
|
|
|
|
|
} |
|
516
|
|
|
|
|
|
|
else |
|
517
|
1
|
|
|
|
|
4
|
{ $h{$type} = $child; |
|
518
|
1
|
|
|
|
|
7
|
trace __x"node {type} not understood, expected are {has}", |
|
519
|
|
|
|
|
|
|
type => $type, has => [sort keys %trans]; |
|
520
|
|
|
|
|
|
|
} |
|
521
|
|
|
|
|
|
|
|
|
522
|
1
|
50
|
50
|
|
|
100
|
return ($label => $self->replyMustUnderstandFault($type)) |
|
523
|
|
|
|
|
|
|
if $child->getAttributeNS($envns, 'mustUnderstand') || 0; |
|
524
|
|
|
|
|
|
|
} |
|
525
|
11
|
|
|
|
|
57
|
($label => \%h); |
|
526
|
12
|
|
|
|
|
53
|
}; |
|
527
|
|
|
|
|
|
|
|
|
528
|
12
|
|
|
|
|
57
|
+{ type => $type |
|
529
|
|
|
|
|
|
|
, replace => $code |
|
530
|
|
|
|
|
|
|
}; |
|
531
|
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
} |
|
533
|
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
sub _reader_body_rpclit_wrapper($$) |
|
535
|
0
|
|
|
0
|
|
0
|
{ my ($self, $procedure, $body) = @_; |
|
536
|
0
|
|
|
|
|
0
|
my %trans = map +($_->[1] => [ $_->[0], $_->[2] ]), @$body; |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# this should use key_rewrite, but there is no $wsdl here |
|
539
|
|
|
|
|
|
|
# my $label = $wsdl->prefixed($procedure); |
|
540
|
0
|
|
|
|
|
0
|
my $label = (unpack_type $procedure)[1]; |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
my $code = sub |
|
543
|
0
|
0
|
|
0
|
|
0
|
{ my $xml = shift or return {}; |
|
544
|
0
|
|
|
|
|
0
|
my %h; |
|
545
|
0
|
|
|
|
|
0
|
foreach my $child ($xml->childNodes) |
|
546
|
0
|
0
|
|
|
|
0
|
{ $child->isa('XML::LibXML::Element') or next; |
|
547
|
0
|
|
|
|
|
0
|
my $type = type_of_node $child; |
|
548
|
0
|
0
|
|
|
|
0
|
if(my $t = $trans{$type}) |
|
549
|
0
|
|
|
|
|
0
|
{ $h{$t->[0]} = $t->[1]->($child) } |
|
550
|
0
|
|
|
|
|
0
|
else { $h{$type} = $child } |
|
551
|
|
|
|
|
|
|
} |
|
552
|
0
|
|
|
|
|
0
|
\%h; |
|
553
|
0
|
|
|
|
|
0
|
}; |
|
554
|
|
|
|
|
|
|
|
|
555
|
0
|
|
|
|
|
0
|
[ [ $label => $procedure => $code ] ]; |
|
556
|
|
|
|
|
|
|
} |
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
sub _reader_header($) |
|
559
|
6
|
|
|
6
|
|
21
|
{ my ($self, $args) = @_; |
|
560
|
6
|
|
100
|
|
|
64
|
my $header = $args->{header} || []; |
|
561
|
6
|
|
|
|
|
14
|
my @rules; |
|
562
|
|
|
|
|
|
|
|
|
563
|
6
|
|
|
|
|
19
|
foreach my $h (@$header) |
|
564
|
2
|
|
|
|
|
5
|
{ my $part = $h->{parts}[0]; |
|
565
|
2
|
|
|
|
|
4
|
my $label = $part->{name}; |
|
566
|
2
|
|
|
|
|
5
|
my $element = $part->{element}; |
|
567
|
2
|
|
33
|
|
|
27
|
my $code = $part->{reader} ||= $self->_reader($element, %$args); |
|
568
|
2
|
|
|
|
|
28798
|
push @rules, [$label, $element, $code]; |
|
569
|
|
|
|
|
|
|
} |
|
570
|
|
|
|
|
|
|
|
|
571
|
6
|
|
|
|
|
18
|
\@rules; |
|
572
|
|
|
|
|
|
|
} |
|
573
|
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub _reader_body($$) |
|
575
|
6
|
|
|
6
|
|
16
|
{ my ($self, $args, $refxops) = @_; |
|
576
|
6
|
|
|
|
|
14
|
my $body = $args->{body}; |
|
577
|
6
|
|
100
|
|
|
45
|
my $parts = $body->{parts} || []; |
|
578
|
6
|
50
|
|
|
|
14
|
my @hooks = @{$args->{hooks} || []}; |
|
|
6
|
|
|
|
|
32
|
|
|
579
|
6
|
100
|
|
|
|
21
|
push @hooks, $self->_reader_xop_hook($refxops) |
|
580
|
|
|
|
|
|
|
if _xop_enabled; |
|
581
|
|
|
|
|
|
|
|
|
582
|
6
|
|
|
|
|
24
|
local $args->{hooks} = \@hooks; |
|
583
|
|
|
|
|
|
|
|
|
584
|
6
|
|
|
|
|
10
|
my @rules; |
|
585
|
6
|
|
|
|
|
18
|
foreach my $part (@$parts) |
|
586
|
4
|
|
|
|
|
9
|
{ my $label = $part->{name}; |
|
587
|
|
|
|
|
|
|
|
|
588
|
4
|
|
|
|
|
8
|
my ($t, $code); |
|
589
|
4
|
50
|
|
|
|
16
|
if($part->{element}) |
|
|
|
0
|
|
|
|
|
|
|
590
|
4
|
|
|
|
|
28
|
{ ($t, $code) = $self->_reader_body_element($args, $part) } |
|
591
|
|
|
|
|
|
|
elsif($part->{type}) |
|
592
|
0
|
|
|
|
|
0
|
{ ($t, $code) = $self->_reader_body_type($args, $part) } |
|
593
|
|
|
|
|
|
|
else |
|
594
|
0
|
|
|
|
|
0
|
{ error __x"part {name} has neither element nor type specified" |
|
595
|
|
|
|
|
|
|
, name => $label; |
|
596
|
|
|
|
|
|
|
} |
|
597
|
4
|
|
|
|
|
42
|
push @rules, [ $label, $t, $code ]; |
|
598
|
|
|
|
|
|
|
} |
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
#use Data::Dumper; |
|
601
|
|
|
|
|
|
|
#warn "RULES=", Dumper \@rules, $parts; |
|
602
|
6
|
|
|
|
|
23
|
\@rules; |
|
603
|
|
|
|
|
|
|
} |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
sub _reader_body_element($$) |
|
606
|
4
|
|
|
4
|
|
11
|
{ my ($self, $args, $part) = @_; |
|
607
|
|
|
|
|
|
|
|
|
608
|
4
|
|
|
|
|
9
|
my $element = $part->{element}; |
|
609
|
4
|
|
33
|
|
|
51
|
my $code = $part->{reader} || $self->_reader($element, %$args); |
|
610
|
|
|
|
|
|
|
|
|
611
|
4
|
|
|
|
|
44308
|
($element, $code); |
|
612
|
|
|
|
|
|
|
} |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub _reader_body_type($$) |
|
615
|
0
|
|
|
0
|
|
0
|
{ my ($self, $args, $part) = @_; |
|
616
|
0
|
|
|
|
|
0
|
my $name = $part->{name}; |
|
617
|
|
|
|
|
|
|
|
|
618
|
0
|
0
|
|
|
|
0
|
$args->{style} eq 'rpc' |
|
619
|
|
|
|
|
|
|
or error __x"only rpc style messages can use 'type' as used by {part}" |
|
620
|
|
|
|
|
|
|
, part => $name; |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
return $part->{reader} |
|
623
|
0
|
0
|
|
|
|
0
|
if $part->{reader}; |
|
624
|
|
|
|
|
|
|
|
|
625
|
0
|
|
|
|
|
0
|
my $type = $part->{type}; |
|
626
|
0
|
|
|
|
|
0
|
my ($ns, $local) = unpack_type $type; |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
my $r = $part->{reader} = |
|
629
|
0
|
|
|
|
|
0
|
$self->schemas->compileType |
|
630
|
|
|
|
|
|
|
( READER => $type, %$args |
|
631
|
|
|
|
|
|
|
, element => $name # $args->{body}{procedure} |
|
632
|
|
|
|
|
|
|
); |
|
633
|
|
|
|
|
|
|
|
|
634
|
0
|
|
|
|
|
0
|
($name, $r); |
|
635
|
|
|
|
|
|
|
} |
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
sub _reader_faults($) |
|
638
|
0
|
|
|
0
|
|
0
|
{ my ($self, $args) = @_; |
|
639
|
0
|
|
|
0
|
|
0
|
sub { shift }; |
|
|
0
|
|
|
|
|
0
|
|
|
640
|
|
|
|
|
|
|
} |
|
641
|
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
sub _reader_xop_hook($) |
|
643
|
1
|
|
|
1
|
|
2
|
{ my ($self, $refxops) = @_; |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
my $xop_merge = sub |
|
646
|
4
|
|
|
4
|
|
900
|
{ my ($xml, $args, $path, $type, $r) = @_; |
|
647
|
4
|
100
|
|
|
|
15
|
if(my $incls = $xml->getElementsByTagNameNS(XOP10, 'Include')) |
|
648
|
1
|
50
|
50
|
|
|
176
|
{ my $href = $incls->shift->getAttribute('href') || '' |
|
649
|
|
|
|
|
|
|
or return ($type => $xml); |
|
650
|
|
|
|
|
|
|
|
|
651
|
1
|
|
|
|
|
38
|
$href =~ s/^cid://; |
|
652
|
1
|
50
|
|
|
|
32
|
my $xop = $$refxops->{$href} |
|
653
|
|
|
|
|
|
|
or return ($type => $xml); |
|
654
|
|
|
|
|
|
|
|
|
655
|
1
|
|
|
|
|
8
|
return ($type => $xop); |
|
656
|
|
|
|
|
|
|
} |
|
657
|
|
|
|
|
|
|
|
|
658
|
3
|
|
|
|
|
491
|
($type => decode_base64 $xml->textContent); |
|
659
|
1
|
|
|
|
|
6
|
}; |
|
660
|
|
|
|
|
|
|
|
|
661
|
1
|
|
|
|
|
17
|
+{ type => 'xsd:base64Binary', replace => $xop_merge }; |
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
|
|
664
|
12
|
|
|
12
|
|
78
|
sub _reader(@) { shift->schemas->reader(@_) } |
|
665
|
17
|
|
|
17
|
|
90
|
sub _writer(@) { shift->schemas->writer(@_) } |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
#------------------------------------------------ |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
|
|
670
|
0
|
|
|
0
|
1
|
|
sub roleURI($) { panic "not implemented" } |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
|
|
673
|
0
|
|
|
0
|
1
|
|
sub roleAbbreviation($) { panic "not implemented" } |
|
674
|
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
|
|
676
|
0
|
|
|
0
|
1
|
|
sub replyMustUnderstandFault($) { panic "not implemented" } |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
#---------------------- |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
1; |