google-ads-common 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/ChangeLog +5 -0
  2. data/README +1 -4
  3. data/Rakefile +2 -2
  4. data/lib/ads_common/api.rb +106 -16
  5. data/lib/ads_common/api_config.rb +2 -3
  6. data/lib/ads_common/auth/base_handler.rb +22 -3
  7. data/lib/ads_common/auth/client_login_handler.rb +27 -32
  8. data/lib/ads_common/auth/oauth_handler.rb +260 -0
  9. data/lib/ads_common/build/savon_abstract_generator.rb +12 -11
  10. data/lib/ads_common/build/savon_generator.rb +31 -27
  11. data/lib/ads_common/build/savon_registry.rb +46 -23
  12. data/lib/ads_common/build/savon_registry_generator.rb +23 -10
  13. data/lib/ads_common/build/savon_service_generator.rb +17 -3
  14. data/lib/ads_common/config.rb +1 -1
  15. data/lib/ads_common/credential_handler.rb +3 -7
  16. data/lib/ads_common/errors.rb +18 -6
  17. data/lib/ads_common/savon_headers/base_header_handler.rb +80 -0
  18. data/lib/ads_common/{soap4r_logger.rb → savon_headers/httpi_request_proxy.rb} +27 -20
  19. data/lib/ads_common/savon_headers/oauth_header_handler.rb +92 -0
  20. data/lib/ads_common/savon_headers/simple_header_handler.rb +17 -49
  21. data/lib/ads_common/savon_service.rb +129 -41
  22. data/test/test_savon_service.rb +9 -4
  23. metadata +39 -43
  24. data/lib/ads_common/build/rake_common.rb +0 -343
  25. data/lib/ads_common/build/soap4r_generator.rb +0 -565
  26. data/lib/ads_common/savon_headers/client_login_header_handler.rb +0 -60
  27. data/lib/ads_common/soap4r_headers/nested_header_handler.rb +0 -50
  28. data/lib/ads_common/soap4r_headers/single_header_handler.rb +0 -44
  29. data/lib/ads_common/soap4r_patches.rb +0 -210
  30. data/lib/ads_common/soap4r_response_handler.rb +0 -80
@@ -1,565 +0,0 @@
1
- #!/usr/bin/ruby
2
- #
3
- # Author:: api.sgomes@gmail.com (Sérgio Gomes)
4
- #
5
- # Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
6
- #
7
- # License:: Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16
- # implied.
17
- # See the License for the specific language governing permissions and
18
- # limitations under the License.
19
- #
20
- # Generates the wrappers for API services. Only used during the
21
- # 'rake generate' step of library setup.
22
-
23
- module AdsCommon
24
- module Build
25
-
26
- # Contains the methods that handle wrapper code generation.
27
- module Soap4rGenerator
28
- ARRAY_CLASSNAME = 'SOAP::SOAPArray'
29
-
30
- # Should be overriden for specific APIs, to contain the API config
31
- # module.
32
- def api_config
33
- nil
34
- end
35
-
36
- # Should be overriden for specific APIs, to contain the extension config
37
- # module.
38
- def extension_config
39
- nil
40
- end
41
-
42
- # Should be overriden for specific APIs, to contain an instance of
43
- # AdsCommon::Config with the configs for the appropriate library.
44
- def config
45
- nil
46
- end
47
-
48
- # Converts from camelCase names to underscore_separated names.
49
- #
50
- # Args:
51
- # - text: the text to be converted
52
- #
53
- def underscore(text)
54
- text.gsub(/[a-z0-9][A-Z]/) do |match|
55
- match[0,1] + '_' + match[1,1].downcase
56
- end
57
- end
58
-
59
- # Generate the wrapper class for a given service.
60
- # These classes make it easier to invoke the API methods, by removing the
61
- # need to instance a <MethodName> object, instead allowing passing of the
62
- # call parameters directly.
63
- #
64
- # Args:
65
- # - version: the API version (as an integer)
66
- # - service: the service name (as a string)
67
- #
68
- # Returns:
69
- # The Ruby code for the class, as a string.
70
- #
71
- def generate_wrapper_class(version, service)
72
- wrapper = service.to_s + "Wrapper"
73
- module_name = api_config.module_name(version, service)
74
- driver = api_config.interface_name(version, service)
75
- driver_class = eval(driver)
76
- api_name = api_config.api_name
77
-
78
- registry =
79
- eval("#{module_name}::DefaultMappingRegistry::LiteralRegistry")
80
-
81
- class_def = <<-EOS
82
- # This file was automatically generated during the "rake generate" step of
83
- # library setup.
84
- require '#{api_config.api_path}/#{version}/#{service}Driver.rb'
85
-
86
- module #{api_name}
87
- module #{version.to_s.upcase}
88
- module #{service}
89
-
90
- # Wrapper class for the #{version.to_s} #{service} service.
91
- # This class is automatically generated.
92
- class #{wrapper}
93
-
94
- # Holds the API object to which the wrapper belongs.
95
- attr_reader :api
96
-
97
- # Version and service utility fields.
98
- attr_reader :version, :service
99
-
100
- REGISTRY = #{module_name}::DefaultMappingRegistry::LiteralRegistry
101
- # This takes advantage of the code generated by soap4r to get the
102
- # correct namespace for a given service. It accesses one of the fields
103
- # in the description of the service's methods, which indicates the
104
- # namespace.
105
- # Since we're using a fixed version of soap4r (1.5.8), and this is
106
- # automatically generated as part of the stub generation, it will
107
- # always point to what we want.
108
- NAMESPACE = '#{driver_class::Methods[0][2][0][2][1]}'
109
-
110
- # Holds a shortcut to the parent module.
111
- # Use this to avoid typing the full class name when creating classes
112
- # belonging to this service, e.g.
113
- # service_object.module::ClassName
114
- # instead of
115
- # #{api_name}::#{version.to_s.upcase}::#{service}::ClassName
116
- # This will make it easier to migrate your code between API versions.
117
- attr_reader :module
118
-
119
- public
120
-
121
- # Constructor for #{wrapper}.
122
- #
123
- # Args:
124
- # - driver: SOAP::RPC::Driver object with the remote SOAP methods for
125
- # this service
126
- # - api: the API object to which the wrapper belongs
127
- #
128
- def initialize(driver, api)
129
- @driver = driver
130
- @api = api
131
- @module = #{api_name}::#{version.to_s.upcase}::#{service}
132
- @version = :#{version}
133
- @service = :#{service}
134
- end
135
-
136
- # Returns the namespace for this service.
137
- def namespace
138
- return NAMESPACE
139
- end
140
-
141
- private
142
-
143
- # Converts from underscore_separated names to camelCase names.
144
- #
145
- # Args:
146
- # - text: the text to be converted
147
- #
148
- def camel_case(text)
149
- text.gsub(/_\\w/) {|match| match[1..-1].upcase}
150
- end
151
-
152
- # Converts from camelCase names to underscore_separated names.
153
- #
154
- # Args:
155
- # - text: the text to be converted
156
- #
157
- def underscore(text)
158
- text.gsub(/[a-z0-9][A-Z]/) do |match|
159
- match[0,1] + '_' + match[1,1].downcase
160
- end
161
- end
162
-
163
- # Validates whether an object is of the correct type.
164
- # This method is invoked by the hash to object converter during
165
- # runtime to check the type validity of every object.
166
- #
167
- # Args:
168
- # - object: the hash "object" being evaluated
169
- # - type: the expected type (the class object itself)
170
- #
171
- # Returns:
172
- # nil, upon success
173
- #
174
- # Raises:
175
- # - ArgumentError: in case of an unexpected type
176
- #
177
- def validate_object(object, type)
178
- return nil if object.is_a? type
179
-
180
- wsdl_type_obj = type.new
181
-
182
- if object.is_a? Hash
183
- xsi_type = object[:xsi_type] or object['xsi_type']
184
- if xsi_type
185
- begin
186
- subtype = @module.class_eval(xsi_type)
187
- user_type_obj = subtype.new
188
- rescue
189
- raise ArgumentError, "Specified xsi_type '" + xsi_type +
190
- "' is unknown"
191
- end
192
- unless user_type_obj.is_a? type
193
- raise ArgumentError, "Specified xsi_type '" + xsi_type +
194
- "' is not a subclass of " + type.to_s
195
- end
196
- else
197
- object.each do |key, value|
198
- if key.to_s != 'xsi_type'
199
- if !wsdl_type_obj.respond_to?(camel_case(key.to_s).to_sym)
200
- raise ArgumentError, "Unknown property '" + key.to_s +
201
- "' for type " + type.to_s
202
- end
203
- end
204
- end
205
- end
206
- end
207
- return nil
208
- end
209
-
210
- # Sets a property on a real (soap4r-generated) object.
211
- #
212
- # Args:
213
- # - object: the object being modified
214
- # - property: the property being set
215
- # - value: the value it's being set to
216
- #
217
- def set_object_property(object, property, value)
218
- begin
219
- object.send(property.to_s + '=', value)
220
- rescue
221
- object_class = object.class.name.split('::').last
222
- error = AdsCommon::Errors::MissingPropertyError.new(
223
- property, object_class)
224
- message = "'Missing property `" + property.to_s +
225
- "' for object class `" + object_class + "'"
226
- raise(error, message)
227
- end
228
- end
229
-
230
- public
231
-
232
- # Converts dynamic objects (property hashes) into real soap4r objects.
233
- # This is meant to be called when setting properties on a class, so
234
- # the method receives an optional parameter specifying the class and
235
- # property. This way, it's possible to determine the default type for
236
- # the object if none is provided.
237
- #
238
- # Args:
239
- # - object: the object being converted
240
- # - parent_class: the class whose property is being set
241
- # - property: the property being set
242
- #
243
- def convert_to_object(object, parent_class = nil, property = nil)
244
- property = camel_case(property.to_s) if property
245
- if object.is_a? Hash
246
- # Process a hash.
247
- specified_class = object[:xsi_type] or object['xsi_type']
248
- default_class = nil
249
- # Determine default class for this object, given the property
250
- # being set.
251
- if parent_class and property
252
- parent = REGISTRY.schema_definition_from_class(parent_class)
253
- element = parent.elements.entries.find do |entry|
254
- entry.varname.to_s == property.to_s
255
- end
256
- default_class = element.mapped_class if element
257
- end
258
- validate_object(object, default_class)
259
- real_class = nil
260
- if specified_class
261
- real_class = @module.class_eval(specified_class)
262
- else
263
- real_class = default_class
264
- end
265
- # Instance real object.
266
- real_object = real_class.new
267
- # Set each of its properties.
268
- object.each do |entry, value|
269
- entry = entry.to_s
270
- unless entry == 'xsi_type'
271
- if @api.config.read('service.use_ruby_names', true)
272
- entry = camel_case(entry)
273
- end
274
- if value.is_a? Hash
275
- # Recurse.
276
- set_object_property(real_object, entry,
277
- convert_to_object(value, real_class, entry))
278
- elsif value.is_a? Array
279
- set_object_property(real_object, entry,
280
- value.map do |item|
281
- # Recurse.
282
- convert_to_object(item, real_class, entry)
283
- end
284
- )
285
- else
286
- set_object_property(real_object, entry, value)
287
- end
288
- end
289
- end
290
- return real_object
291
- elsif object.is_a? Array
292
- # Process an array
293
- return object.map do |entry|
294
- # Recurse.
295
- convert_to_object(entry, parent_class, property)
296
- end
297
- else
298
- return object
299
- end
300
- end
301
-
302
- # Converts real soap4r objects into dynamic ones (property hashes).
303
- # This is meant to be called for return objects of remote calls.
304
- #
305
- # Args:
306
- # - object: the object being converted
307
- #
308
- def convert_from_object(object)
309
- if object.class.name =~
310
- /#{api_config.api_name}::#{version.to_s.upcase}::\\w+::\\w+/
311
- # Handle soap4r object
312
- object_class = REGISTRY.schema_definition_from_class(object.class)
313
- if object_class.elements and !object_class.elements.entries.empty?
314
- # Process complex object.
315
- hash = {}
316
- hash[:xsi_type] = object.class.name.split('::').last
317
- object_class.elements.entries.each do |entry|
318
- property = entry.varname.to_s
319
- if object.respond_to? property and !property.include?('_Type')
320
- value = object.send(property)
321
- property_name = nil
322
- if @api.config.read('service.use_ruby_names', true)
323
- property_name = underscore(property).to_sym
324
- else
325
- property_name = property.to_sym
326
- end
327
- # Recurse.
328
- hash[property_name] = convert_from_object(value) if value
329
- end
330
- end
331
- return hash
332
- else
333
- # Process simple object.
334
- parent = object.class.superclass
335
- return parent.new(object)
336
- end
337
- elsif object.is_a? Array
338
- # Handle arrays
339
- return object.map do |entry|
340
- # Recurse.
341
- convert_from_object(entry)
342
- end
343
- else
344
- # Handle native objects
345
- return object
346
- end
347
- end
348
-
349
-
350
- public
351
-
352
- EOS
353
-
354
- # Add service methods
355
- methods = driver_class::Methods
356
- module_name = api_config.module_name(version, service)
357
- methods.each do |method|
358
- name = method[1]
359
- doc_link = doc_link(version, service, name)
360
- method_def = <<-EOS
361
- # Calls the {#{name}}[#{doc_link}] method of the #{service} service.
362
- # Check {the online documentation for this method}[#{doc_link}].
363
- EOS
364
-
365
- begin
366
- method_class = eval("#{module_name}::#{fix_case_up(name)}")
367
- arguments =
368
- registry.schema_definition_from_class(method_class).elements
369
- rescue
370
- method_class = nil
371
- arguments = nil
372
- end
373
-
374
- if arguments and arguments.size > 0
375
- method_def += <<-EOS
376
- #
377
- # Args:
378
- EOS
379
- end
380
-
381
- if arguments
382
- # Add list of arguments to the RDoc comment
383
- arguments.each_with_index do |elem, index|
384
- if type(elem) == ARRAY_CLASSNAME
385
- method_def += <<-EOS
386
- # - #{elem.varname}: #{type(elem)} of #{elem.mapped_class}
387
- EOS
388
- else
389
- method_def += <<-EOS
390
- # - #{elem.varname}: #{type(elem)}
391
- EOS
392
- end
393
- end
394
- end
395
-
396
- begin
397
- response_class =
398
- eval("#{module_name}::#{fix_case_up(name)}Response")
399
- returns =
400
- registry.schema_definition_from_class(response_class).elements
401
-
402
- if returns.size > 0
403
- method_def += <<-EOS
404
- #
405
- # Returns:
406
- EOS
407
- end
408
-
409
- # Add list of returns to the RDoc comment
410
- returns.each_with_index do |elem, index|
411
- if type(elem) == ARRAY_CLASSNAME
412
- method_def += <<-EOS
413
- # - #{elem.varname}: #{type(elem)} of #{elem.mapped_class}
414
- EOS
415
- else
416
- method_def += <<-EOS
417
- # - #{elem.varname}: #{type(elem)}
418
- EOS
419
- end
420
- end
421
- rescue
422
- method_def += <<-EOS
423
- #
424
- # Returns:
425
- EOS
426
- end
427
-
428
- arg_names = arguments ? arguments.map {|elem| elem.varname} : []
429
- arg_list = arg_names.join(', ')
430
-
431
- method_def += <<-EOS
432
- #
433
- # Raises:
434
- # Error::ApiError (or a subclass thereof) if a SOAP fault occurs.
435
- #
436
- def #{name}(#{arg_list})
437
- begin
438
- arg_array = []
439
- EOS
440
-
441
- # Add validation for every argument
442
- if arguments
443
- arguments.each_with_index do |elem, index|
444
- method_def += <<-EOS
445
- validate_object(#{arg_names[index]}, #{type(elem)})
446
- arg_array << convert_to_object(#{elem.varname}, #{method_class},
447
- '#{elem.varname}')
448
- EOS
449
- end
450
- end
451
-
452
- method_def += <<-EOS
453
- # Construct request object and make API call
454
- EOS
455
-
456
- if arguments
457
- method_def += <<-EOS
458
- obj = #{module_name}::#{fix_case_up(name)}.new(*arg_array)
459
- reply = convert_from_object(@driver.#{name}(obj))
460
- EOS
461
- else
462
- method_def += <<-EOS
463
- reply = convert_from_object(@driver.#{name}())
464
- EOS
465
- end
466
-
467
- method_def += <<-EOS
468
- reply = reply[:rval] if reply.include?(:rval)
469
- return reply
470
- rescue SOAP::FaultError => fault
471
- raise #{api_config.api_name}::Errors.create_api_exception(fault,
472
- self)
473
- end
474
- end
475
-
476
- EOS
477
- class_def += method_def
478
-
479
- if name != underscore(name)
480
- class_def += <<-EOS
481
- alias #{underscore(name)} #{name}\n
482
-
483
- EOS
484
- end
485
- end
486
-
487
- # Add extension methods, if any
488
- extensions = extension_config.extensions[[version, service]]
489
- unless extensions.nil?
490
- extensions.each do |ext|
491
- params = extension_config.methods[ext].join(', ')
492
- arglist = 'self'
493
- arglist += ", #{params}" if params != ''
494
- method_def = <<-EOS
495
- # <i>Extension method</i> -- Calls the
496
- # #{api_config.api_name}::Extensions.#{ext} method with +self+ as the
497
- # first parameter.
498
- def #{ext}(#{params})
499
- return #{api_config.api_name}::Extensions.#{ext}(#{arglist})
500
- end
501
-
502
- EOS
503
- class_def += method_def
504
- end
505
- end
506
-
507
- class_def += <<-EOS
508
- end
509
- end
510
- end
511
- end
512
- EOS
513
- return class_def
514
- end
515
-
516
- # Helper method to fix a method name from lowerCamelCase to CamelCase.
517
- #
518
- # Args:
519
- # - name: the method name
520
- #
521
- # Returns:
522
- # The fixed name.
523
- #
524
- def fix_case_up(name)
525
- return name[0, 1].upcase + name[1..-1]
526
- end
527
-
528
- # Helper method to create a link to a method's entry in the API online
529
- # docs.
530
- #
531
- # Args:
532
- # - version: the API version (as an integer)
533
- # - service: the service name (as a string)
534
- # - method: the method name (as a string)
535
- #
536
- # Returns:
537
- # The URL to the method's entry in the documentation (as a string).
538
- # +nil+ if none.
539
- #
540
- def doc_link(version, service, method)
541
- return nil
542
- end
543
-
544
- # Helper method to return the expected type for a parameter, given the
545
- # SchemaElementDefinition.
546
- #
547
- # Args:
548
- # - element: SOAP::Mapping::SchemaElementDefinition element for the
549
- # parameter (taken from the schema definition of the class)
550
- #
551
- # Returns:
552
- # The full name for the expected parameter type (as a String)
553
- #
554
- def type(element)
555
- # Check if it's an array
556
- if element.as_array?
557
- return ARRAY_CLASSNAME
558
- else
559
- return element.mapped_class
560
- end
561
- end
562
- end
563
- end
564
- end
565
-