mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 e17884c45c
			
		
	
	
		e17884c45c
		
	
	
	
	
		
			
			Content-Length parameter optional for responses in xmlrpc/client.rb; suggested by Daniel Berger <Daniel.Berger@qwest.com> and approved by the maintainer. * lib/xmlrpc/create.rb (XMLRPC::Create::conv2value): Add DateTime support to xmlrpc; approved by the maintainer. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11816 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			290 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| #
 | |
| # Creates XML-RPC call/response documents
 | |
| # 
 | |
| # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
 | |
| #
 | |
| # $Id$
 | |
| #
 | |
| 
 | |
| require "date"
 | |
| require "xmlrpc/base64"
 | |
| 
 | |
| module XMLRPC
 | |
| 
 | |
|   module XMLWriter
 | |
| 
 | |
|     class Abstract
 | |
|       def ele(name, *children)
 | |
| 	element(name, nil, *children)
 | |
|       end
 | |
| 
 | |
|       def tag(name, txt)
 | |
| 	element(name, nil, text(txt))
 | |
|       end
 | |
|     end
 | |
| 
 | |
| 
 | |
|     class Simple < Abstract
 | |
| 
 | |
|       def document_to_str(doc)
 | |
| 	doc
 | |
|       end
 | |
| 
 | |
|       def document(*params)
 | |
| 	params.join("")
 | |
|       end
 | |
| 
 | |
|       def pi(name, *params)
 | |
| 	"<?#{name} " + params.join(" ") + " ?>"
 | |
|       end
 | |
| 
 | |
|       def element(name, attrs, *children)
 | |
| 	raise "attributes not yet implemented" unless attrs.nil?
 | |
|         if children.empty?
 | |
|           "<#{name}/>" 
 | |
|         else
 | |
|           "<#{name}>" + children.join("") + "</#{name}>"
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       def text(txt)
 | |
|         cleaned = txt.dup
 | |
|         cleaned.gsub!(/&/, '&')
 | |
|         cleaned.gsub!(/</, '<')
 | |
|         cleaned.gsub!(/>/, '>')
 | |
|         cleaned
 | |
|       end
 | |
| 
 | |
|     end # class Simple
 | |
| 
 | |
| 
 | |
|     class XMLParser < Abstract
 | |
| 
 | |
|       def initialize
 | |
| 	require "xmltreebuilder"
 | |
|       end
 | |
| 
 | |
|       def document_to_str(doc)
 | |
| 	doc.to_s
 | |
|       end
 | |
| 
 | |
|       def document(*params)
 | |
| 	XML::SimpleTree::Document.new(*params) 
 | |
|       end
 | |
| 
 | |
|       def pi(name, *params)
 | |
| 	XML::SimpleTree::ProcessingInstruction.new(name, *params)
 | |
|       end
 | |
| 
 | |
|       def element(name, attrs, *children)
 | |
| 	XML::SimpleTree::Element.new(name, attrs, *children)
 | |
|       end
 | |
| 
 | |
|       def text(txt)
 | |
| 	XML::SimpleTree::Text.new(txt)
 | |
|       end
 | |
| 
 | |
|     end # class XMLParser
 | |
| 
 | |
|     Classes = [Simple, XMLParser]
 | |
| 
 | |
|     # yields an instance of each installed XML writer
 | |
|     def self.each_installed_writer
 | |
|       XMLRPC::XMLWriter::Classes.each do |klass|
 | |
|         begin
 | |
|           yield klass.new
 | |
|         rescue LoadError
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|   end # module XMLWriter
 | |
| 
 | |
|   class Create
 | |
| 
 | |
|     def initialize(xml_writer = nil)
 | |
|       @writer = xml_writer || Config::DEFAULT_WRITER.new
 | |
|     end
 | |
| 
 | |
| 
 | |
|     def methodCall(name, *params)
 | |
|       name = name.to_s
 | |
| 
 | |
|       if name !~ /[a-zA-Z0-9_.:\/]+/
 | |
| 	raise ArgumentError, "Wrong XML-RPC method-name"
 | |
|       end
 | |
| 
 | |
|       parameter = params.collect do |param|
 | |
| 	@writer.ele("param", conv2value(param))
 | |
|       end
 | |
| 
 | |
|       tree = @writer.document(
 | |
| 	       @writer.pi("xml", 'version="1.0"'),
 | |
| 	       @writer.ele("methodCall",   
 | |
| 		 @writer.tag("methodName", name),
 | |
| 		 @writer.ele("params", *parameter)    
 | |
| 	       )
 | |
| 	     )
 | |
| 
 | |
|       @writer.document_to_str(tree) + "\n"
 | |
|     end
 | |
| 
 | |
| 
 | |
| 
 | |
|     #
 | |
|     # generates a XML-RPC methodResponse document
 | |
|     #
 | |
|     # if is_ret == false then the params array must
 | |
|     # contain only one element, which is a structure
 | |
|     # of a fault return-value.
 | |
|     # 
 | |
|     # if is_ret == true then a normal 
 | |
|     # return-value of all the given params is created.
 | |
|     #
 | |
|     def methodResponse(is_ret, *params)
 | |
| 
 | |
|       if is_ret 
 | |
| 	resp = params.collect do |param|
 | |
| 	  @writer.ele("param", conv2value(param))
 | |
| 	end
 | |
|      
 | |
| 	resp = [@writer.ele("params", *resp)]
 | |
|       else
 | |
| 	if params.size != 1 or params[0] === XMLRPC::FaultException 
 | |
| 	  raise ArgumentError, "no valid fault-structure given"
 | |
| 	end
 | |
| 	resp = @writer.ele("fault", conv2value(params[0].to_h))
 | |
|       end
 | |
| 
 | |
| 	
 | |
|       tree = @writer.document(
 | |
| 	       @writer.pi("xml", 'version="1.0"'),
 | |
| 	       @writer.ele("methodResponse", resp) 
 | |
| 	     )
 | |
| 
 | |
|       @writer.document_to_str(tree) + "\n"
 | |
|     end
 | |
| 
 | |
| 
 | |
| 
 | |
|     #####################################
 | |
|     private
 | |
|     #####################################
 | |
| 
 | |
|     #
 | |
|     # converts a Ruby object into
 | |
|     # a XML-RPC <value> tag
 | |
|     #
 | |
|     def conv2value(param)
 | |
| 
 | |
| 	val = case param
 | |
| 	when Fixnum 
 | |
| 	  @writer.tag("i4", param.to_s)
 | |
| 
 | |
| 	when Bignum
 | |
|           if Config::ENABLE_BIGINT
 | |
|             @writer.tag("i4", param.to_s)
 | |
|           else
 | |
|             if param >= -(2**31) and param <= (2**31-1)
 | |
|               @writer.tag("i4", param.to_s)
 | |
|             else
 | |
|               raise "Bignum is too big! Must be signed 32-bit integer!"
 | |
|             end
 | |
|           end
 | |
| 	when TrueClass, FalseClass
 | |
| 	  @writer.tag("boolean", param ? "1" : "0")
 | |
| 
 | |
| 	when Symbol 
 | |
| 	  @writer.tag("string", param.to_s)
 | |
| 
 | |
| 	when String 
 | |
| 	  @writer.tag("string", param)
 | |
| 
 | |
|         when NilClass
 | |
|           if Config::ENABLE_NIL_CREATE
 | |
|             @writer.ele("nil")
 | |
|           else
 | |
|             raise "Wrong type NilClass. Not allowed!"
 | |
|           end
 | |
| 
 | |
| 	when Float
 | |
| 	  @writer.tag("double", param.to_s)
 | |
| 
 | |
| 	when Struct
 | |
| 	  h = param.members.collect do |key| 
 | |
| 	    value = param[key]
 | |
| 	    @writer.ele("member", 
 | |
| 	      @writer.tag("name", key.to_s),
 | |
| 	      conv2value(value) 
 | |
| 	    )
 | |
| 	  end
 | |
| 
 | |
| 	  @writer.ele("struct", *h) 
 | |
| 
 | |
| 	when Hash
 | |
| 	  # TODO: can a Hash be empty?
 | |
| 	  
 | |
| 	  h = param.collect do |key, value|
 | |
| 	    @writer.ele("member", 
 | |
| 	      @writer.tag("name", key.to_s),
 | |
| 	      conv2value(value) 
 | |
| 	    )
 | |
| 	  end
 | |
| 
 | |
| 	  @writer.ele("struct", *h) 
 | |
| 
 | |
| 	when Array
 | |
| 	  # TODO: can an Array be empty?
 | |
| 	  a = param.collect {|v| conv2value(v) }
 | |
| 	  
 | |
| 	  @writer.ele("array", 
 | |
| 	    @writer.ele("data", *a)
 | |
| 	  )
 | |
| 
 | |
| 	when Time, Date, ::DateTime
 | |
| 	  @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))  
 | |
| 
 | |
| 	when XMLRPC::DateTime
 | |
| 	  @writer.tag("dateTime.iso8601", 
 | |
| 	    format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
 | |
|    
 | |
| 	when XMLRPC::Base64
 | |
| 	  @writer.tag("base64", param.encoded) 
 | |
| 
 | |
| 	else 
 | |
|           if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable
 | |
|             # convert Ruby object into Hash
 | |
|             ret = {"___class___" => param.class.name}
 | |
|             param.instance_variables.each {|v| 
 | |
|               name = v[1..-1]
 | |
|               val = param.instance_variable_get(v)
 | |
| 
 | |
|               if val.nil?
 | |
|                 ret[name] = val if Config::ENABLE_NIL_CREATE
 | |
|               else
 | |
|                 ret[name] = val
 | |
|               end
 | |
|             }
 | |
|             return conv2value(ret)
 | |
|           else 
 | |
|             ok, pa = wrong_type(param)
 | |
|             if ok
 | |
|               return conv2value(pa)
 | |
|             else 
 | |
|               raise "Wrong type!"
 | |
|             end
 | |
|           end
 | |
| 	end
 | |
| 	 
 | |
| 	@writer.ele("value", val)
 | |
|     end
 | |
| 
 | |
|     def wrong_type(value)
 | |
|       false
 | |
|     end
 | |
| 
 | |
|     
 | |
|   end # class Create
 | |
| 
 | |
| end # module XMLRPC
 | |
| 
 |