File Coverage

lib/XML/Compile/SOAP/WSA.pm
Criterion Covered Total %
statement 84 91 92.3
branch 9 18 50.0
condition 6 15 40.0
subroutine 21 23 91.3
pod 7 8 87.5
total 127 155 81.9


line stmt bran cond sub pod time code
1             # Copyrights 2010-2020 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-WSA. 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::WSA;
10 3     3   760012 use vars '$VERSION';
  3         25  
  3         128  
11             $VERSION = '0.95';
12              
13 3     3   15 use base 'XML::Compile::SOAP::Extension';
  3         4  
  3         539  
14              
15 3     3   753 use warnings;
  3         5  
  3         56  
16 3     3   12 use strict;
  3         4  
  3         70  
17              
18 3     3   13 use Log::Report 'xml-compile-soap-wsa';
  3         4  
  3         12  
19              
20 3     3   1249 use XML::Compile::WSA::Util qw/WSA10MODULE WSA09 WSA10 WSDL11WSAW/;
  3         5  
  3         194  
21 3     3   18 use XML::Compile::SOAP::Util qw/WSDL11/;
  3         4  
  3         119  
22 3     3   13 use XML::Compile::Util qw/pack_type/;
  3         6  
  3         97  
23              
24 3     3   15 use File::Spec ();
  3         12  
  3         56  
25 3     3   13 use File::Basename qw/dirname/;
  3         4  
  3         2977  
26              
27             my @common_hdr_elems = qw/To From Action ReplyTo FaultTo MessageID
28             RelatesTo RetryAfter/;
29             my @wsa09_hdr_elems = (@common_hdr_elems, qw/ReplyAfter/);
30             my @wsa10_hdr_elems = (@common_hdr_elems, qw/ReferenceParameters/);
31              
32             my %versions =
33             ( '0.9' => { xsd => '20070619-wsa09.xsd', wsa => WSA09
34             , hdr => \@wsa09_hdr_elems }
35             , '1.0' => { xsd => '20080723-wsa10.xsd', wsa => WSA10
36             , hdr => \@wsa10_hdr_elems }
37             );
38              
39             my $xsddir = File::Spec->catdir((dirname dirname __FILE__), 'WSA', 'xsd');
40              
41              
42             sub init($)
43 2     2 0 276 { my ($self, $args) = @_;
44              
45 2         15 $self->SUPER::init($args);
46             my $version = $args->{version}
47 2 50       100 or error __x"explicit wsa_version required";
48 2         10 trace "initializing wsa $version";
49              
50 2 50       34 $version = '1.0' if $version eq WSA10MODULE;
51 2 50       9 $versions{$version}
52             or error __x"unknown wsa version {v}, pick from {vs}"
53             , v => $version, vs => [keys %versions];
54 2         9 $self->{version} = $version;
55 2         5 $self;
56             }
57              
58             #-----------
59              
60              
61 2     2 1 10 sub version() {shift->{version}}
62 4     4 1 18 sub wsaNS() {$versions{shift->{version}}{wsa}}
63              
64             # This is not uglier than the WSA specification does: if you do not
65             # specify these attributes cleanly in the WSDL specs, then everyone
66             # needs hacks.
67             # Documented in XML::Compile::SOAP::Operation
68              
69             sub XML::Compile::SOAP::Operation::wsaAction($)
70 4     4 1 1321 { my ($self, $dir) = @_;
71 4 100       40 $dir eq 'INPUT' ? $self->{wsa}{action_input} : $self->{wsa}{action_output};
72             }
73              
74             #-----------
75              
76             sub _load_ns($$)
77 4     4   10 { my ($self, $schema, $fn) = @_;
78 4         43 $schema->importDefinitions(File::Spec->catfile($xsddir, $fn));
79             }
80              
81             sub wsdl11Init($$)
82 2     2 1 5876 { my ($self, $wsdl, $args) = @_;
83 2         8 my $def = $versions{$self->{version}};
84              
85 2         7 my $ns = $self->wsaNS;
86 2         8 $wsdl->addPrefixes(wsa => $ns, wsaw => WSDL11WSAW);
87 2         126 $wsdl->addKeyRewrite('PREFIXED(wsa,wsaw)');
88              
89 2         20 $wsdl->addCompileOptions('READERS'
90             , anyElement => 'TAKE_ALL'
91             , anyAttribute => 'TAKE_ALL'
92             );
93              
94 2         25 trace "loading wsa $self->{version}";
95 2         35 $self->_load_ns($wsdl, $def->{xsd});
96 2         3767 $self->_load_ns($wsdl, '20060512-wsaw.xsd');
97              
98 2 50       1914 my $wsa_action_ns = $self->version eq '0.9' ? $ns : WSDL11WSAW;
99             $wsdl->addHook
100             ( action => 'READER'
101             , type => pack_type(WSDL11, 'tParam')
102             , after => sub
103 4     4   237479 { my ($xml, $data, $path) = @_;
104 4         17 $data->{wsa_action} = $xml->getAttributeNS($wsa_action_ns,'Action');
105 4         62 $data;
106             }
107 2         8 );
108              
109             # [0.94] Many headers may contain attributes (which are usually not auto-
110             # detected anyway), which will cause the field to be a HASH. Older
111             # versions of this module would always simply return the content, not a
112             # HASH. Let's not break those.
113             $wsdl->addHook
114             ( action => 'READER'
115             , type => 'wsa:AttributedURIType'
116             , after => sub
117 3     3   26373 { my ($xml, $data, $path) = @_;
118             $data = $data->{_}
119 3 50 33     38 if ref $data eq 'HASH' && keys %$data==1 && $data->{_};
      33        
120 3         8 $data;
121             }
122 2         123 );
123              
124             # For unknown reason, the FaultDetail header is described everywhere
125             # in the docs, but missing from the schema.
126 2         94 $wsdl->importDefinitions( <<_FAULTDETAIL );
127            
128             xmlns:tns="$ns" targetNamespace="$ns"
129             elementFormDefault="qualified"
130             attributeFormDefault="unqualified">
131            
132            
133            
134            
135            
136            
137            
138            
139             _FAULTDETAIL
140              
141 2         985 $self;
142             }
143              
144             sub soap11OperationInit($$)
145 2     2 1 28035 { my ($self, $op, $args) = @_;
146 2         11 my $ns = $self->wsaNS;
147              
148 2         8 $op->{wsa}{action_input} = $args->{input_def}{body}{wsa_action};
149 2         7 $op->{wsa}{action_output} = $args->{output_def}{body}{wsa_action};
150              
151 2         19 trace "adding wsa header logic";
152 2         46 my $def = $versions{$self->{version}};
153 2         4 foreach my $hdr ( @{$def->{hdr}} )
  2         6  
154 18         500 { $op->addHeader(INPUT => "wsa_$hdr" => "{$ns}$hdr");
155 18         586 $op->addHeader(OUTPUT => "wsa_$hdr" => "{$ns}$hdr");
156             }
157              
158             # soap11 specific
159 2         72 $op->addHeader(OUTPUT => wsa_FaultDetail => "{$ns}FaultDetail");
160             }
161             *soap12OperationInit = \&soap11OperationInit;
162              
163             sub soap11ClientWrapper($$$)
164 2     2 1 240137 { my ($self, $op, $call, $args) = @_;
165 2         10 my $to = ($op->endPoints)[0];
166 2   66     19 my $action = $op->wsaAction('INPUT') || $op->soapAction;
167             # my $outact = $op->wsaAction('OUTPUT');
168              
169 2 50       23 trace "added wsa in call $to".($action ? " for $action" : '');
170             sub
171 2 50   2   1721 { my $data = @_==1 ? shift : {@_};
172 2   33     16 $data->{wsa_To} ||= $to;
173 2   33     11 $data->{wsa_Action} ||= $action;
174 2         6 $call->($data);
175             # should we check that the wsa_Action in the reply is correct?
176 2         53 };
177             }
178             *soap12ClientWrapper = \&soap11ClientWrapper;
179              
180             sub soap11HandlerWrapper($$$)
181 0     0 1   { my ($self, $op, $cb, $args) = @_;
182 0           my $outact = $op->wsaAction('OUTPUT');
183 0 0         defined $outact
184             or return $cb;
185              
186             sub
187 0     0     { my $data = $cb->(@_);
188 0           $data->{wsa_Action} = $outact;
189 0           $data;
190 0           };
191             }
192             *soap12HandlerWrapper = \&soap11HandlerWrapper;
193              
194              
195             1;