Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

root/branches/1_5/lib/soap/rpc/driver.rb

Revision 1974, 6.7 kB (checked in by nahi, 1 year ago)
  • add the Generator option for using default namespace in SOAP message. it's for interoperability with non XML Namespace comformant implementation. false by default (same behavior as before.) you can turn it on with Driver#use_default_namespace = true or Server#use_default_namespace = true. closes #430.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # SOAP4R - SOAP RPC driver
2 # Copyright (C) 2000-2007  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
3
4 # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
5 # redistribute it and/or modify it under the same terms of Ruby's license;
6 # either the dual license version in 2003, or any later version.
7
8
9 require 'soap/soap'
10 require 'soap/mapping'
11 require 'soap/rpc/rpc'
12 require 'soap/rpc/proxy'
13 require 'soap/rpc/element'
14 require 'soap/streamHandler'
15 require 'soap/property'
16 require 'soap/header/handlerset'
17
18
19 module SOAP
20 module RPC
21
22
23 class Driver
24   class << self
25     if RUBY_VERSION >= "1.7.0"
26       def __attr_proxy(symbol, assignable = false)
27         name = symbol.to_s
28         define_method(name) {
29           @proxy.__send__(name)
30         }
31         if assignable
32           aname = name + '='
33           define_method(aname) { |rhs|
34             @proxy.__send__(aname, rhs)
35           }
36         end
37       end
38     else
39       def __attr_proxy(symbol, assignable = false)
40         name = symbol.to_s
41         module_eval <<-EOS
42           def #{name}
43             @proxy.#{name}
44           end
45         EOS
46         if assignable
47           module_eval <<-EOS
48             def #{name}=(value)
49               @proxy.#{name} = value
50             end
51           EOS
52         end
53       end
54     end
55   end
56
57   __attr_proxy :endpoint_url, true
58   __attr_proxy :mapping_registry, true
59   __attr_proxy :literal_mapping_registry, true
60   __attr_proxy :allow_unqualified_element, true
61   __attr_proxy :default_encodingstyle, true
62   __attr_proxy :generate_explicit_type, true
63   __attr_proxy :use_default_namespace, true
64   __attr_proxy :return_response_as_xml, true
65   __attr_proxy :headerhandler
66   __attr_proxy :filterchain
67   __attr_proxy :streamhandler
68   __attr_proxy :test_loopback_response
69   __attr_proxy :reset_stream
70
71   attr_reader :proxy
72   attr_reader :options
73   attr_accessor :soapaction
74
75   def inspect
76     "#<#{self.class}:#{@proxy.inspect}>"
77   end
78
79   def httpproxy
80     options["protocol.http.proxy"]
81   end
82
83   def httpproxy=(httpproxy)
84     options["protocol.http.proxy"] = httpproxy
85   end
86
87   def wiredump_dev
88     options["protocol.http.wiredump_dev"]
89   end
90
91   def wiredump_dev=(wiredump_dev)
92     options["protocol.http.wiredump_dev"] = wiredump_dev
93   end
94
95   def mandatorycharset
96     options["protocol.mandatorycharset"]
97   end
98
99   def mandatorycharset=(mandatorycharset)
100     options["protocol.mandatorycharset"] = mandatorycharset
101   end
102
103   def wiredump_file_base
104     options["protocol.wiredump_file_base"]
105   end
106
107   def wiredump_file_base=(wiredump_file_base)
108     options["protocol.wiredump_file_base"] = wiredump_file_base
109   end
110
111   def initialize(endpoint_url, namespace = nil, soapaction = nil)
112     @namespace = namespace
113     @soapaction = soapaction
114     @options = setup_options
115     @wiredump_file_base = nil
116     @proxy = Proxy.new(endpoint_url, @soapaction, @options)
117   end
118
119   def loadproperty(propertyname)
120     unless options.loadproperty(propertyname)
121       raise LoadError.new("No such property to load -- #{propertyname}")
122     end
123   end
124
125   def add_rpc_method(name, *params)
126     add_rpc_method_with_soapaction_as(name, name, @soapaction, *params)
127   end
128
129   def add_rpc_method_as(name, name_as, *params)
130     add_rpc_method_with_soapaction_as(name, name_as, @soapaction, *params)
131   end
132
133   def add_rpc_method_with_soapaction(name, soapaction, *params)
134     add_rpc_method_with_soapaction_as(name, name, soapaction, *params)
135   end
136
137   def add_rpc_method_with_soapaction_as(name, name_as, soapaction, *params)
138     param_def = SOAPMethod.create_rpc_param_def(params)
139     qname = XSD::QName.new(@namespace, name_as)
140     @proxy.add_rpc_method(qname, soapaction, name, param_def)
141     add_rpc_method_interface(name, param_def)
142   end
143
144   # add_method is for shortcut of typical rpc/encoded method definition.
145   alias add_method add_rpc_method
146   alias add_method_as add_rpc_method_as
147   alias add_method_with_soapaction add_rpc_method_with_soapaction
148   alias add_method_with_soapaction_as add_rpc_method_with_soapaction_as
149
150   def add_document_method(name, soapaction, req_qname, res_qname)
151     param_def = SOAPMethod.create_doc_param_def(req_qname, res_qname)
152     @proxy.add_document_method(soapaction, name, param_def)
153     add_document_method_interface(name, param_def)
154   end
155
156   def add_rpc_operation(qname, soapaction, name, param_def, opt = {})
157     @proxy.add_rpc_operation(qname, soapaction, name, param_def, opt)
158     add_rpc_method_interface(name, param_def)
159   end
160
161   def add_document_operation(soapaction, name, param_def, opt = {})
162     @proxy.add_document_operation(soapaction, name, param_def, opt)
163     add_document_method_interface(name, param_def)
164   end
165
166   def invoke(headers, body)
167     if headers and !headers.is_a?(SOAPHeader)
168       headers = create_header(headers)
169     end
170     set_wiredump_file_base(body.elename.name)
171     env = @proxy.invoke(headers, body)
172     if env.nil?
173       return nil, nil
174     else
175       return env.header, env.body
176     end
177   end
178
179   def call(name, *params)
180     set_wiredump_file_base(name)
181     @proxy.call(name, *params)
182   end
183
184 private
185
186   def set_wiredump_file_base(name)
187     if @wiredump_file_base
188       @proxy.set_wiredump_file_base("#{@wiredump_file_base}_#{name}")
189     end
190   end
191
192   def create_header(headers)
193     header = SOAPHeader.new()
194     headers.each do |content, mustunderstand, encodingstyle|
195       header.add(SOAPHeaderItem.new(content, mustunderstand, encodingstyle))
196     end
197     header
198   end
199
200   def setup_options
201     if opt = Property.loadproperty(::SOAP::PropertyName)
202       opt = opt["client"]
203     end
204     opt ||= Property.new
205     opt.add_hook("protocol.mandatorycharset") do |key, value|
206       @proxy.mandatorycharset = value
207     end
208     opt.add_hook("protocol.wiredump_file_base") do |key, value|
209       @wiredump_file_base = value
210     end
211     opt["protocol.http.charset"] ||= XSD::Charset.xml_encoding_label
212     opt["protocol.http.proxy"] ||= Env::HTTP_PROXY
213     opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
214     opt
215   end
216
217   def add_rpc_method_interface(name, param_def)
218     param_count = RPC::SOAPMethod.param_count(param_def,
219       RPC::SOAPMethod::IN, RPC::SOAPMethod::INOUT)
220     add_method_interface(name, param_count)
221   end
222
223   def add_document_method_interface(name, param_def)
224     param_count = RPC::SOAPMethod.param_count(param_def, RPC::SOAPMethod::IN)
225     add_method_interface(name, param_count)
226   end
227
228   # Mapping.define_singleton_method calls define_method with proc and it
229   # exhausts much memory for each singleton Object.  just instance_eval instead
230   # of it.
231   def add_method_interface(name, param_count)
232     instance_eval <<-EOS
233       def #{name}(*arg)
234         unless arg.size == #{param_count}
235           raise ArgumentError.new(
236             "wrong number of arguments (\#{arg.size} for #{param_count})")
237         end
238         call(#{name.dump}, *arg)
239       end
240     EOS
241     self.method(name)
242   end
243 end
244
245
246 end
247 end
Note: See TracBrowser for help on using the browser.