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

Changeset 1754

Show
Ignore:
Timestamp:
05/04/07 01:16:37 (2 years ago)
Author:
nahi
Message:
  • added wsdl:fault support. patch and sample are from Peter. Thanks.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/soap/encodingstyle/literalHandler.rb

    r1735 r1754  
    223223 
    224224  def decode_textbuf(node) 
    225     if node.is_a?(XSD::XSDString) 
     225    case node 
     226    when XSD::XSDString, SOAPElement 
    226227      if @charset 
    227228        node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset)) 
  • trunk/lib/soap/rpc/router.rb

    r1742 r1754  
    169169          create_mapping_opt) 
    170170      default_encodingstyle = op.response_default_encodingstyle 
    171     rescue Exception 
    172       soap_response = fault($!) 
     171    rescue Exception => e 
     172      # If a wsdl fault was raised by service, the fault declaration details 
     173      # is kept in wsdl_fault. Otherwise (exception is a program fault) 
     174      # wsdl_fault is nil 
     175      wsdl_fault_details = op.faults && op.faults[e.class.name] 
     176      soap_response = fault(e, wsdl_fault_details) 
    173177      default_encodingstyle = nil 
    174178    end 
     
    182186  # Create fault response string. 
    183187  def create_fault_response(e) 
    184     env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e))) 
     188    env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e, nil))) 
    185189    opt = {} 
    186190    opt[:external_content] = nil 
     
    319323 
    320324  # Create fault response. 
    321   def fault(e
     325  def fault(e, wsdl_fault_details
    322326    if e.is_a?(UnhandledMustUnderstandHeaderError) 
    323327      faultcode = FaultCode::MustUnderstand 
     
    325329      faultcode = FaultCode::Server 
    326330    end 
    327     detail = Mapping.obj2soap(Mapping::SOAPException.new(e), 
    328       @mapping_registry) 
    329     detail.elename ||= XSD::QName::EMPTY # for literal mappingregstry 
     331 
     332    # If the exception represents a WSDL fault, the fault element should 
     333    # be added as the SOAP fault <detail> element. If the exception is a 
     334    # normal program exception, it is wrapped inside a custom SOAP4R 
     335    # SOAP exception element. 
     336    detail = nil 
     337    if (wsdl_fault_details) 
     338      registry = wsdl_fault_details[:use] == "literal" ? 
     339        @literal_mapping_registry : @mapping_registry 
     340      faultQName = XSD::QName.new( 
     341        wsdl_fault_details[:ns], wsdl_fault_details[:name] 
     342      ) 
     343      detail = Mapping.obj2soap(e, registry, faultQName) 
     344      # wrap fault element (SOAPFault swallows top-level element) 
     345      wrapper = SOAP::SOAPElement.new(faultQName) 
     346      wrapper.add(detail) 
     347      detail = wrapper 
     348    else 
     349      # Exception is a normal program exception. Wrap it. 
     350      detail = Mapping.obj2soap(Mapping::SOAPException.new(e), 
     351                                @mapping_registry) 
     352      detail.elename ||= XSD::QName::EMPTY # for literal mappingregstry 
     353    end 
     354 
    330355    SOAPFault.new( 
    331356      SOAPElement.new(nil, faultcode), 
     
    346371    attr_reader :request_use 
    347372    attr_reader :response_use 
     373    attr_reader :faults 
    348374 
    349375    def initialize(soapaction, name, param_def, opt) 
     
    354380      @request_use = opt[:request_use] 
    355381      @response_use = opt[:response_use] 
     382      @faults = opt[:faults] 
    356383      check_style(@request_style) 
    357384      check_style(@response_style) 
     
    470497      end 
    471498    end 
    472      
     499 
    473500    def response_doc(result, mapping_registry, literal_mapping_registry, opt) 
    474501      if @doc_response_qnames.size == 0 
  • trunk/lib/wsdl/param.rb

    r1574 r1754  
    5757    when SOAPFaultName 
    5858      o = WSDL::SOAP::Fault.new 
    59       @soap_fault = o 
     59      @soapfault = o 
    6060      o 
    6161    when DocumentationName 
  • trunk/lib/wsdl/soap/definitions.rb

    r1739 r1754  
    8383      faultparts = message(name).parts 
    8484      if faultparts.size != 1 
    85         raise RuntimeError.new("expecting fault message to have only 1 part") 
    86       end 
    87       if result.index(faultparts[0].type).nil? 
    88         result << faultparts[0].type 
     85        raise RuntimeError.new("Expecting fault message \"#{name}\" to have ONE part") 
     86      end 
     87      fault_part = faultparts[0] 
     88      # WS-I Basic Profile Version 1.1 (R2205) requires fault message parts  
     89      # to refer to elements rather than types 
     90      if not fault_part.element 
     91        raise RuntimeError.new("Fault message \"#{name}\" part \"#{fault_part.name}\" must specify an \"element\" attribute") 
     92      end 
     93 
     94      if result.index(fault_part.element).nil? 
     95        result << fault_part.element 
    8996      end 
    9097    end 
     
    93100 
    94101private 
     102 
     103  def operation_binding(binding, operation_qname) 
     104    binding.operations.each do |op_binding| 
     105      if (op_binding.soapoperation_name == operation_qname) 
     106        return op_binding 
     107      end 
     108    end 
     109  end 
     110 
     111  def get_fault_binding(op_binding, fault_name) 
     112    op_binding.fault.each do |fault| 
     113      return fault if fault.name == fault_name 
     114    end 
     115    return nil 
     116  end 
     117 
     118  def op_binding_declares_fault(op_binding, fault_name) 
     119    return get_fault_binding(op_binding, fault_name) != nil 
     120  end 
    95121 
    96122  def collect_fault_messages 
     
    99125      porttype.operations.each do |operation| 
    100126        operation.fault.each do |fault| 
     127          # Make sure the operation fault has a name 
     128          if not fault.name 
     129            warn("Operation \"#{operation.name}\": fault must specify a \"name\" attribute") 
     130            next 
     131          end 
     132          operation_qname = XSD::QName.new(operation.targetnamespace, operation.name) 
     133          binding = porttype.find_binding() 
     134          op_binding = operation_binding(binding, operation_qname) 
     135          # Make sure that portType fault has a corresponding soap:fault 
     136          # definition in binding section. 
     137          if not op_binding_declares_fault(op_binding, fault.name) 
     138            raise RuntimeError.new("Operation \"#{operation.name}\", fault \"#{fault.name}\": no corresponding wsdl:fault binding found with a matching \"name\" attribute")           
     139          end 
     140           
     141          fault_binding = get_fault_binding(op_binding, fault.name) 
     142          if fault_binding.soapfault.name != fault_binding.name 
     143            puts "WARNING: name of soap:fault \"#{fault_binding.soapfault.name}\" doesn't match the name of wsdl:fault \"#{fault_binding.name}\" in operation \"#{operation.name}\" \n\n" 
     144          end 
     145          # According to WS-I (R2723): if in a wsdl:binding the use attribute 
     146          # on a contained soapbind:fault element is present, its value MUST  
     147          # be "literal".           
     148          if fault_binding.soapfault.use and fault_binding.soapfault.use != "literal" 
     149            raise RuntimeError.new("Operation \"#{operation.name}\", fault \"#{fault.name}\": soap:fault \"use\" attribute must be \"literal\"")           
     150          end 
     151 
    101152          if result.index(fault.message).nil? 
    102153            result << fault.message 
  • trunk/lib/wsdl/soap/methodDefCreator.rb

    r1731 r1754  
    4141    if binding 
    4242      binding.operations.each do |op_bind| 
    43         op = op_bind.find_operation 
    4443        next unless op_bind # no binding is defined 
    4544        next unless op_bind.soapoperation # not a SOAP operation binding 
     45        op = op_bind.find_operation 
    4646        methoddef << ",\n" unless methoddef.empty? 
    4747        methoddef << dump_method(op, op_bind).chomp 
     
    9393 
    9494  def dump_method(operation, binding) 
     95    op_faults = {} 
     96    binding.fault.each do |fault| 
     97      op_fault = {} 
     98      soapfault = fault.soapfault 
     99      op_fault[:ns] = fault.name.namespace 
     100      op_fault[:name] = fault.name.name 
     101      op_fault[:namespace] = soapfault.namespace 
     102      op_fault[:use] = soapfault.use || "literal" 
     103      op_fault[:encodingstyle] = soapfault.encodingstyle || "document" 
     104      op_faults[fault.name.name] = op_fault 
     105    end 
     106    op_faults_str = op_faults.inspect 
     107 
    95108    name = safemethodname(operation.name) 
    96109    name_as = operation.name 
     
    116129  #{paramstr}, 
    117130  { :request_style =>  #{sym(style.id2name)}, :request_use =>  #{sym(inputuse.id2name)}, 
    118     :response_style => #{sym(style.id2name)}, :response_use => #{sym(outputuse.id2name)} } 
     131    :response_style => #{sym(style.id2name)}, :response_use => #{sym(outputuse.id2name)}, 
     132    :faults => #{op_faults_str} } 
    119133__EOD__ 
    120134    if inputuse == :encoded or outputuse == :encoded 
  • trunk/lib/wsdl/soap/wsdl2ruby.rb

    r1731 r1754  
    5858    @modulepath = @opt['module_path'] 
    5959    create_classdef if @opt.key?('classdef') 
    60     create_mapping_registry if @opt.key?('mapping_registry') or @opt.key?('driver') 
     60    create_mapping_registry if @opt.key?('mapping_registry') 
    6161    create_servant_skelton(@opt['servant_skelton']) if @opt.key?('servant_skelton') 
    6262    create_cgi_stub(@opt['cgi_stub']) if @opt.key?('cgi_stub')