# File lib/soap/rpc/router.rb, line 37 37: def initialize(actor) 38: @actor = actor 39: @mapping_registry = nil 40: @headerhandler = Header::HandlerSet.new 41: @literal_mapping_registry = ::SOAP::Mapping::LiteralRegistry.new 42: @generate_explicit_type = true 43: @use_default_namespace = false 44: @external_ces = nil 45: @operation_by_soapaction = {} 46: @operation_by_qname = {} 47: @headerhandlerfactory = [] 48: @filterchain = Filter::FilterChain.new 49: end
# File lib/soap/rpc/router.rb, line 125 125: def add_document_operation(receiver, soapaction, name, param_def, opt = {}) 126: # 127: # adopt workaround for doc/lit wrapper method 128: # (you should consider to simply use rpc/lit service) 129: # 130: #unless soapaction 131: # raise RPCRoutingError.new("soapaction is a must for document method") 132: #end 133: ensure_styleuse_option(opt, :document, :literal) 134: op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def, 135: opt) 136: if opt[:request_style] != :document 137: raise RPCRoutingError.new("illegal request_style given") 138: end 139: assign_operation(soapaction, first_input_part_qname(param_def), op) 140: end
# File lib/soap/rpc/router.rb, line 143 143: def add_document_request_operation(factory, soapaction, name, param_def, opt = {}) 144: # 145: # adopt workaround for doc/lit wrapper method 146: # (you should consider to simply use rpc/lit service) 147: # 148: #unless soapaction 149: # raise RPCRoutingError.new("soapaction is a must for document method") 150: #end 151: ensure_styleuse_option(opt, :document, :literal) 152: op = RequestScopeOperation.new(soapaction, receiver, name, param_def, opt) 153: if opt[:request_style] != :document 154: raise RPCRoutingError.new("illegal request_style given") 155: end 156: assign_operation(soapaction, first_input_part_qname(param_def), op) 157: end
# File lib/soap/rpc/router.rb, line 61 61: def add_headerhandler(handler) 62: @headerhandler.add(handler) 63: end
header handler interface
# File lib/soap/rpc/router.rb, line 54 54: def add_request_headerhandler(factory) 55: unless factory.respond_to?(:create) 56: raise TypeError.new("factory must respond to 'create'") 57: end 58: @headerhandlerfactory << factory 59: end
operation definition interface
# File lib/soap/rpc/router.rb, line 102 102: def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {}) 103: ensure_styleuse_option(opt, :rpc, :encoded) 104: opt[:request_qname] = qname 105: op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def, 106: opt) 107: if opt[:request_style] != :rpc 108: raise RPCRoutingError.new("illegal request_style given") 109: end 110: assign_operation(soapaction, qname, op) 111: end
# File lib/soap/rpc/router.rb, line 115 115: def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {}) 116: ensure_styleuse_option(opt, :rpc, :encoded) 117: opt[:request_qname] = qname 118: op = RequestScopeOperation.new(soapaction, factory, name, param_def, opt) 119: if opt[:request_style] != :rpc 120: raise RPCRoutingError.new("illegal request_style given") 121: end 122: assign_operation(soapaction, qname, op) 123: end
servant definition interface
# File lib/soap/rpc/router.rb, line 68 68: def add_rpc_request_servant(factory, namespace) 69: unless factory.respond_to?(:create) 70: raise TypeError.new("factory must respond to 'create'") 71: end 72: obj = factory.create # a dummy instance for introspection 73: ::SOAP::RPC.defined_methods(obj).each do |name| 74: begin 75: qname = XSD::QName.new(namespace, name) 76: param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name) 77: opt = create_styleuse_option(:rpc, :encoded) 78: add_rpc_request_operation(factory, qname, nil, name, param_def, opt) 79: rescue SOAP::RPC::MethodDefinitionError => e 80: p e if $DEBUG 81: end 82: end 83: end
# File lib/soap/rpc/router.rb, line 85 85: def add_rpc_servant(obj, namespace) 86: ::SOAP::RPC.defined_methods(obj).each do |name| 87: begin 88: qname = XSD::QName.new(namespace, name) 89: param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name) 90: opt = create_styleuse_option(:rpc, :encoded) 91: add_rpc_operation(obj, qname, nil, name, param_def, opt) 92: rescue SOAP::RPC::MethodDefinitionError => e 93: p e if $DEBUG 94: end 95: end 96: end
Create fault response string.
# File lib/soap/rpc/router.rb, line 200 200: def create_fault_response(e) 201: env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e, nil), true)) 202: opt = {} 203: opt[:external_content] = nil 204: @filterchain.reverse_each do |filter| 205: env = filter.on_outbound(env, opt) 206: break unless env 207: end 208: response_string = Processor.marshal(env, opt) 209: conn_data = StreamHandler::ConnectionData.new(response_string) 210: conn_data.is_fault = true 211: if ext = opt[:external_content] 212: mimeize(conn_data, ext) 213: end 214: conn_data 215: end
# File lib/soap/rpc/router.rb, line 159 159: def route(conn_data) 160: # we cannot set request_default_encodingsyle before parsing the content. 161: env = unmarshal(conn_data) 162: if env.nil? 163: raise ArgumentError.new("illegal SOAP marshal format") 164: end 165: op = lookup_operation(conn_data.soapaction, env.body) 166: headerhandler = @headerhandler.dup 167: @headerhandlerfactory.each do |f| 168: headerhandler.add(f.create) 169: end 170: soap_response = default_encodingstyle = nil 171: begin 172: receive_headers(headerhandler, env.header) 173: soap_response = 174: op.call(env.body, @mapping_registry, @literal_mapping_registry, 175: create_mapping_opt) 176: conn_data.is_fault = true if soap_response.is_a?(SOAPFault) 177: default_encodingstyle = op.response_default_encodingstyle 178: rescue Exception => e 179: # If a wsdl fault was raised by service, the fault declaration details 180: # is kept in wsdl_fault. Otherwise (exception is a program fault) 181: # wsdl_fault is nil 182: wsdl_fault_details = op.faults && op.faults[e.class.name] 183: soap_response = fault(e, wsdl_fault_details) 184: conn_data.is_fault = true 185: default_encodingstyle = nil 186: end 187: header = call_headers(headerhandler) 188: if op.response_use.nil? 189: conn_data.send_string = '' 190: conn_data.is_nocontent = true 191: conn_data 192: else 193: body = SOAPBody.new(soap_response, conn_data.is_fault) 194: env = SOAPEnvelope.new(header, body) 195: marshal(conn_data, env, default_encodingstyle) 196: end 197: end
# File lib/soap/rpc/router.rb, line 247 247: def assign_operation(soapaction, qname, op) 248: assigned = false 249: if soapaction and !soapaction.empty? 250: @operation_by_soapaction[soapaction] = op 251: assigned = true 252: end 253: if qname 254: @operation_by_qname[qname] = op 255: assigned = true 256: end 257: unless assigned 258: raise RPCRoutingError.new("cannot assign operation") 259: end 260: end
# File lib/soap/rpc/router.rb, line 278 278: def call_headers(headerhandler) 279: header = ::SOAP::SOAPHeader.new 280: items = headerhandler.on_outbound(header) 281: items.each do |item| 282: header.add(item.elename.name, item) 283: end 284: header 285: end
# File lib/soap/rpc/router.rb, line 394 394: def create_mapping_opt 395: { :external_ces => @external_ces } 396: end
# File lib/soap/rpc/router.rb, line 229 229: def create_styleuse_option(style, use) 230: opt = {} 231: opt[:request_style] = opt[:response_style] = style 232: opt[:request_use] = opt[:response_use] = use 233: opt 234: end
# File lib/soap/rpc/router.rb, line 236 236: def ensure_styleuse_option(opt, style, use) 237: if opt[:request_style] || opt[:response_style] || opt[:request_use] || opt[:response_use] 238: # do not edit 239: else 240: opt[:request_style] ||= style 241: opt[:response_style] ||= style 242: opt[:request_use] ||= use 243: opt[:response_use] ||= use 244: end 245: end
Create fault response.
# File lib/soap/rpc/router.rb, line 353 353: def fault(e, wsdl_fault_details) 354: if e.is_a?(UnhandledMustUnderstandHeaderError) 355: faultcode = FaultCode::MustUnderstand 356: else 357: faultcode = FaultCode::Server 358: end 359: 360: # If the exception represents a WSDL fault, the fault element should 361: # be added as the SOAP fault <detail> element. If the exception is a 362: # normal program exception, it is wrapped inside a custom SOAP4R 363: # SOAP exception element. 364: detail = nil 365: begin 366: if (wsdl_fault_details) 367: registry = wsdl_fault_details[:use] == "literal" ? 368: @literal_mapping_registry : @mapping_registry 369: faultQName = XSD::QName.new( 370: wsdl_fault_details[:ns], wsdl_fault_details[:name] 371: ) 372: detail = Mapping.obj2soap(e, registry, faultQName) 373: # wrap fault element (SOAPFault swallows top-level element) 374: wrapper = SOAP::SOAPElement.new(faultQName) 375: wrapper.add(detail) 376: detail = wrapper 377: else 378: # Exception is a normal program exception. Wrap it. 379: detail = Mapping.obj2soap(Mapping::SOAPException.new(e), 380: @mapping_registry) 381: detail.elename ||= XSD::QName::EMPTY # for literal mappingregstry 382: end 383: rescue 384: detail = SOAPString.new("failed to serialize detail object: #{$!}") 385: end 386: 387: SOAPFault.new( 388: SOAPElement.new(nil, faultcode), 389: SOAPString.new(e.to_s), 390: SOAPString.new(@actor), 391: detail) 392: end
# File lib/soap/rpc/router.rb, line 219 219: def first_input_part_qname(param_def) 220: param_def.each do |inout, paramname, typeinfo| 221: if inout == SOAPMethod::IN 222: klass, nsdef, namedef = typeinfo 223: return XSD::QName.new(nsdef, namedef) 224: end 225: end 226: nil 227: end
# File lib/soap/rpc/router.rb, line 262 262: def lookup_operation(soapaction, body) 263: if op = @operation_by_soapaction[soapaction] 264: return op 265: end 266: qname = body.root_node.elename 267: if op = @operation_by_qname[qname] 268: return op 269: end 270: if soapaction 271: raise RPCRoutingError.new( 272: "operation: #{soapaction} #{qname} not supported") 273: else 274: raise RPCRoutingError.new("operation: #{qname} not supported") 275: end 276: end
# File lib/soap/rpc/router.rb, line 322 322: def marshal(conn_data, env, default_encodingstyle = nil) 323: opt = {} 324: opt[:external_content] = nil 325: opt[:default_encodingstyle] = default_encodingstyle 326: opt[:generate_explicit_type] = @generate_explicit_type 327: opt[:use_default_namespace] = @use_default_namespace 328: @filterchain.reverse_each do |filter| 329: env = filter.on_outbound(env, opt) 330: break unless env 331: end 332: response_string = Processor.marshal(env, opt) 333: conn_data.send_string = response_string 334: if ext = opt[:external_content] 335: mimeize(conn_data, ext) 336: end 337: conn_data 338: end
# File lib/soap/rpc/router.rb, line 340 340: def mimeize(conn_data, ext) 341: mime = MIMEMessage.new 342: ext.each do |k, v| 343: mime.add_attachment(v.data) 344: end 345: mime.add_part(conn_data.send_string + "\r\n") 346: mime.close 347: conn_data.send_string = mime.content_str 348: conn_data.send_contenttype = mime.headers['content-type'].str 349: conn_data 350: end
# File lib/soap/rpc/router.rb, line 287 287: def receive_headers(headerhandler, header) 288: headerhandler.on_inbound(header) if header 289: end
# File lib/soap/rpc/router.rb, line 291 291: def unmarshal(conn_data) 292: xml = nil 293: opt = {} 294: contenttype = conn_data.receive_contenttype 295: if /#{MIMEMessage::MultipartContentType}/ =~ contenttype 296: opt[:external_content] = {} 297: mime = MIMEMessage.parse("Content-Type: " + contenttype, 298: conn_data.receive_string) 299: mime.parts.each do |part| 300: value = Attachment.new(part.content) 301: value.contentid = part.contentid 302: obj = SOAPAttachment.new(value) 303: opt[:external_content][value.contentid] = obj if value.contentid 304: end 305: opt[:charset] = 306: StreamHandler.parse_media_type(mime.root.headers['content-type'].str) 307: xml = mime.root.content 308: else 309: opt[:charset] = ::SOAP::StreamHandler.parse_media_type(contenttype) 310: xml = conn_data.receive_string 311: end 312: @filterchain.each do |filter| 313: xml = filter.on_inbound(xml, opt) 314: break unless xml 315: end 316: env = Processor.unmarshal(xml, opt) 317: charset = opt[:charset] 318: conn_data.send_contenttype = "text/xml; charset=\"#{charset}\"" 319: env 320: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.