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

root/trunk/lib/soap/wsdlDriver.rb

Revision 2007, 4.9 kB (checked in by nahi, 1 year ago)
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # SOAP4R - SOAP WSDL 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 'wsdl/parser'
10 require 'wsdl/importer'
11 require 'xsd/qname'
12 require 'xsd/codegen/gensupport'
13 require 'soap/attrproxy'
14 require 'soap/mapping/wsdlencodedregistry'
15 require 'soap/mapping/wsdlliteralregistry'
16 require 'soap/rpc/driver'
17 require 'wsdl/soap/methodDefCreator'
18 require 'wsdl/soap/classDefCreatorSupport'
19 require 'wsdl/soap/classNameCreator'
20
21
22 module SOAP
23
24
25 class WSDLDriverFactory
26   include WSDL::SOAP::ClassDefCreatorSupport
27
28   class FactoryError < StandardError; end
29
30   attr_reader :wsdl
31
32   def initialize(wsdl)
33     @wsdl = import(wsdl)
34   end
35  
36   def inspect
37     sprintf("#<%s:%s:0x%x\n\n%s>", self.class.name, @wsdl.name, __id__, dump_method_signatures)
38   end
39
40   def create_rpc_driver(servicename = nil, portname = nil)
41     port = find_port(servicename, portname)
42     drv = SOAP::RPC::Driver.new(port.soap_address.location)
43     if binding = port.find_binding
44       init_driver(drv, binding)
45       add_operation(drv, binding)
46     end
47     drv
48   end
49
50   def dump_method_signatures(servicename = nil, portname = nil)
51     targetservice = XSD::QName.new(@wsdl.targetnamespace, servicename) if servicename
52     targetport = XSD::QName.new(@wsdl.targetnamespace, portname) if portname
53     sig = []
54     element_definitions = @wsdl.collect_elements
55     @wsdl.services.each do |service|
56       next if targetservice and service.name != targetservice
57       service.ports.each do |port|
58         next if targetport and port.name != targetport
59         if porttype = port.porttype
60           assigned_method = collect_assigned_method(porttype.name)
61           if binding = port.porttype.find_binding
62             sig << binding.operations.collect { |op_bind|
63               operation = op_bind.find_operation
64               name = assigned_method[op_bind.boundid] || op_bind.name
65               str = "= #{safemethodname(name)}\n\n"
66               str << dump_method_signature(name, operation, element_definitions)
67               str.gsub(/^#/, " ")
68             }.join("\n")
69           end
70         end
71       end
72     end
73     sig.join("\n")
74   end
75
76 private
77
78   def collect_assigned_method(porttypename)
79     name_creator = WSDL::SOAP::ClassNameCreator.new
80     methoddefcreator =
81       WSDL::SOAP::MethodDefCreator.new(@wsdl, name_creator, nil, {})
82     methoddefcreator.dump(porttypename)
83     methoddefcreator.assigned_method
84   end
85
86   def find_port(servicename = nil, portname = nil)
87     service = port = nil
88     if servicename
89       service = @wsdl.service(
90         XSD::QName.new(@wsdl.targetnamespace, servicename))
91     else
92       service = @wsdl.services[0]
93     end
94     if service.nil?
95       raise FactoryError.new("service #{servicename} not found in WSDL")
96     end
97     if portname
98       port = service.ports[XSD::QName.new(@wsdl.targetnamespace, portname)]
99       if port.nil?
100         raise FactoryError.new("port #{portname} not found in WSDL")
101       end
102     else
103       port = service.ports.find { |port| !port.soap_address.nil? }
104       if port.nil?
105         raise FactoryError.new("no ports have soap:address")
106       end
107     end
108     if port.soap_address.nil?
109       raise FactoryError.new("soap:address element not found in WSDL")
110     end
111     port
112   end
113
114   def init_driver(drv, binding)
115     wsdl_elements = @wsdl.collect_elements
116     wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
117     rpc_decode_typemap = wsdl_types +
118       @wsdl.soap_rpc_complextypes(binding)
119     drv.proxy.mapping_registry =
120       Mapping::WSDLEncodedRegistry.new(rpc_decode_typemap)
121     drv.proxy.literal_mapping_registry =
122       Mapping::WSDLLiteralRegistry.new(wsdl_types, wsdl_elements)
123   end
124
125   def add_operation(drv, binding)
126     name_creator = WSDL::SOAP::ClassNameCreator.new
127     modulepath = 'WSDLDriverFactory'
128     methoddefcreator =
129       WSDL::SOAP::MethodDefCreator.new(@wsdl, name_creator, modulepath, {})
130     mdefs = methoddefcreator.create(binding.name)
131     if mdefs.nil?
132       raise FactoryError.new("no method definition found in WSDL")
133     end
134     mdefs.each do |mdef|
135       opt = {
136         :request_style => mdef.style,
137         :response_style => mdef.style,
138         :request_use => mdef.inputuse,
139         :response_use => mdef.outputuse
140       }
141       qname = mdef.qname
142       soapaction = mdef.soapaction
143       name = mdef.name
144       if mdef.style == :rpc
145         drv.add_rpc_operation(qname, soapaction, name, mdef.parameters, opt)
146       else
147         drv.add_document_operation(soapaction, name, mdef.parameters, opt)
148       end
149       orgname = mdef.qname.name
150       if orgname != name and orgname.capitalize == name.capitalize
151         ::SOAP::Mapping.define_singleton_method(drv, orgname) do |*arg|
152           __send__(name, *arg)
153         end
154       end
155     end
156   end
157
158   def import(location)
159     WSDL::Importer.import(location)
160   end
161 end
162
163
164 end
Note: See TracBrowser for help on using the browser.