class SOAP::RPC::Router

Attributes

actor[R]
external_ces[RW]
generate_explicit_type[RW]
literal_mapping_registry[RW]
mapping_registry[RW]

Public Class Methods

new(actor) click to toggle source
# File lib/soap/rpc/router.rb, line 33
def initialize(actor)
  @actor = actor
  @mapping_registry = nil
  @headerhandler = Header::HandlerSet.new
  @literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
  @generate_explicit_type = true
  @external_ces = nil
  @operation_by_soapaction = {}
  @operation_by_qname = {}
  @headerhandlerfactory = []
end

Public Instance Methods

add_document_method(receiver, soapaction, name, param_def, opt = {})
add_document_operation(receiver, soapaction, name, param_def, opt = {}) click to toggle source
# File lib/soap/rpc/router.rb, line 119
def add_document_operation(receiver, soapaction, name, param_def, opt = {})
  #
  # adopt workaround for doc/lit wrapper method
  # (you should consider to simply use rpc/lit service)
  #
  #unless soapaction
  #  raise RPCRoutingError.new("soapaction is a must for document method")
  #end
  ensure_styleuse_option(opt, :document, :literal)
  op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
    opt)
  if opt[:request_style] != :document
    raise RPCRoutingError.new("illegal request_style given")
  end
  assign_operation(soapaction, first_input_part_qname(param_def), op)
end
Also aliased as: add_document_method
add_document_request_operation(factory, soapaction, name, param_def, opt = {}) click to toggle source
# File lib/soap/rpc/router.rb, line 137
def add_document_request_operation(factory, soapaction, name, param_def, opt = {})
  #
  # adopt workaround for doc/lit wrapper method
  # (you should consider to simply use rpc/lit service)
  #
  #unless soapaction
  #  raise RPCRoutingError.new("soapaction is a must for document method")
  #end
  ensure_styleuse_option(opt, :document, :literal)
  op = RequestScopeOperation.new(soapaction, receiver, name, param_def, opt)
  if opt[:request_style] != :document
    raise RPCRoutingError.new("illegal request_style given")
  end
  assign_operation(soapaction, first_input_part_qname(param_def), op)
end
add_headerhandler(handler) click to toggle source
# File lib/soap/rpc/router.rb, line 55
def add_headerhandler(handler)
  @headerhandler.add(handler)
end
add_method(receiver, qname, soapaction, name, param_def, opt = {})
Alias for: add_rpc_operation
add_request_headerhandler(factory) click to toggle source

header handler interface

# File lib/soap/rpc/router.rb, line 48
def add_request_headerhandler(factory)
  unless factory.respond_to?(:create)
    raise TypeError.new("factory must respond to 'create'")
  end
  @headerhandlerfactory << factory
end
add_rpc_method(receiver, qname, soapaction, name, param_def, opt = {})
Alias for: add_rpc_operation
add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {}) click to toggle source

operation definition interface

# File lib/soap/rpc/router.rb, line 96
def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
  ensure_styleuse_option(opt, :rpc, :encoded)
  opt[:request_qname] = qname
  op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
    opt)
  if opt[:request_style] != :rpc
    raise RPCRoutingError.new("illegal request_style given")
  end
  assign_operation(soapaction, qname, op)
end
Also aliased as: add_method, add_rpc_method
add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {}) click to toggle source
# File lib/soap/rpc/router.rb, line 109
def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {})
  ensure_styleuse_option(opt, :rpc, :encoded)
  opt[:request_qname] = qname
  op = RequestScopeOperation.new(soapaction, factory, name, param_def, opt)
  if opt[:request_style] != :rpc
    raise RPCRoutingError.new("illegal request_style given")
  end
  assign_operation(soapaction, qname, op)
end
add_rpc_request_servant(factory, namespace) click to toggle source

servant definition interface

# File lib/soap/rpc/router.rb, line 62
def add_rpc_request_servant(factory, namespace)
  unless factory.respond_to?(:create)
    raise TypeError.new("factory must respond to 'create'")
  end
  obj = factory.create        # a dummy instance for introspection
  ::SOAP::RPC.defined_methods(obj).each do |name|
    begin
      qname = XSD::QName.new(namespace, name)
      param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
      opt = create_styleuse_option(:rpc, :encoded)
      add_rpc_request_operation(factory, qname, nil, name, param_def, opt)
    rescue SOAP::RPC::MethodDefinitionError => e
      p e if $DEBUG
    end
  end
end
add_rpc_servant(obj, namespace) click to toggle source
# File lib/soap/rpc/router.rb, line 79
def add_rpc_servant(obj, namespace)
  ::SOAP::RPC.defined_methods(obj).each do |name|
    begin
      qname = XSD::QName.new(namespace, name)
      param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
      opt = create_styleuse_option(:rpc, :encoded)
      add_rpc_operation(obj, qname, nil, name, param_def, opt)
    rescue SOAP::RPC::MethodDefinitionError => e
      p e if $DEBUG
    end
  end
end
Also aliased as: add_servant
add_servant(obj, namespace)
Alias for: add_rpc_servant
create_fault_response(e) click to toggle source

Create fault response string.

# File lib/soap/rpc/router.rb, line 183
def create_fault_response(e)
  env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e)))
  opt = {}
  opt[:external_content] = nil
  response_string = Processor.marshal(env, opt)
  conn_data = StreamHandler::ConnectionData.new(response_string)
  conn_data.is_fault = true
  if ext = opt[:external_content]
    mimeize(conn_data, ext)
  end
  conn_data
end
route(conn_data) click to toggle source
# File lib/soap/rpc/router.rb, line 153
def route(conn_data)
  # we cannot set request_default_encodingsyle before parsing the content.
  env = unmarshal(conn_data)
  if env.nil?
    raise ArgumentError.new("illegal SOAP marshal format")
  end
  op = lookup_operation(conn_data.soapaction, env.body)
  headerhandler = @headerhandler.dup
  @headerhandlerfactory.each do |f|
    headerhandler.add(f.create)
  end
  receive_headers(headerhandler, env.header)
  soap_response = default_encodingstyle = nil
  begin
    soap_response =
      op.call(env.body, @mapping_registry, @literal_mapping_registry,
        create_mapping_opt)
    default_encodingstyle = op.response_default_encodingstyle
  rescue Exception
    soap_response = fault($!)
    default_encodingstyle = nil
  end
  conn_data.is_fault = true if soap_response.is_a?(SOAPFault)
  header = call_headers(headerhandler)
  body = SOAPBody.new(soap_response)
  env = SOAPEnvelope.new(header, body)
  marshal(conn_data, env, default_encodingstyle)
end

Private Instance Methods

assign_operation(soapaction, qname, op) click to toggle source
# File lib/soap/rpc/router.rb, line 222
def assign_operation(soapaction, qname, op)
  assigned = false
  if soapaction and !soapaction.empty?
    @operation_by_soapaction[soapaction] = op
    assigned = true
  end
  if qname
    @operation_by_qname[qname] = op
    assigned = true
  end
  unless assigned
    raise RPCRoutingError.new("cannot assign operation")
  end
end
call_headers(headerhandler) click to toggle source
# File lib/soap/rpc/router.rb, line 253
def call_headers(headerhandler)
  headers = headerhandler.on_outbound
  if headers.empty?
    nil
  else
    h = ::SOAP::SOAPHeader.new
    headers.each do |header|
      h.add(header.elename.name, header)
    end
    h
  end
end
create_mapping_opt() click to toggle source
# File lib/soap/rpc/router.rb, line 330
def create_mapping_opt
  { :external_ces => @external_ces }
end
create_styleuse_option(style, use) click to toggle source
# File lib/soap/rpc/router.rb, line 208
def create_styleuse_option(style, use)
  opt = {}
  opt[:request_style] = opt[:response_style] = style
  opt[:request_use] = opt[:response_use] = use
  opt
end
ensure_styleuse_option(opt, style, use) click to toggle source
# File lib/soap/rpc/router.rb, line 215
def ensure_styleuse_option(opt, style, use)
  opt[:request_style] ||= style
  opt[:response_style] ||= style
  opt[:request_use] ||= use
  opt[:response_use] ||= use
end
fault(e) click to toggle source

Create fault response.

# File lib/soap/rpc/router.rb, line 321
def fault(e)
  detail = Mapping::SOAPException.new(e)
  SOAPFault.new(
    SOAPString.new('Server'),
    SOAPString.new(e.to_s),
    SOAPString.new(@actor),
    Mapping.obj2soap(detail, @mapping_registry))
end
first_input_part_qname(param_def) click to toggle source
# File lib/soap/rpc/router.rb, line 198
def first_input_part_qname(param_def)
  param_def.each do |inout, paramname, typeinfo|
    if inout == SOAPMethod::IN
      klass, nsdef, namedef = typeinfo
      return XSD::QName.new(nsdef, namedef)
    end
  end
  nil
end
lookup_operation(soapaction, body) click to toggle source
# File lib/soap/rpc/router.rb, line 237
def lookup_operation(soapaction, body)
  if op = @operation_by_soapaction[soapaction]
    return op
  end
  qname = body.root_node.elename
  if op = @operation_by_qname[qname]
    return op
  end
  if soapaction
    raise RPCRoutingError.new(
      "operation: #{soapaction} #{qname} not supported")
  else
    raise RPCRoutingError.new("operation: #{qname} not supported")
  end
end
marshal(conn_data, env, default_encodingstyle = nil) click to toggle source
# File lib/soap/rpc/router.rb, line 295
def marshal(conn_data, env, default_encodingstyle = nil)
  opt = {}
  opt[:external_content] = nil
  opt[:default_encodingstyle] = default_encodingstyle
  opt[:generate_explicit_type] = @generate_explicit_type
  response_string = Processor.marshal(env, opt)
  conn_data.send_string = response_string
  if ext = opt[:external_content]
    mimeize(conn_data, ext)
  end
  conn_data
end
mimeize(conn_data, ext) click to toggle source
# File lib/soap/rpc/router.rb, line 308
def mimeize(conn_data, ext)
  mime = MIMEMessage.new
  ext.each do |k, v|
    mime.add_attachment(v.data)
  end
  mime.add_part(conn_data.send_string + "\r\n")
  mime.close
  conn_data.send_string = mime.content_str
  conn_data.send_contenttype = mime.headers['content-type'].str
  conn_data
end
receive_headers(headerhandler, headers) click to toggle source
# File lib/soap/rpc/router.rb, line 266
def receive_headers(headerhandler, headers)
  headerhandler.on_inbound(headers) if headers
end
unmarshal(conn_data) click to toggle source
# File lib/soap/rpc/router.rb, line 270
def unmarshal(conn_data)
  opt = {}
  contenttype = conn_data.receive_contenttype
  if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
    opt[:external_content] = {}
    mime = MIMEMessage.parse("Content-Type: " + contenttype,
      conn_data.receive_string)
    mime.parts.each do |part|
      value = Attachment.new(part.content)
      value.contentid = part.contentid
      obj = SOAPAttachment.new(value)
      opt[:external_content][value.contentid] = obj if value.contentid
    end
    opt[:charset] =
      StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
    env = Processor.unmarshal(mime.root.content, opt)
  else
    opt[:charset] = ::SOAP::StreamHandler.parse_media_type(contenttype)
    env = Processor.unmarshal(conn_data.receive_string, opt)
  end
  charset = opt[:charset]
  conn_data.send_contenttype = "text/xml; charset=\"#{charset}\""
  env
end