File Coverage

blib/lib/Google/Ads/AdWords/Deserializer.pm
Criterion Covered Total %
statement 18 18 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 24 24 100.0


line stmt bran cond sub pod time code
1             # Copyright 2011, Google Inc. All Rights Reserved.
2             #
3             # Licensed under the Apache License, Version 2.0 (the "License");
4             # you may not use this file except in compliance with the License.
5             # You may obtain a copy of the License at
6             #
7             # http://www.apache.org/licenses/LICENSE-2.0
8             #
9             # Unless required by applicable law or agreed to in writing, software
10             # distributed under the License is distributed on an "AS IS" BASIS,
11             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12             # See the License for the specific language governing permissions and
13             # limitations under the License.
14              
15             package Google::Ads::AdWords::Deserializer;
16              
17 13     13   19990 use strict;
  13         27  
  13         497  
18 13     13   77 use warnings;
  13         742  
  13         402  
19 13     13   7619 use utf8;
  13         159  
  13         64  
20 13     13   377 use version;
  13         29  
  13         71  
21 13     13   4081 use Scalar::Util qw(blessed);
  13         31  
  13         794  
22              
23 13     13   84 use base qw(SOAP::WSDL::Deserializer::XSD);
  13         25  
  13         5641  
24              
25             # The following needs to be on one line because CPAN uses a particularly hacky
26             # eval() to determine module versions.
27             use Google::Ads::AdWords::Constants; our $VERSION = ${Google::Ads::AdWords::Constants::VERSION};
28             use Google::Ads::AdWords::Logging;
29             use Google::Ads::AdWords::RequestStats;
30             use Google::Ads::SOAP::Deserializer::MessageParser;
31              
32             # Class attributes used to hook this class with the AdWords client
33             my %client_of : ATTR(:name :default<>);
34              
35             # Invoked by SOAP::WSDL to deserialize incoming SOAP responses.
36             sub deserialize {
37             my $self = shift;
38             my ($response_xml) = @_;
39             my $client = $self->get_client();
40             utf8::is_utf8 $response_xml and utf8::encode $response_xml;
41              
42             my $request_message = sprintf("Outgoing request:\n%s",
43             $client->get_last_soap_request());
44             my $response_message = sprintf("Incoming response:\n%s", $response_xml);
45             $client->set_last_soap_response($response_xml);
46              
47             my $response_header =
48             $self->__get_element_content($response_xml, "ResponseHeader");
49              
50             my $request_stats;
51             if ($response_header) {
52             my $request_id =
53             $self->__get_element_content($response_header, "requestId");
54             my $service_name =
55             $self->__get_element_content($response_header, "serviceName");
56             my $method_name =
57             $self->__get_element_content($response_header, "methodName");
58             my $operations =
59             $self->__get_element_content($response_header, "operations");
60             my $response_time =
61             $self->__get_element_content($response_header, "responseTime");
62              
63             my $auth_handler = $client->_get_auth_handler();
64             $request_stats = Google::Ads::AdWords::RequestStats->new({
65             client_id => $client->get_client_id(),
66             server => $client->get_alternate_url(),
67             service_name => $service_name,
68             method_name => $method_name,
69             response_time => $response_time,
70             request_id => $request_id,
71             operations => $operations
72             });
73             }
74              
75             $response_xml =~ s!.*!!;
76             my @response = $self->_deserialize($response_xml);
77             my $is_fault = $response[0]->isa("SOAP::WSDL::SOAP::Typelib::Fault");
78              
79             if ($request_stats) {
80             $request_stats->set_is_fault($is_fault);
81             if ($is_fault) {
82             $request_stats->set_fault_message($response[0]->get_faultstring());
83             Google::Ads::AdWords::Logging::get_awapi_logger->logwarn($request_stats);
84             } else {
85             Google::Ads::AdWords::Logging::get_awapi_logger->info($request_stats);
86             }
87             $client->_push_new_request_stats($request_stats);
88             }
89              
90             if ($is_fault) {
91             Google::Ads::AdWords::Logging::get_soap_logger->info($request_message);
92             Google::Ads::AdWords::Logging::get_soap_logger->info($response_message);
93             if ($self->get_client->get_die_on_faults) {
94             die(
95             sprintf("A fault was returned by the server:\n%s\n",
96             $response[0]->get_faultstring()));
97             }
98             } else {
99             Google::Ads::AdWords::Logging::get_soap_logger->debug($request_message);
100             Google::Ads::AdWords::Logging::get_soap_logger->debug($response_message);
101             }
102              
103             # Unwrapping the response if contains an rval no value for the user to see the
104             # outer response object.
105             if ($response[0] && $response[0]->can('get_rval')) {
106             $response[0] = $response[0]->get_rval();
107             }
108              
109             return @response;
110             }
111              
112             sub _deserialize {
113             my ($self, $content) = @_;
114              
115             my $parser = Google::Ads::SOAP::Deserializer::MessageParser->new(
116             {strict => $self->get_strict()});
117             $parser->class_resolver($self->get_class_resolver());
118             eval { $parser->parse_string($content) };
119             if ($@) {
120             return $self->generate_fault({
121             code => 'SOAP-ENV:Server',
122             role => 'urn:localhost',
123             message => "Error deserializing message: $@. \n" .
124             "Message was: \n$content"
125             });
126             }
127             return ($parser->get_data(), $parser->get_header());
128             }
129              
130             # Retrieves the content of a given XML element.
131             sub __get_element_content {
132             my ($self, $xml, $element_name) = @_;
133              
134             my $regex =
135             "<(?:[^:>]+:)?${element_name}(?:\\s[^>]*)?>(.+?)" .
136             "]+:)?${element_name}(?:\\s[^>]*)?>";
137              
138             $xml =~ /$regex/ and my $content = $1;
139              
140             return $content;
141             }
142              
143             # Invoked by SOAP::WSDL when deserialize die()s.
144             sub generate_fault {
145             my ($self, $args) = @_;
146             Google::Ads::AdWords::Logging::get_soap_logger->info($args->{message});
147             die($args->{message});
148             }
149              
150             return 1;
151              
152             =pod
153              
154             =head1 NAME
155              
156             Google::Ads::AdWords::Deserializer
157              
158             =head1 DESCRIPTION
159              
160             Google::Ads::AdWords::Deserializer extends the
161             L module.
162             The default deserializer used by .
163             Above the normal functionality of
164             L,
165             this module implements hooks into
166             L to simplify
167             logging and keeping track of all the information in the AdWords API response
168             headers.
169              
170             =head1 METHODS
171              
172             =head2 deserialize
173              
174             A method automatically invoked by SOAP::WSDL when an incoming SOAP XML response
175             needs to be deserialized.
176              
177             =head3 Parameters
178              
179             The SOAP XML response string.
180              
181             =head3 Returns
182              
183             A L object representing the SOAP response. Most of the
184             API calls return their result wrapped within an tag, that gets unwrapped
185             and the inner object is returned instead in those cases.
186              
187             =head3 Exceptions
188              
189             If deserialization fails or the SOAP response contains a
190             L object and
191             Google::Ads::AdWords::Client::get_die_on_faults() is set to true, then a die
192             call is triggered.
193              
194             If L is set to false then the
195             deserialized message will be passed back, containing a
196             L object.
197              
198             =head2 generate_fault
199              
200             A method automatically invoked on deserialization if an error occurred and
201             L is set to true.
202              
203             =head3 Parameters
204              
205             A L object.
206              
207             =head3 Exceptions
208              
209             Always die()s with the value of the input parameter's message.
210              
211             =head1 LICENSE AND COPYRIGHT
212              
213             Copyright 2011 Google Inc.
214              
215             Licensed under the Apache License, Version 2.0 (the "License");
216             you may not use this file except in compliance with the License.
217             You may obtain a copy of the License at
218              
219             http://www.apache.org/licenses/LICENSE-2.0
220              
221             Unless required by applicable law or agreed to in writing, software
222             distributed under the License is distributed on an "AS IS" BASIS,
223             WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
224             See the License for the specific language governing permissions and
225             limitations under the License.
226              
227             =head1 REPOSITORY INFORMATION
228              
229             $Rev: $
230             $LastChangedBy: $
231             $Id: $
232              
233             =cut