| Class | SOAP::RPC::Router |
| In: |
lib/soap/rpc/router.rb
|
| Parent: | Object |
| actor | [R] | |
| external_ces | [RW] | |
| generate_explicit_type | [RW] | |
| literal_mapping_registry | [RW] | |
| mapping_registry | [RW] |
# File lib/soap/rpc/router.rb, line 33
33: def initialize(actor)
34: @actor = actor
35: @mapping_registry = nil
36: @headerhandler = Header::HandlerSet.new
37: @literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
38: @generate_explicit_type = true
39: @external_ces = nil
40: @operation_by_soapaction = {}
41: @operation_by_qname = {}
42: @headerhandlerfactory = []
43: end
Alias for add_document_operation
# File lib/soap/rpc/router.rb, line 119
119: def add_document_operation(receiver, soapaction, name, param_def, opt = {})
120: #
121: # adopt workaround for doc/lit wrapper method
122: # (you should consider to simply use rpc/lit service)
123: #
124: #unless soapaction
125: # raise RPCRoutingError.new("soapaction is a must for document method")
126: #end
127: ensure_styleuse_option(opt, :document, :literal)
128: op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
129: opt)
130: if opt[:request_style] != :document
131: raise RPCRoutingError.new("illegal request_style given")
132: end
133: assign_operation(soapaction, first_input_part_qname(param_def), op)
134: end
# File lib/soap/rpc/router.rb, line 137
137: def add_document_request_operation(factory, soapaction, name, param_def, opt = {})
138: #
139: # adopt workaround for doc/lit wrapper method
140: # (you should consider to simply use rpc/lit service)
141: #
142: #unless soapaction
143: # raise RPCRoutingError.new("soapaction is a must for document method")
144: #end
145: ensure_styleuse_option(opt, :document, :literal)
146: op = RequestScopeOperation.new(soapaction, receiver, name, param_def, opt)
147: if opt[:request_style] != :document
148: raise RPCRoutingError.new("illegal request_style given")
149: end
150: assign_operation(soapaction, first_input_part_qname(param_def), op)
151: end
# File lib/soap/rpc/router.rb, line 55
55: def add_headerhandler(handler)
56: @headerhandler.add(handler)
57: end
header handler interface
# File lib/soap/rpc/router.rb, line 48
48: def add_request_headerhandler(factory)
49: unless factory.respond_to?(:create)
50: raise TypeError.new("factory must respond to 'create'")
51: end
52: @headerhandlerfactory << factory
53: end
operation definition interface
# File lib/soap/rpc/router.rb, line 96
96: def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
97: ensure_styleuse_option(opt, :rpc, :encoded)
98: opt[:request_qname] = qname
99: op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
100: opt)
101: if opt[:request_style] != :rpc
102: raise RPCRoutingError.new("illegal request_style given")
103: end
104: assign_operation(soapaction, qname, op)
105: end
# File lib/soap/rpc/router.rb, line 109
109: def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {})
110: ensure_styleuse_option(opt, :rpc, :encoded)
111: opt[:request_qname] = qname
112: op = RequestScopeOperation.new(soapaction, factory, name, param_def, opt)
113: if opt[:request_style] != :rpc
114: raise RPCRoutingError.new("illegal request_style given")
115: end
116: assign_operation(soapaction, qname, op)
117: end
servant definition interface
# File lib/soap/rpc/router.rb, line 62
62: def add_rpc_request_servant(factory, namespace)
63: unless factory.respond_to?(:create)
64: raise TypeError.new("factory must respond to 'create'")
65: end
66: obj = factory.create # a dummy instance for introspection
67: ::SOAP::RPC.defined_methods(obj).each do |name|
68: begin
69: qname = XSD::QName.new(namespace, name)
70: param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
71: opt = create_styleuse_option(:rpc, :encoded)
72: add_rpc_request_operation(factory, qname, nil, name, param_def, opt)
73: rescue SOAP::RPC::MethodDefinitionError => e
74: p e if $DEBUG
75: end
76: end
77: end
# File lib/soap/rpc/router.rb, line 79
79: def add_rpc_servant(obj, namespace)
80: ::SOAP::RPC.defined_methods(obj).each do |name|
81: begin
82: qname = XSD::QName.new(namespace, name)
83: param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
84: opt = create_styleuse_option(:rpc, :encoded)
85: add_rpc_operation(obj, qname, nil, name, param_def, opt)
86: rescue SOAP::RPC::MethodDefinitionError => e
87: p e if $DEBUG
88: end
89: end
90: end
Create fault response string.
# File lib/soap/rpc/router.rb, line 183
183: def create_fault_response(e)
184: env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e)))
185: opt = {}
186: opt[:external_content] = nil
187: response_string = Processor.marshal(env, opt)
188: conn_data = StreamHandler::ConnectionData.new(response_string)
189: conn_data.is_fault = true
190: if ext = opt[:external_content]
191: mimeize(conn_data, ext)
192: end
193: conn_data
194: end
# File lib/soap/rpc/router.rb, line 153
153: def route(conn_data)
154: # we cannot set request_default_encodingsyle before parsing the content.
155: env = unmarshal(conn_data)
156: if env.nil?
157: raise ArgumentError.new("illegal SOAP marshal format")
158: end
159: op = lookup_operation(conn_data.soapaction, env.body)
160: headerhandler = @headerhandler.dup
161: @headerhandlerfactory.each do |f|
162: headerhandler.add(f.create)
163: end
164: receive_headers(headerhandler, env.header)
165: soap_response = default_encodingstyle = nil
166: begin
167: soap_response =
168: op.call(env.body, @mapping_registry, @literal_mapping_registry,
169: create_mapping_opt)
170: default_encodingstyle = op.response_default_encodingstyle
171: rescue Exception
172: soap_response = fault($!)
173: default_encodingstyle = nil
174: end
175: conn_data.is_fault = true if soap_response.is_a?(SOAPFault)
176: header = call_headers(headerhandler)
177: body = SOAPBody.new(soap_response)
178: env = SOAPEnvelope.new(header, body)
179: marshal(conn_data, env, default_encodingstyle)
180: end
# File lib/soap/rpc/router.rb, line 222
222: def assign_operation(soapaction, qname, op)
223: assigned = false
224: if soapaction and !soapaction.empty?
225: @operation_by_soapaction[soapaction] = op
226: assigned = true
227: end
228: if qname
229: @operation_by_qname[qname] = op
230: assigned = true
231: end
232: unless assigned
233: raise RPCRoutingError.new("cannot assign operation")
234: end
235: end
# File lib/soap/rpc/router.rb, line 253
253: def call_headers(headerhandler)
254: headers = headerhandler.on_outbound
255: if headers.empty?
256: nil
257: else
258: h = ::SOAP::SOAPHeader.new
259: headers.each do |header|
260: h.add(header.elename.name, header)
261: end
262: h
263: end
264: end
# File lib/soap/rpc/router.rb, line 330
330: def create_mapping_opt
331: { :external_ces => @external_ces }
332: end
# File lib/soap/rpc/router.rb, line 208
208: def create_styleuse_option(style, use)
209: opt = {}
210: opt[:request_style] = opt[:response_style] = style
211: opt[:request_use] = opt[:response_use] = use
212: opt
213: end
# File lib/soap/rpc/router.rb, line 215
215: def ensure_styleuse_option(opt, style, use)
216: opt[:request_style] ||= style
217: opt[:response_style] ||= style
218: opt[:request_use] ||= use
219: opt[:response_use] ||= use
220: end
Create fault response.
# File lib/soap/rpc/router.rb, line 321
321: def fault(e)
322: detail = Mapping::SOAPException.new(e)
323: SOAPFault.new(
324: SOAPString.new('Server'),
325: SOAPString.new(e.to_s),
326: SOAPString.new(@actor),
327: Mapping.obj2soap(detail, @mapping_registry))
328: end
# File lib/soap/rpc/router.rb, line 198
198: def first_input_part_qname(param_def)
199: param_def.each do |inout, paramname, typeinfo|
200: if inout == SOAPMethod::IN
201: klass, nsdef, namedef = typeinfo
202: return XSD::QName.new(nsdef, namedef)
203: end
204: end
205: nil
206: end
# File lib/soap/rpc/router.rb, line 237
237: def lookup_operation(soapaction, body)
238: if op = @operation_by_soapaction[soapaction]
239: return op
240: end
241: qname = body.root_node.elename
242: if op = @operation_by_qname[qname]
243: return op
244: end
245: if soapaction
246: raise RPCRoutingError.new(
247: "operation: #{soapaction} #{qname} not supported")
248: else
249: raise RPCRoutingError.new("operation: #{qname} not supported")
250: end
251: end
# File lib/soap/rpc/router.rb, line 295
295: def marshal(conn_data, env, default_encodingstyle = nil)
296: opt = {}
297: opt[:external_content] = nil
298: opt[:default_encodingstyle] = default_encodingstyle
299: opt[:generate_explicit_type] = @generate_explicit_type
300: response_string = Processor.marshal(env, opt)
301: conn_data.send_string = response_string
302: if ext = opt[:external_content]
303: mimeize(conn_data, ext)
304: end
305: conn_data
306: end
# File lib/soap/rpc/router.rb, line 308
308: def mimeize(conn_data, ext)
309: mime = MIMEMessage.new
310: ext.each do |k, v|
311: mime.add_attachment(v.data)
312: end
313: mime.add_part(conn_data.send_string + "\r\n")
314: mime.close
315: conn_data.send_string = mime.content_str
316: conn_data.send_contenttype = mime.headers['content-type'].str
317: conn_data
318: end
# File lib/soap/rpc/router.rb, line 266
266: def receive_headers(headerhandler, headers)
267: headerhandler.on_inbound(headers) if headers
268: end
# File lib/soap/rpc/router.rb, line 270
270: def unmarshal(conn_data)
271: opt = {}
272: contenttype = conn_data.receive_contenttype
273: if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
274: opt[:external_content] = {}
275: mime = MIMEMessage.parse("Content-Type: " + contenttype,
276: conn_data.receive_string)
277: mime.parts.each do |part|
278: value = Attachment.new(part.content)
279: value.contentid = part.contentid
280: obj = SOAPAttachment.new(value)
281: opt[:external_content][value.contentid] = obj if value.contentid
282: end
283: opt[:charset] =
284: StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
285: env = Processor.unmarshal(mime.root.content, opt)
286: else
287: opt[:charset] = ::SOAP::StreamHandler.parse_media_type(contenttype)
288: env = Processor.unmarshal(conn_data.receive_string, opt)
289: end
290: charset = opt[:charset]
291: conn_data.send_contenttype = "text/xml; charset=\"#{charset}\""
292: env
293: end