aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/lib/action_web_service/vendor/ws/encoding
diff options
context:
space:
mode:
authorLeon Breedt <bitserf@gmail.com>2005-02-25 23:39:39 +0000
committerLeon Breedt <bitserf@gmail.com>2005-02-25 23:39:39 +0000
commit6f5a7b200443baf209d2f33c428ed4a4059782f7 (patch)
tree9c3942fe27be69c102873d9fdaa13f66dc12853d /actionwebservice/lib/action_web_service/vendor/ws/encoding
parent10faf204b712763f05a2b3155a4fd9c5338f1fb2 (diff)
downloadrails-6f5a7b200443baf209d2f33c428ed4a4059782f7.tar.gz
rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.tar.bz2
rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.zip
merged the changes for the upcoming 0.6.0:
seperate out protocol marshaling into a small 'ws' library in vendor, so that AWS itself only does integration with ActionPack, and so we can keep protocol specific code in AWS proper to a minimum. refactor unit tests to get 95% code coverage (for a baseline). be far more relaxed about the types given to us by the remote side, don't do any poor man's type checking, just try to cast and marshal to the correct types if possible, and if not, return what they gave us anyway. this should make interoperating with fuzzy XML-RPC clients easier. if exception reporting is turned on, do best-effort error responses, so that we can avoid "Internal protocol error" with no details if there is a bug in AWS itself. also perform extensive cleanups on AWS proper. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@800 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/lib/action_web_service/vendor/ws/encoding')
-rw-r--r--actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb26
-rw-r--r--actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb90
-rw-r--r--actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb53
3 files changed, 169 insertions, 0 deletions
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb b/actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb
new file mode 100644
index 0000000000..257c7d0993
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb
@@ -0,0 +1,26 @@
+module WS
+ module Encoding
+ # Encoders operate on _foreign_ objects. That is, Ruby object
+ # instances that are the _marshaling format specific_ representation
+ # of objects. In other words, objects that have not yet been marshaled, but
+ # are in protocol-specific form (such as an AST or DOM element), and not
+ # native Ruby form.
+ class AbstractEncoding
+ def encode_rpc_call(method_name, params)
+ raise NotImplementedError
+ end
+
+ def decode_rpc_call(obj)
+ raise NotImplementedError
+ end
+
+ def encode_rpc_response(method_name, return_value)
+ raise NotImplementedError
+ end
+
+ def decode_rpc_response(obj)
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb b/actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb
new file mode 100644
index 0000000000..f4d2f5a7d6
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb
@@ -0,0 +1,90 @@
+require 'soap/processor'
+require 'soap/mapping'
+require 'soap/rpc/element'
+
+module WS
+ module Encoding
+ class SoapRpcError < WSError
+ end
+
+ class SoapRpcEncoding < AbstractEncoding
+ attr_accessor :method_namespace
+
+ def initialize(method_namespace='')
+ @method_namespace = method_namespace
+ end
+
+ def encode_rpc_call(method_name, foreign_params)
+ qname = create_method_qname(method_name)
+ param_def = []
+ params = foreign_params.map do |p|
+ param_def << ['in', p.param.info.name, p.param.info.data.mapping]
+ [p.param.info.name, p.soap_object]
+ end
+ request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
+ request.set_param(params)
+ envelope = create_soap_envelope(request)
+ SOAP::Processor.marshal(envelope)
+ end
+
+ def decode_rpc_call(obj)
+ envelope = SOAP::Processor.unmarshal(obj)
+ unless envelope
+ raise(SoapRpcError, "Malformed SOAP request")
+ end
+ request = envelope.body.request
+ method_name = request.elename.name
+ params = request.collect do |key, value|
+ info = ParamInfo.new(key, nil, nil)
+ param = Param.new(nil, info)
+ Marshaling::SoapForeignObject.new(param, request[key])
+ end
+ [method_name, params]
+ end
+
+ def encode_rpc_response(method_name, return_value)
+ response = nil
+ qname = create_method_qname(method_name)
+ if return_value.nil?
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
+ else
+ param = return_value.param
+ soap_object = return_value.soap_object
+ param_def = [['retval', 'return', param.info.data.mapping]]
+ if soap_object.is_a?(SOAP::SOAPFault)
+ response = soap_object
+ else
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def)
+ response.retval = soap_object
+ end
+ end
+ envelope = create_soap_envelope(response)
+ SOAP::Processor.marshal(envelope)
+ end
+
+ def decode_rpc_response(obj)
+ envelope = SOAP::Processor.unmarshal(obj)
+ unless envelope
+ raise(SoapRpcError, "Malformed SOAP response")
+ end
+ method_name = envelope.body.request.elename.name
+ return_value = envelope.body.response
+ info = ParamInfo.new('return', nil, nil)
+ param = Param.new(nil, info)
+ return_value = Marshaling::SoapForeignObject.new(param, return_value)
+ [method_name, return_value]
+ end
+
+ private
+ def create_soap_envelope(body)
+ header = SOAP::SOAPHeader.new
+ body = SOAP::SOAPBody.new(body)
+ SOAP::SOAPEnvelope.new(header, body)
+ end
+
+ def create_method_qname(method_name)
+ XSD::QName.new(@method_namespace, method_name)
+ end
+ end
+ end
+end
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb b/actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb
new file mode 100644
index 0000000000..b38ae81abf
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb
@@ -0,0 +1,53 @@
+require 'xmlrpc/marshal'
+
+module WS
+ module Encoding
+ class XmlRpcError < WSError
+ end
+
+ class XmlRpcEncoding < AbstractEncoding
+ def encode_rpc_call(method_name, params)
+ XMLRPC::Marshal.dump_call(method_name, *params)
+ end
+
+ def decode_rpc_call(obj)
+ method_name, params = XMLRPC::Marshal.load_call(obj) rescue nil
+ unless method_name && params
+ raise(XmlRpcError, "Malformed XML-RPC request")
+ end
+ i = 0
+ params = params.map do |value|
+ param = XmlRpcDecodedParam.new("param#{i}", value)
+ i += 1
+ param
+ end
+ [method_name, params]
+ end
+
+ def encode_rpc_response(method_name, return_value)
+ if return_value.nil?
+ XMLRPC::Marshal.dump_response(true)
+ else
+ XMLRPC::Marshal.dump_response(return_value)
+ end
+ end
+
+ def decode_rpc_response(obj)
+ return_value = XMLRPC::Marshal.load_response(obj) rescue nil
+ if return_value.nil?
+ raise(XmlRpcError, "Malformed XML-RPC response")
+ end
+ [nil, XmlRpcDecodedParam.new('return', return_value)]
+ end
+ end
+
+ class XmlRpcDecodedParam
+ attr :param
+
+ def initialize(name, value)
+ info = ParamInfo.new(name, value.class)
+ @param = Param.new(value, info)
+ end
+ end
+ end
+end