line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyrights 2014-2021 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-WSDL11. 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::WSDL11; |
10
|
5
|
|
|
5
|
|
1461889
|
use vars '$VERSION'; |
|
5
|
|
|
|
|
94
|
|
|
5
|
|
|
|
|
313
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.08'; |
12
|
|
|
|
|
|
|
|
13
|
5
|
|
|
5
|
|
34
|
use base 'XML::Compile::Cache'; |
|
5
|
|
|
|
|
6
|
|
|
5
|
|
|
|
|
3034
|
|
14
|
|
|
|
|
|
|
|
15
|
5
|
|
|
5
|
|
721840
|
use warnings; |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
150
|
|
16
|
5
|
|
|
5
|
|
28
|
use strict; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
119
|
|
17
|
|
|
|
|
|
|
|
18
|
5
|
|
|
5
|
|
26
|
use Log::Report 'xml-compile-soap'; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
41
|
|
19
|
|
|
|
|
|
|
|
20
|
5
|
|
|
5
|
|
1517
|
use XML::Compile (); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
109
|
|
21
|
5
|
|
|
5
|
|
30
|
use XML::Compile::Util qw/pack_type unpack_type/; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
275
|
|
22
|
5
|
|
|
5
|
|
3077
|
use XML::Compile::SOAP (); |
|
5
|
|
|
|
|
49117
|
|
|
5
|
|
|
|
|
177
|
|
23
|
5
|
|
|
5
|
|
46
|
use XML::Compile::SOAP::Util qw/:wsdl11/; |
|
5
|
|
|
|
|
17
|
|
|
5
|
|
|
|
|
658
|
|
24
|
5
|
|
|
5
|
|
2800
|
use XML::Compile::SOAP::Extension; |
|
5
|
|
|
|
|
4688
|
|
|
5
|
|
|
|
|
176
|
|
25
|
|
|
|
|
|
|
|
26
|
5
|
|
|
5
|
|
2598
|
use XML::Compile::SOAP::Operation (); |
|
5
|
|
|
|
|
10983
|
|
|
5
|
|
|
|
|
128
|
|
27
|
5
|
|
|
5
|
|
2553
|
use XML::Compile::Transport (); |
|
5
|
|
|
|
|
7566
|
|
|
5
|
|
|
|
|
120
|
|
28
|
|
|
|
|
|
|
|
29
|
5
|
|
|
5
|
|
34
|
use File::Spec (); |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
108
|
|
30
|
5
|
|
|
5
|
|
31
|
use List::Util qw/first/; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
310
|
|
31
|
5
|
|
|
5
|
|
32
|
use Scalar::Util qw/blessed/; |
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
297
|
|
32
|
5
|
|
|
5
|
|
30
|
use File::Basename qw/dirname/; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
21464
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub init($) |
36
|
5
|
|
|
5
|
0
|
8971
|
{ my ($self, $args) = @_; |
37
|
5
|
50
|
|
|
|
26
|
$args->{schemas} and panic "new(schemas) option removed in 0.78"; |
38
|
5
|
|
|
|
|
15
|
my $wsdl = delete $args->{top}; |
39
|
|
|
|
|
|
|
|
40
|
5
|
|
|
|
|
17
|
local $args->{any_element} = 'ATTEMPT'; |
41
|
5
|
|
|
|
|
14
|
local $args->{any_attribute} = 'ATTEMPT'; # not implemented |
42
|
5
|
|
|
|
|
15
|
local $args->{allow_undeclared} = 1; |
43
|
|
|
|
|
|
|
|
44
|
5
|
|
|
|
|
40
|
$self->SUPER::init($args); |
45
|
|
|
|
|
|
|
|
46
|
5
|
|
|
|
|
1871
|
$self->{index} = {}; |
47
|
|
|
|
|
|
|
|
48
|
5
|
|
|
|
|
28
|
$self->addPrefixes(wsdl => WSDL11, soap => WSDL11SOAP, http => WSDL11HTTP); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# next modules should change into an extension as well... |
51
|
|
|
|
|
|
|
$_->can('_initWSDL11') && $_->_initWSDL11($self) |
52
|
5
|
|
50
|
|
|
654
|
for XML::Compile::SOAP->registered; |
53
|
|
|
|
|
|
|
|
54
|
5
|
|
|
|
|
77
|
XML::Compile::SOAP::Extension->wsdl11Init($self, $args); |
55
|
|
|
|
|
|
|
|
56
|
5
|
|
|
|
|
61
|
$self->declare |
57
|
|
|
|
|
|
|
( READER => 'wsdl:definitions' |
58
|
|
|
|
|
|
|
, key_rewrite => 'PREFIXED(wsdl,soap,http)' |
59
|
|
|
|
|
|
|
, hook => {type => 'wsdl:tOperation', after => 'ELEMENT_ORDER'} |
60
|
|
|
|
|
|
|
); |
61
|
|
|
|
|
|
|
|
62
|
5
|
|
|
|
|
22
|
$self->{XCW_dcopts} = {}; |
63
|
5
|
|
|
|
|
16
|
$self->{XCW_server} = $args->{server_type}; |
64
|
|
|
|
|
|
|
|
65
|
5
|
|
|
|
|
670
|
my @xsds = map File::Spec->catdir(dirname(__FILE__), 'WSDL11', 'xsd', $_) |
66
|
|
|
|
|
|
|
, qw(wsdl.xsd wsdl-mime.xsd wsdl-http.xsd); |
67
|
|
|
|
|
|
|
|
68
|
5
|
|
|
|
|
42
|
$self->importDefinitions(\@xsds, element_form_default => 'qualified'); |
69
|
|
|
|
|
|
|
|
70
|
5
|
50
|
|
|
|
25086
|
$self->addWSDL($_) for ref $wsdl eq 'ARRAY' ? @$wsdl : $wsdl; |
71
|
5
|
|
|
|
|
160
|
$self; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
0
|
0
|
0
|
sub schemas(@) { panic "schemas() removed in v2.00, not needed anymore" } |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
#-------------------------- |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub compileAll(;$$) |
80
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $need, $usens) = @_; |
81
|
0
|
0
|
0
|
|
|
0
|
$self->SUPER::compileAll($need, $usens) |
82
|
|
|
|
|
|
|
if !$need || $need ne 'CALLS'; |
83
|
|
|
|
|
|
|
|
84
|
0
|
0
|
0
|
|
|
0
|
$self->compileCalls |
85
|
|
|
|
|
|
|
if !$need || $need eq 'CALLS'; |
86
|
0
|
|
|
|
|
0
|
$self; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub compileCalls(@) |
91
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, %args) = @_; |
92
|
0
|
|
|
|
|
0
|
my $long = $args{long_names}; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
my @ops = $self->operations |
95
|
|
|
|
|
|
|
( service => delete $args{service} |
96
|
|
|
|
|
|
|
, port => delete $args{port} |
97
|
|
|
|
|
|
|
, binding => delete $args{binding} |
98
|
0
|
|
|
|
|
0
|
); |
99
|
|
|
|
|
|
|
|
100
|
0
|
|
|
|
|
0
|
foreach my $op (@ops) |
101
|
0
|
0
|
|
|
|
0
|
{ my $alias = $long ? $op->longName : undef; |
102
|
0
|
|
|
|
|
0
|
$self->compileCall($op, alias => $alias, %args); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
0
|
$self; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub compileCall($@) |
110
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $oper, %opts) = @_; |
111
|
0
|
|
|
|
|
0
|
my $alias = delete $opts{alias}; |
112
|
0
|
0
|
|
|
|
0
|
my $op = blessed $oper ? $oper : $self->operation($oper, %opts); |
113
|
|
|
|
|
|
|
|
114
|
0
|
|
0
|
|
|
0
|
my $name = $alias || $op->name; |
115
|
|
|
|
|
|
|
error __x"a compiled call for {name} already exists", name => $name |
116
|
0
|
0
|
|
|
|
0
|
if $self->{XCW_ccode}{$name}; |
117
|
|
|
|
|
|
|
|
118
|
0
|
|
0
|
|
|
0
|
my $dopts = $self->{XCW_dcopts} || {}; |
119
|
0
|
|
|
|
|
0
|
my @opts = %opts; |
120
|
0
|
0
|
|
|
|
0
|
push @opts, ref $dopts eq 'ARRAY' ? @$dopts : %$dopts; |
121
|
0
|
|
|
|
|
0
|
trace "compiling call `$name'"; |
122
|
0
|
|
|
|
|
0
|
$self->{XCW_ccode}{$name} = $op->compileClient(@opts); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub call($@) |
127
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $name) = (shift, shift); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
my $codes = $self->{XCW_ccode} |
130
|
0
|
0
|
|
|
|
0
|
or error __x"you can only use call() after compileCalls()"; |
131
|
|
|
|
|
|
|
|
132
|
0
|
0
|
|
|
|
0
|
my $call = $codes->{$name} |
133
|
|
|
|
|
|
|
or error __x"operation `{name}' is not known", name => $name; |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
0
|
$call->(@_); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
#-------------------------- |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub addWSDL($%) |
142
|
6
|
|
|
6
|
1
|
24
|
{ my ($self, $data, %args) = @_; |
143
|
6
|
50
|
|
|
|
25
|
defined $data or return (); |
144
|
|
|
|
|
|
|
|
145
|
6
|
50
|
|
|
|
24
|
if(ref $data eq 'ARRAY') |
146
|
0
|
|
|
|
|
0
|
{ $self->addWSDL($_) for @$data; |
147
|
0
|
|
|
|
|
0
|
return $self; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
6
|
|
|
|
|
28
|
my ($node, %details) = $self->dataToXML($data); |
151
|
6
|
50
|
|
|
|
1947
|
defined $node or return $self; |
152
|
|
|
|
|
|
|
|
153
|
6
|
50
|
33
|
|
|
83
|
$node->localName eq 'definitions' && $node->namespaceURI eq WSDL11 |
154
|
|
|
|
|
|
|
or error __x"root element for WSDL is not 'wsdl:definitions'"; |
155
|
|
|
|
|
|
|
|
156
|
6
|
|
|
|
|
35
|
$self->importDefinitions($node, details => \%details); |
157
|
6
|
|
|
|
|
9105
|
$self->learnPrefixes($node); |
158
|
|
|
|
|
|
|
|
159
|
6
|
|
|
|
|
260
|
my $spec = $self->reader('wsdl:definitions')->($node); |
160
|
|
|
|
|
|
|
my $tns = $spec->{targetNamespace} |
161
|
6
|
50
|
|
|
|
663312
|
or error __x"WSDL sets no targetNamespace"; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# WSDL 1.1 par 2.1.1 says: WSDL def types each in own name-space |
164
|
6
|
|
|
|
|
23
|
my $index = $self->{index}; |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# silly WSDL structure |
167
|
6
|
|
50
|
|
|
29
|
my $toplevels = $spec->{gr_wsdl_anyTopLevelOptionalElement} || []; |
168
|
|
|
|
|
|
|
|
169
|
6
|
|
|
|
|
22
|
foreach my $toplevel (@$toplevels) |
170
|
33
|
|
|
|
|
97
|
{ my ($which, $def) = %$toplevel; # always only one |
171
|
33
|
100
|
|
|
|
187
|
$which =~ s/^wsdl_(service|message|binding|portType)$/$1/ |
172
|
|
|
|
|
|
|
or next; |
173
|
|
|
|
|
|
|
|
174
|
27
|
|
|
|
|
109
|
$index->{$which}{pack_type $tns, $def->{name}} = $def; |
175
|
|
|
|
|
|
|
|
176
|
27
|
100
|
|
|
|
210
|
if($which eq 'service') |
177
|
5
|
50
|
|
|
|
14
|
{ foreach my $port ( @{$def->{wsdl_port} || []} ) |
|
5
|
|
|
|
|
27
|
|
178
|
9
|
|
|
9
|
|
85
|
{ my $addr_label = first { /address$/ } keys %$port |
179
|
|
|
|
|
|
|
or error __x"no address in port {port}" |
180
|
5
|
50
|
|
|
|
53
|
, port => $port->{name}; |
181
|
5
|
|
|
|
|
28
|
my $first_addr = $port->{$addr_label}; |
182
|
5
|
50
|
|
|
|
29
|
$first_addr = $first_addr->[0] if ref $first_addr eq 'ARRAY'; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Is XML::Compile::SOAP loaded? |
185
|
5
|
50
|
|
|
|
22
|
ref $first_addr eq 'HASH' |
186
|
|
|
|
|
|
|
or error __x"wsdl namespace {ns} not loaded" |
187
|
|
|
|
|
|
|
, ns => $first_addr->namespaceURI; |
188
|
|
|
|
|
|
|
|
189
|
5
|
|
|
|
|
28
|
$index->{port}{pack_type $tns, $port->{name}} = $port; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# no service block when only one port |
195
|
6
|
50
|
|
|
|
69
|
unless($index->{service}) |
196
|
|
|
|
|
|
|
{ # only from this WSDL, cannot use collective $index |
197
|
0
|
|
0
|
|
|
0
|
my @portTypes = map $_->{wsdl_portType}||(), @$toplevels; |
198
|
0
|
0
|
|
|
|
0
|
@portTypes==1 |
199
|
|
|
|
|
|
|
or error __x"no service definition so needs 1 portType, found {nr}" |
200
|
|
|
|
|
|
|
, nr => scalar @portTypes; |
201
|
|
|
|
|
|
|
|
202
|
0
|
|
0
|
|
|
0
|
my @bindings = map $_->{wsdl_binding}||(), @$toplevels; |
203
|
0
|
0
|
|
|
|
0
|
@bindings==1 |
204
|
|
|
|
|
|
|
or error __x"no service definition so needs 1 binding, found {nr}" |
205
|
|
|
|
|
|
|
, nr => scalar @bindings; |
206
|
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
0
|
my $binding = pack_type $tns, $bindings[0]->{name}; |
208
|
0
|
|
|
|
|
0
|
my $portname = $portTypes[0]->{name}; |
209
|
0
|
|
|
|
|
0
|
my $servname = $portname; |
210
|
0
|
0
|
|
|
|
0
|
$servname =~ s/Service$|(?:Service)?Port(?:Type)?$/Service/i |
211
|
|
|
|
|
|
|
or $servname .= 'Service'; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
my $addr |
214
|
|
|
|
|
|
|
= $bindings[0]->{soap_binding} ? 'soap_address' |
215
|
0
|
0
|
|
|
|
0
|
: $bindings[0]->{soap12_binding} ? 'soap12_address' |
|
|
0
|
|
|
|
|
|
216
|
|
|
|
|
|
|
: error __x"unrecognized binding type for wsdl without service block"; |
217
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
0
|
my %port = (name => $portname, binding => $binding |
219
|
|
|
|
|
|
|
, $addr => {location => 'http://localhost'} ); |
220
|
|
|
|
|
|
|
|
221
|
0
|
|
|
|
|
0
|
$index->{service}{pack_type $tns, $servname} |
222
|
|
|
|
|
|
|
= { name => $servname, wsdl_port => [ \%port ] }; |
223
|
0
|
|
|
|
|
0
|
$index->{port}{pack_type $tns, $portname} = \%port; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
#warn "INDEX: ",Dumper $index; |
226
|
6
|
|
|
|
|
50
|
$self; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
sub namesFor($) |
231
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $class) = @_; |
232
|
0
|
0
|
|
|
|
0
|
keys %{shift->index($class) || {}}; |
|
0
|
|
|
|
|
0
|
|
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# new options, then also add them to the list in compileClient() |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub operation(@) |
239
|
9
|
|
|
9
|
1
|
88968
|
{ my $self = shift; |
240
|
9
|
100
|
|
|
|
50
|
my $name = @_ % 2 ? shift : undef; |
241
|
9
|
|
|
|
|
38
|
my %args = (name => $name, @_); |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# |
244
|
|
|
|
|
|
|
## Service structure |
245
|
|
|
|
|
|
|
# |
246
|
|
|
|
|
|
|
|
247
|
9
|
|
|
|
|
43
|
my $service = $self->findDef(service => delete $args{service}); |
248
|
|
|
|
|
|
|
|
249
|
9
|
|
|
|
|
24
|
my $port; |
250
|
9
|
50
|
|
|
|
15
|
my @ports = @{$service->{wsdl_port} || []}; |
|
9
|
|
|
|
|
41
|
|
251
|
9
|
50
|
|
9
|
|
63
|
if(my $not = first {blessed $_} @ports) |
|
9
|
|
|
|
|
48
|
|
252
|
0
|
|
|
|
|
0
|
{ error __x"not all name-spaces loaded, {ns} not parsed in port" |
253
|
|
|
|
|
|
|
, ns => $not->namespaceURI; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
9
|
|
|
|
|
63
|
my @portnames = map $_->{name}, @ports; |
257
|
9
|
100
|
|
|
|
59
|
if(my $portname = delete $args{port}) |
|
|
50
|
|
|
|
|
|
258
|
2
|
|
|
2
|
|
9
|
{ $port = first {$_->{name} eq $portname} @ports; |
|
2
|
|
|
|
|
6
|
|
259
|
2
|
50
|
|
|
|
8
|
error __x"cannot find port `{portname}', pick from {ports}" |
260
|
|
|
|
|
|
|
, portname => $portname, ports => join("\n ", '', @portnames) |
261
|
|
|
|
|
|
|
unless $port; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
elsif(@ports==1) |
264
|
7
|
|
|
|
|
19
|
{ $port = shift @ports; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
else |
267
|
0
|
|
|
|
|
0
|
{ error __x"specify port explicitly, pick from {portnames}" |
268
|
|
|
|
|
|
|
, portnames => join("\n ", '', @portnames); |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# get plugin for operation |
272
|
14
|
100
|
|
14
|
|
150
|
my $address = first { /address$/ && $port->{$_}{location}} keys %$port |
273
|
|
|
|
|
|
|
or error __x"no address provided in service {service} port {port}" |
274
|
9
|
50
|
|
|
|
60
|
, service => $service->{name}, port => $port->{name}; |
275
|
|
|
|
|
|
|
|
276
|
9
|
50
|
|
|
|
54
|
if($address =~ m/^{/) # } |
277
|
0
|
|
|
|
|
0
|
{ my ($ns) = unpack_type $address; |
278
|
|
|
|
|
|
|
|
279
|
0
|
0
|
|
|
|
0
|
warning __"Since v2.00 you have to require XML::Compile::SOAP11 explicitly" |
280
|
|
|
|
|
|
|
if $ns eq WSDL11SOAP; |
281
|
|
|
|
|
|
|
|
282
|
0
|
|
|
|
|
0
|
error __x"ports of type {ns} not supported (not loaded?)", ns => $ns; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
#use Data::Dumper; |
286
|
|
|
|
|
|
|
#warn Dumper $port, $self->prefixes; |
287
|
9
|
|
|
|
|
68
|
my ($prefix) = $address =~ m/(\w+)_address$/; |
288
|
9
|
50
|
|
|
|
31
|
$prefix |
289
|
|
|
|
|
|
|
or error __x"port address not prefixed; probably need to add a plugin XML::Compile::SOAP12"; |
290
|
|
|
|
|
|
|
|
291
|
9
|
|
|
|
|
90
|
my $opns = $self->findName("$prefix:"); |
292
|
9
|
|
|
|
|
299
|
my $protocol = XML::Compile::SOAP->plugin($opns); |
293
|
9
|
50
|
|
|
|
70
|
unless($protocol) |
294
|
0
|
0
|
|
|
|
0
|
{ my $pkg = $opns eq WSDL11SOAP ? 'SOAP11' |
|
|
0
|
|
|
|
|
|
295
|
|
|
|
|
|
|
: $opns eq WSDL11SOAP12 ? 'SOAP12' |
296
|
|
|
|
|
|
|
: undef; |
297
|
|
|
|
|
|
|
|
298
|
0
|
0
|
|
|
|
0
|
if($pkg) |
299
|
0
|
|
|
|
|
0
|
{ error __x"add 'use XML::Compile::{pkg}' to your script", pkg=>$pkg; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
else |
302
|
0
|
|
|
|
|
0
|
{ notice __x"ignoring unsupported namespace {ns}", ns => $opns; |
303
|
0
|
|
|
|
|
0
|
return; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
9
|
|
|
|
|
28
|
my $opclass = $protocol.'::Operation'; |
308
|
9
|
50
|
|
|
|
194
|
$opclass->can('_fromWSDL11') |
309
|
|
|
|
|
|
|
or error __x"WSDL11 not supported by {class}", class => $opclass; |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# |
312
|
|
|
|
|
|
|
## Binding |
313
|
|
|
|
|
|
|
# |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
my $bindtype = $port->{binding} |
316
|
|
|
|
|
|
|
or error __x"no binding defined in port '{name}'" |
317
|
9
|
50
|
|
|
|
41
|
, name => $port->{name}; |
318
|
|
|
|
|
|
|
|
319
|
9
|
|
|
|
|
28
|
my $binding = $self->findDef(binding => $bindtype); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
my $type = $binding->{type} # get portTypeType |
322
|
9
|
50
|
|
|
|
35
|
or error __x"no type defined with binding `{name}'" |
323
|
|
|
|
|
|
|
, name => $bindtype; |
324
|
|
|
|
|
|
|
|
325
|
9
|
|
|
|
|
25
|
my $portType = $self->findDef(portType => $type); |
326
|
|
|
|
|
|
|
my $types = $portType->{wsdl_operation} |
327
|
9
|
50
|
|
|
|
34
|
or error __x"no operations defined for portType `{name}'" |
328
|
|
|
|
|
|
|
, name => $type; |
329
|
|
|
|
|
|
|
|
330
|
9
|
|
|
|
|
97
|
my @port_ops = map $_->{name}, @$types; |
331
|
|
|
|
|
|
|
|
332
|
9
|
|
66
|
|
|
34
|
$name ||= delete $args{operation}; |
333
|
9
|
|
|
|
|
16
|
my $port_op; |
334
|
9
|
50
|
|
|
|
40
|
if(defined $name) |
|
|
0
|
|
|
|
|
|
335
|
9
|
|
|
10
|
|
70
|
{ $port_op = first {$_->{name} eq $name} @$types; |
|
10
|
|
|
|
|
31
|
|
336
|
9
|
100
|
|
|
|
55
|
error __x"no operation `{op}' for portType {pt}, pick from{ops}" |
337
|
|
|
|
|
|
|
, op => $name, pt => $type, ops => join("\n ", '', @port_ops) |
338
|
|
|
|
|
|
|
unless $port_op; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
elsif(@port_ops==1) |
341
|
0
|
|
|
|
|
0
|
{ $port_op = shift @$types; |
342
|
0
|
|
|
|
|
0
|
$name = $port_op->{name}; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
else |
345
|
0
|
|
|
|
|
0
|
{ error __x"multiple operations in portType `{pt}', pick from {ops}" |
346
|
|
|
|
|
|
|
, pt => $type, ops => join("\n ", '', @port_ops) |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
8
|
50
|
|
|
|
20
|
my @bindops = @{$binding->{wsdl_operation} || []}; |
|
8
|
|
|
|
|
44
|
|
350
|
8
|
|
|
9
|
|
42
|
my $bind_op = first {$_->{name} eq $name} @bindops; |
|
9
|
|
|
|
|
22
|
|
351
|
8
|
50
|
|
|
|
59
|
$bind_op |
352
|
|
|
|
|
|
|
or error __x"cannot find bind operation for {name}", name => $name; |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# This should be detected while parsing the WSDL because the order of |
355
|
|
|
|
|
|
|
# input and output is significant (and lost), but WSDL 1.1 simplifies |
356
|
|
|
|
|
|
|
# our life by saying that only 2 out-of 4 predefined types can actually |
357
|
|
|
|
|
|
|
# be used at present. |
358
|
|
|
|
|
|
|
|
359
|
8
|
|
|
|
|
16
|
my @order = map +(unpack_type $_)[1], @{$port_op->{_ELEMENT_ORDER}}; |
|
8
|
|
|
|
|
50
|
|
360
|
|
|
|
|
|
|
|
361
|
8
|
|
|
|
|
160
|
my ($first_in, $first_out); |
362
|
8
|
|
|
|
|
53
|
for(my $i = 0; $i<@order; $i++) |
363
|
16
|
100
|
66
|
|
|
75
|
{ $first_in = $i if !defined $first_in && $order[$i] eq 'input'; |
364
|
16
|
100
|
100
|
|
|
94
|
$first_out = $i if !defined $first_out && $order[$i] eq 'output'; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
8
|
50
|
|
|
|
52
|
my $kind |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
368
|
|
|
|
|
|
|
= !defined $first_in ? 'notification-operation' |
369
|
|
|
|
|
|
|
: !defined $first_out ? 'one-way' |
370
|
|
|
|
|
|
|
: $first_in < $first_out ? 'request-response' |
371
|
|
|
|
|
|
|
: 'solicit-response'; |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# |
374
|
|
|
|
|
|
|
### message components |
375
|
|
|
|
|
|
|
# |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
my $operation = $opclass->_fromWSDL11 |
378
|
|
|
|
|
|
|
( name => $name, |
379
|
|
|
|
|
|
|
, kind => $kind |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
, service => $service |
382
|
|
|
|
|
|
|
, serv_port => $port |
383
|
|
|
|
|
|
|
, binding => $binding |
384
|
|
|
|
|
|
|
, bind_op => $bind_op |
385
|
|
|
|
|
|
|
, portType => $portType |
386
|
|
|
|
|
|
|
, port_op => $port_op |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
, wsdl => $self |
389
|
|
|
|
|
|
|
, action => $args{action} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
, server_type => $args{server_type} || $self->{XCW_server} |
392
|
8
|
|
33
|
|
|
115
|
); |
393
|
|
|
|
|
|
|
|
394
|
8
|
|
|
|
|
1538
|
$operation; |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub compileClient(@) |
399
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
400
|
0
|
0
|
|
|
|
0
|
unshift @_, 'operation' if @_ % 2; |
401
|
0
|
0
|
|
|
|
0
|
my $op = $self->operation(@_) or return (); |
402
|
|
|
|
|
|
|
|
403
|
0
|
|
0
|
|
|
0
|
my $dopts = $self->{XCW_dcopts} || {}; |
404
|
0
|
0
|
|
|
|
0
|
$op->compileClient(@_, (ref $dopts eq 'ARRAY' ? @$dopts : %$dopts)); |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
#--------------------- |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub declare($$@) |
411
|
10
|
|
|
10
|
1
|
12242
|
{ my ($self, $need, $names, @opts) = @_; |
412
|
10
|
50
|
|
|
|
37
|
my $opts = @opts==1 ? shift @opts : \@opts; |
413
|
10
|
50
|
|
|
|
36
|
$opts = [ %$opts ] if ref $opts eq 'HASH'; |
414
|
|
|
|
|
|
|
|
415
|
10
|
50
|
|
|
|
73
|
$need eq 'OPERATION' |
416
|
|
|
|
|
|
|
or $self->SUPER::declare($need, $names, @opts); |
417
|
|
|
|
|
|
|
|
418
|
10
|
100
|
|
|
|
1870
|
foreach my $name (ref $names eq 'ARRAY' ? @$names : $names) |
419
|
|
|
|
|
|
|
{ # checking existence of opname is expensive here |
420
|
|
|
|
|
|
|
# and may be problematic with multiple bindings. |
421
|
35
|
|
|
|
|
77
|
$self->{XCW_dcopts}{$name} = $opts; |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
10
|
|
|
|
|
20
|
$self; |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
#-------------------------- |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub index(;$$) |
431
|
53
|
|
|
53
|
1
|
77
|
{ my $index = shift->{index}; |
432
|
53
|
50
|
|
|
|
121
|
@_ or return $index; |
433
|
|
|
|
|
|
|
|
434
|
53
|
50
|
|
|
|
131
|
my $class = $index->{ (shift) } |
435
|
|
|
|
|
|
|
or return (); |
436
|
|
|
|
|
|
|
|
437
|
53
|
50
|
|
|
|
159
|
@_ ? $class->{ (shift) } : $class; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub findDef($;$) |
442
|
53
|
|
|
53
|
1
|
9268
|
{ my ($self, $class, $name) = @_; |
443
|
53
|
50
|
|
|
|
109
|
my $group = $self->index($class) |
444
|
|
|
|
|
|
|
or error __x"no definitions for `{class}' found", class => $class; |
445
|
|
|
|
|
|
|
|
446
|
53
|
100
|
|
|
|
111
|
if(defined $name) |
447
|
41
|
100
|
|
|
|
190
|
{ return $group->{$name} if exists $group->{$name}; # QNAME |
448
|
|
|
|
|
|
|
|
449
|
3
|
50
|
|
|
|
17
|
if($name =~ m/\:/) # PREFIXED |
450
|
0
|
|
|
|
|
0
|
{ my $qname = $self->findName($name); |
451
|
0
|
0
|
|
|
|
0
|
return $group->{$qname} if exists $group->{$qname}; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
3
|
100
|
|
3
|
|
21
|
if(my $q = first { (unpack_type $_)[1] eq $name } keys %$group) |
|
3
|
|
|
|
|
14
|
|
455
|
2
|
|
|
|
|
35
|
{ return $group->{$q}; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
1
|
|
|
|
|
25
|
error __x"no definition for `{name}' as {class}, pick from:{groups}" |
459
|
|
|
|
|
|
|
, name => $name, class => $class |
460
|
|
|
|
|
|
|
, groups => join("\n ", '', sort keys %$group); |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
12
|
100
|
|
|
|
49
|
return values %$group |
464
|
|
|
|
|
|
|
if wantarray; |
465
|
|
|
|
|
|
|
|
466
|
9
|
50
|
|
|
|
58
|
return (values %$group)[0] |
467
|
|
|
|
|
|
|
if keys %$group==1; |
468
|
0
|
|
|
|
|
0
|
my @alts = map $self->prefixed($_), sort keys %$group; |
469
|
0
|
|
|
|
|
0
|
error __x"explicit selection required: pick one {class} from {alts}" |
470
|
|
|
|
|
|
|
, class => $class, alts => join("\n ", '', @alts); |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
sub operations(@) |
475
|
2
|
|
|
2
|
1
|
5336
|
{ my ($self, %args) = @_; |
476
|
2
|
50
|
|
|
|
9
|
$args{produce} and die "produce option removed in 0.81"; |
477
|
|
|
|
|
|
|
|
478
|
2
|
|
|
|
|
2
|
my @ops; |
479
|
2
|
|
|
|
|
5
|
my @services = $self->findDef('service'); |
480
|
2
|
|
|
|
|
5
|
foreach my $service (@services) |
481
|
2
|
|
|
|
|
5
|
{ my $sname = $service->{name}; |
482
|
2
|
50
|
33
|
|
|
7
|
next if $args{service} && $args{service} ne $sname; |
483
|
|
|
|
|
|
|
|
484
|
2
|
50
|
|
|
|
3
|
my @ports = @{$service->{wsdl_port} || []}; |
|
2
|
|
|
|
|
8
|
|
485
|
2
|
|
|
|
|
4
|
foreach my $port (@ports) |
486
|
|
|
|
|
|
|
{ |
487
|
2
|
50
|
33
|
|
|
5
|
next if $args{port} && $args{port} ne $port->{name}; |
488
|
|
|
|
|
|
|
my $bindtype = $port->{binding} |
489
|
|
|
|
|
|
|
or error __x"no binding defined in port '{name}'" |
490
|
2
|
50
|
|
|
|
10
|
, name => $port->{name}; |
491
|
2
|
|
|
|
|
5
|
my $binding = $self->findDef(binding => $bindtype); |
492
|
|
|
|
|
|
|
|
493
|
2
|
50
|
33
|
|
|
6
|
next if $args{binding} && $args{binding} ne $binding->{name}; |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
my $type = $binding->{type} |
496
|
2
|
50
|
|
|
|
7
|
or error __x"no type defined with binding `{name}'" |
497
|
|
|
|
|
|
|
, name => $bindtype; |
498
|
|
|
|
|
|
|
|
499
|
2
|
|
|
|
|
2
|
my %all_ops; |
500
|
2
|
50
|
|
|
|
3
|
foreach my $operation ( @{$binding->{wsdl_operation}||[]} ) |
|
2
|
|
|
|
|
7
|
|
501
|
2
|
|
|
|
|
3
|
{ my $opname = $operation->{name}; |
502
|
|
|
|
|
|
|
|
503
|
2
|
50
|
|
|
|
7
|
if(my $has = $all_ops{$opname}) |
504
|
|
|
|
|
|
|
{ error __x"operation {name} found again; choose service {has} or {also}" |
505
|
|
|
|
|
|
|
, name => $opname, has => $has->serviceName |
506
|
|
|
|
|
|
|
, also => $sname |
507
|
0
|
0
|
0
|
|
|
0
|
if @services > 1 && !$args{service}; |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
error __x"need one set of operations, pick port from {ports}" |
510
|
0
|
|
|
|
|
0
|
, ports => [ map $_->{name}, @ports ], _join => ', '; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
my $op = $all_ops{$opname} = $self->operation |
514
|
|
|
|
|
|
|
( service => $sname |
515
|
|
|
|
|
|
|
, port => $port->{name} |
516
|
|
|
|
|
|
|
, binding => $bindtype |
517
|
|
|
|
|
|
|
, operation => $opname |
518
|
|
|
|
|
|
|
, portType => $type |
519
|
|
|
|
|
|
|
, server_type => $args{server_type} |
520
|
2
|
|
|
|
|
11
|
); |
521
|
|
|
|
|
|
|
|
522
|
2
|
|
|
|
|
8
|
push @ops, $op; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
} |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
2
|
|
|
|
|
7
|
@ops; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
sub endPoint(@) |
532
|
2
|
|
|
2
|
1
|
1561
|
{ my ($self, %args) = @_; |
533
|
2
|
|
|
|
|
6
|
my $service = $self->findDef(service => delete $args{service}); |
534
|
|
|
|
|
|
|
|
535
|
2
|
|
|
|
|
3
|
my $port; |
536
|
2
|
50
|
|
|
|
3
|
my @ports = @{$service->{wsdl_port} || []}; |
|
2
|
|
|
|
|
9
|
|
537
|
2
|
|
|
|
|
9
|
my @portnames = map $_->{name}, @ports; |
538
|
2
|
50
|
|
|
|
10
|
if(my $portname = delete $args{port}) |
|
|
50
|
|
|
|
|
|
539
|
0
|
|
|
0
|
|
0
|
{ $port = first {$_->{name} eq $portname} @ports; |
|
0
|
|
|
|
|
0
|
|
540
|
0
|
0
|
|
|
|
0
|
error __x"cannot find port `{portname}', pick from {ports}" |
541
|
|
|
|
|
|
|
, portname => $portname, ports => join("\n ", '', @portnames) |
542
|
|
|
|
|
|
|
unless $port; |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
elsif(@ports==1) |
545
|
2
|
|
|
|
|
3
|
{ $port = shift @ports; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
else |
548
|
0
|
|
|
|
|
0
|
{ error __x"specify port explicitly, pick from {portnames}" |
549
|
|
|
|
|
|
|
, portnames => join("\n ", '', @portnames); |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
2
|
|
|
|
|
8
|
foreach my $k (keys %$port) |
553
|
2
|
50
|
|
|
|
29
|
{ return $port->{$k}{location} if $k =~ m/address$/; |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
|
556
|
0
|
|
|
|
|
0
|
(); |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
sub printIndex(@) |
561
|
1
|
|
|
1
|
1
|
6829
|
{ my $self = shift; |
562
|
1
|
50
|
|
|
|
5
|
my $fh = @_ % 2 ? shift : select; |
563
|
1
|
|
|
|
|
4
|
my @args = @_; |
564
|
|
|
|
|
|
|
|
565
|
1
|
|
|
|
|
2
|
my %tree; |
566
|
1
|
|
|
|
|
4
|
foreach my $op ($self->operations(@args)) |
567
|
1
|
|
|
|
|
7
|
{ my $port = $op->version.' port '.$op->portName; |
568
|
1
|
|
|
|
|
7
|
my $bind = '(binding '.$op->bindingName.')'; |
569
|
1
|
|
|
|
|
8
|
$tree{'service '.$op->serviceName}{"$port $bind"}{$op->name} = $_; |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
1
|
|
|
|
|
20
|
foreach my $service (sort keys %tree) |
573
|
1
|
|
|
|
|
13
|
{ $fh->print("$service\n"); |
574
|
1
|
|
|
|
|
11
|
foreach my $port (sort keys %{$tree{$service}}) |
|
1
|
|
|
|
|
4
|
|
575
|
1
|
|
|
|
|
5
|
{ $fh->print(" $port\n"); |
576
|
1
|
|
|
|
|
7
|
foreach my $op (sort keys %{$tree{$service}{$port}}) |
|
1
|
|
|
|
|
4
|
|
577
|
1
|
|
|
|
|
4
|
{ $fh->print(" $op\n"); |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
sub explain($$$@) |
585
|
0
|
|
|
0
|
1
|
|
{ my ($self, $opname, $format, $direction, @opts) = @_; |
586
|
0
|
0
|
|
|
|
|
my $op = $self->operation($opname, @opts) |
587
|
|
|
|
|
|
|
or error __x"explain operation {name} not found", name => $opname; |
588
|
0
|
|
|
|
|
|
$op->explain($self, $format, $direction, @opts); |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
#-------------------------------- |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
1; |