actionwebservice 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +21 -0
- data/README +50 -6
- data/Rakefile +9 -9
- data/TODO +6 -6
- data/lib/action_web_service.rb +4 -3
- data/lib/action_web_service/api.rb +248 -1
- data/lib/action_web_service/casting.rb +111 -0
- data/lib/action_web_service/client/soap_client.rb +17 -33
- data/lib/action_web_service/client/xmlrpc_client.rb +10 -34
- data/lib/action_web_service/container/delegated_container.rb +1 -1
- data/lib/action_web_service/dispatcher/abstract.rb +52 -72
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +71 -55
- data/lib/action_web_service/protocol/abstract.rb +82 -3
- data/lib/action_web_service/protocol/discovery.rb +2 -2
- data/lib/action_web_service/protocol/soap_protocol.rb +95 -22
- data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +197 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +56 -24
- data/lib/action_web_service/scaffolding.rb +237 -0
- data/lib/action_web_service/struct.rb +17 -4
- data/lib/action_web_service/support/signature_types.rb +194 -0
- data/lib/action_web_service/templates/scaffolds/layout.rhtml +65 -0
- data/lib/action_web_service/templates/scaffolds/methods.rhtml +6 -0
- data/lib/action_web_service/templates/scaffolds/parameters.rhtml +28 -0
- data/lib/action_web_service/templates/scaffolds/result.rhtml +30 -0
- data/lib/action_web_service/test_invoke.rb +23 -42
- data/test/abstract_dispatcher.rb +102 -48
- data/test/abstract_unit.rb +1 -1
- data/test/api_test.rb +40 -7
- data/test/casting_test.rb +82 -0
- data/test/client_soap_test.rb +3 -0
- data/test/client_xmlrpc_test.rb +5 -1
- data/test/dispatcher_action_controller_soap_test.rb +9 -12
- data/test/dispatcher_action_controller_xmlrpc_test.rb +1 -11
- data/test/run +1 -0
- data/test/scaffolded_controller_test.rb +67 -0
- data/test/struct_test.rb +33 -21
- data/test/test_invoke_test.rb +1 -1
- metadata +18 -31
- data/lib/action_web_service/api/base.rb +0 -135
- data/lib/action_web_service/vendor/ws.rb +0 -4
- data/lib/action_web_service/vendor/ws/common.rb +0 -8
- data/lib/action_web_service/vendor/ws/encoding.rb +0 -3
- data/lib/action_web_service/vendor/ws/encoding/abstract.rb +0 -26
- data/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb +0 -90
- data/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb +0 -53
- data/lib/action_web_service/vendor/ws/marshaling.rb +0 -3
- data/lib/action_web_service/vendor/ws/marshaling/abstract.rb +0 -17
- data/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb +0 -277
- data/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb +0 -116
- data/lib/action_web_service/vendor/ws/types.rb +0 -165
- data/test/ws/abstract_encoding.rb +0 -68
- data/test/ws/abstract_unit.rb +0 -13
- data/test/ws/gencov +0 -3
- data/test/ws/run +0 -5
- data/test/ws/soap_marshaling_test.rb +0 -91
- data/test/ws/soap_rpc_encoding_test.rb +0 -47
- data/test/ws/types_test.rb +0 -43
- data/test/ws/xmlrpc_encoding_test.rb +0 -34
@@ -1,135 +0,0 @@
|
|
1
|
-
module ActionWebService # :nodoc:
|
2
|
-
module API # :nodoc:
|
3
|
-
# A web service API class specifies the methods that will be available for
|
4
|
-
# invocation for an API. It also contains metadata such as the method type
|
5
|
-
# signature hints.
|
6
|
-
#
|
7
|
-
# It is not intended to be instantiated.
|
8
|
-
#
|
9
|
-
# It is attached to web service implementation classes like
|
10
|
-
# ActionWebService::Base and ActionController::Base derivatives by using
|
11
|
-
# ClassMethods#web_service_api.
|
12
|
-
class Base
|
13
|
-
# Whether to transform the public API method names into camel-cased names
|
14
|
-
class_inheritable_option :inflect_names, true
|
15
|
-
|
16
|
-
# Whether to allow ActiveRecord::Base models in <tt>:expects</tt>.
|
17
|
-
# The default is +false+, you should be aware of the security implications
|
18
|
-
# of allowing this, and ensure that you don't allow remote callers to
|
19
|
-
# easily overwrite data they should not have access to.
|
20
|
-
class_inheritable_option :allow_active_record_expects, false
|
21
|
-
|
22
|
-
# If present, the name of a method to call when the remote caller
|
23
|
-
# tried to call a nonexistent method. Semantically equivalent to
|
24
|
-
# +method_missing+.
|
25
|
-
class_inheritable_option :default_api_method
|
26
|
-
|
27
|
-
# Disallow instantiation
|
28
|
-
private_class_method :new, :allocate
|
29
|
-
|
30
|
-
class << self
|
31
|
-
# API methods have a +name+, which must be the Ruby method name to use when
|
32
|
-
# performing the invocation on the web service object.
|
33
|
-
#
|
34
|
-
# The signatures for the method input parameters and return value can
|
35
|
-
# by specified in +options+.
|
36
|
-
#
|
37
|
-
# A signature is an array of one or more parameter specifiers.
|
38
|
-
# A parameter specifier can be one of the following:
|
39
|
-
#
|
40
|
-
# * A symbol or string of representing one of the Action Web Service base types.
|
41
|
-
# See ActionWebService::Signature for a canonical list of the base types.
|
42
|
-
# * The Class object of the parameter type
|
43
|
-
# * A single-element Array containing one of the two preceding items. This
|
44
|
-
# will cause Action Web Service to treat the parameter at that position
|
45
|
-
# as an array containing only values of the given type.
|
46
|
-
# * A Hash containing as key the name of the parameter, and as value
|
47
|
-
# one of the three preceding items
|
48
|
-
#
|
49
|
-
# If no method input parameter or method return value signatures are given,
|
50
|
-
# the method is assumed to take no parameters and/or return no values of
|
51
|
-
# interest, and any values that are received by the server will be
|
52
|
-
# discarded and ignored.
|
53
|
-
#
|
54
|
-
# Valid options:
|
55
|
-
# [<tt>:expects</tt>] Signature for the method input parameters
|
56
|
-
# [<tt>:returns</tt>] Signature for the method return value
|
57
|
-
# [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value
|
58
|
-
def api_method(name, options={})
|
59
|
-
validate_options([:expects, :returns, :expects_and_returns], options.keys)
|
60
|
-
if options[:expects_and_returns]
|
61
|
-
expects = options[:expects_and_returns]
|
62
|
-
returns = options[:expects_and_returns]
|
63
|
-
else
|
64
|
-
expects = options[:expects]
|
65
|
-
returns = options[:returns]
|
66
|
-
end
|
67
|
-
expects = canonical_signature(expects)
|
68
|
-
returns = canonical_signature(returns)
|
69
|
-
if expects
|
70
|
-
expects.each do |param|
|
71
|
-
klass = WS::BaseTypes.canonical_param_type_class(param)
|
72
|
-
klass = klass[0] if klass.is_a?(Array)
|
73
|
-
if klass.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects
|
74
|
-
raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects")
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
name = name.to_sym
|
79
|
-
public_name = public_api_method_name(name)
|
80
|
-
info = { :expects => expects, :returns => returns }
|
81
|
-
write_inheritable_hash("api_methods", name => info)
|
82
|
-
write_inheritable_hash("api_public_method_names", public_name => name)
|
83
|
-
end
|
84
|
-
|
85
|
-
# Whether the given method name is a service method on this API
|
86
|
-
def has_api_method?(name)
|
87
|
-
api_methods.has_key?(name)
|
88
|
-
end
|
89
|
-
|
90
|
-
# Whether the given public method name has a corresponding service method
|
91
|
-
# on this API
|
92
|
-
def has_public_api_method?(public_name)
|
93
|
-
api_public_method_names.has_key?(public_name)
|
94
|
-
end
|
95
|
-
|
96
|
-
# The corresponding public method name for the given service method name
|
97
|
-
def public_api_method_name(name)
|
98
|
-
if inflect_names
|
99
|
-
name.to_s.camelize
|
100
|
-
else
|
101
|
-
name.to_s
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# The corresponding service method name for the given public method name
|
106
|
-
def api_method_name(public_name)
|
107
|
-
api_public_method_names[public_name]
|
108
|
-
end
|
109
|
-
|
110
|
-
# A Hash containing all service methods on this API, and their
|
111
|
-
# associated metadata.
|
112
|
-
def api_methods
|
113
|
-
read_inheritable_attribute("api_methods") || {}
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
def api_public_method_names
|
118
|
-
read_inheritable_attribute("api_public_method_names") || {}
|
119
|
-
end
|
120
|
-
|
121
|
-
def validate_options(valid_option_keys, supplied_option_keys)
|
122
|
-
unknown_option_keys = supplied_option_keys - valid_option_keys
|
123
|
-
unless unknown_option_keys.empty?
|
124
|
-
raise(ActionWebServiceError, "Unknown options: #{unknown_option_keys}")
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def canonical_signature(signature)
|
129
|
-
return nil if signature.nil?
|
130
|
-
signature.map{|spec| WS::BaseTypes.canonical_param_type_spec(spec)}
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module WS
|
2
|
-
module Encoding
|
3
|
-
# Encoders operate on _foreign_ objects. That is, Ruby object
|
4
|
-
# instances that are the _marshaling format specific_ representation
|
5
|
-
# of objects. In other words, objects that have not yet been marshaled, but
|
6
|
-
# are in protocol-specific form (such as an AST or DOM element), and not
|
7
|
-
# native Ruby form.
|
8
|
-
class AbstractEncoding
|
9
|
-
def encode_rpc_call(method_name, params)
|
10
|
-
raise NotImplementedError
|
11
|
-
end
|
12
|
-
|
13
|
-
def decode_rpc_call(obj)
|
14
|
-
raise NotImplementedError
|
15
|
-
end
|
16
|
-
|
17
|
-
def encode_rpc_response(method_name, return_value)
|
18
|
-
raise NotImplementedError
|
19
|
-
end
|
20
|
-
|
21
|
-
def decode_rpc_response(obj)
|
22
|
-
raise NotImplementedError
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,90 +0,0 @@
|
|
1
|
-
require 'soap/processor'
|
2
|
-
require 'soap/mapping'
|
3
|
-
require 'soap/rpc/element'
|
4
|
-
|
5
|
-
module WS
|
6
|
-
module Encoding
|
7
|
-
class SoapRpcError < WSError
|
8
|
-
end
|
9
|
-
|
10
|
-
class SoapRpcEncoding < AbstractEncoding
|
11
|
-
attr_accessor :method_namespace
|
12
|
-
|
13
|
-
def initialize(method_namespace='')
|
14
|
-
@method_namespace = method_namespace
|
15
|
-
end
|
16
|
-
|
17
|
-
def encode_rpc_call(method_name, foreign_params)
|
18
|
-
qname = create_method_qname(method_name)
|
19
|
-
param_def = []
|
20
|
-
params = foreign_params.map do |p|
|
21
|
-
param_def << ['in', p.param.info.name, p.param.info.data.mapping]
|
22
|
-
[p.param.info.name, p.soap_object]
|
23
|
-
end
|
24
|
-
request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
|
25
|
-
request.set_param(params)
|
26
|
-
envelope = create_soap_envelope(request)
|
27
|
-
SOAP::Processor.marshal(envelope)
|
28
|
-
end
|
29
|
-
|
30
|
-
def decode_rpc_call(obj)
|
31
|
-
envelope = SOAP::Processor.unmarshal(obj)
|
32
|
-
unless envelope
|
33
|
-
raise(SoapRpcError, "Malformed SOAP request")
|
34
|
-
end
|
35
|
-
request = envelope.body.request
|
36
|
-
method_name = request.elename.name
|
37
|
-
params = request.collect do |key, value|
|
38
|
-
info = ParamInfo.new(key, nil, nil)
|
39
|
-
param = Param.new(nil, info)
|
40
|
-
Marshaling::SoapForeignObject.new(param, request[key])
|
41
|
-
end
|
42
|
-
[method_name, params]
|
43
|
-
end
|
44
|
-
|
45
|
-
def encode_rpc_response(method_name, return_value)
|
46
|
-
response = nil
|
47
|
-
qname = create_method_qname(method_name)
|
48
|
-
if return_value.nil?
|
49
|
-
response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
|
50
|
-
else
|
51
|
-
param = return_value.param
|
52
|
-
soap_object = return_value.soap_object
|
53
|
-
param_def = [['retval', 'return', param.info.data.mapping]]
|
54
|
-
if soap_object.is_a?(SOAP::SOAPFault)
|
55
|
-
response = soap_object
|
56
|
-
else
|
57
|
-
response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def)
|
58
|
-
response.retval = soap_object
|
59
|
-
end
|
60
|
-
end
|
61
|
-
envelope = create_soap_envelope(response)
|
62
|
-
SOAP::Processor.marshal(envelope)
|
63
|
-
end
|
64
|
-
|
65
|
-
def decode_rpc_response(obj)
|
66
|
-
envelope = SOAP::Processor.unmarshal(obj)
|
67
|
-
unless envelope
|
68
|
-
raise(SoapRpcError, "Malformed SOAP response")
|
69
|
-
end
|
70
|
-
method_name = envelope.body.request.elename.name
|
71
|
-
return_value = envelope.body.response
|
72
|
-
info = ParamInfo.new('return', nil, nil)
|
73
|
-
param = Param.new(nil, info)
|
74
|
-
return_value = Marshaling::SoapForeignObject.new(param, return_value)
|
75
|
-
[method_name, return_value]
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
def create_soap_envelope(body)
|
80
|
-
header = SOAP::SOAPHeader.new
|
81
|
-
body = SOAP::SOAPBody.new(body)
|
82
|
-
SOAP::SOAPEnvelope.new(header, body)
|
83
|
-
end
|
84
|
-
|
85
|
-
def create_method_qname(method_name)
|
86
|
-
XSD::QName.new(@method_namespace, method_name)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'xmlrpc/marshal'
|
2
|
-
|
3
|
-
module WS
|
4
|
-
module Encoding
|
5
|
-
class XmlRpcError < WSError
|
6
|
-
end
|
7
|
-
|
8
|
-
class XmlRpcEncoding < AbstractEncoding
|
9
|
-
def encode_rpc_call(method_name, params)
|
10
|
-
XMLRPC::Marshal.dump_call(method_name, *params)
|
11
|
-
end
|
12
|
-
|
13
|
-
def decode_rpc_call(obj)
|
14
|
-
method_name, params = XMLRPC::Marshal.load_call(obj) rescue nil
|
15
|
-
unless method_name && params
|
16
|
-
raise(XmlRpcError, "Malformed XML-RPC request")
|
17
|
-
end
|
18
|
-
i = 0
|
19
|
-
params = params.map do |value|
|
20
|
-
param = XmlRpcDecodedParam.new("param#{i}", value)
|
21
|
-
i += 1
|
22
|
-
param
|
23
|
-
end
|
24
|
-
[method_name, params]
|
25
|
-
end
|
26
|
-
|
27
|
-
def encode_rpc_response(method_name, return_value)
|
28
|
-
if return_value.nil?
|
29
|
-
XMLRPC::Marshal.dump_response(true)
|
30
|
-
else
|
31
|
-
XMLRPC::Marshal.dump_response(return_value)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def decode_rpc_response(obj)
|
36
|
-
return_value = XMLRPC::Marshal.load_response(obj) rescue nil
|
37
|
-
if return_value.nil?
|
38
|
-
raise(XmlRpcError, "Malformed XML-RPC response")
|
39
|
-
end
|
40
|
-
[nil, XmlRpcDecodedParam.new('return', return_value)]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class XmlRpcDecodedParam
|
45
|
-
attr :param
|
46
|
-
|
47
|
-
def initialize(name, value)
|
48
|
-
info = ParamInfo.new(name, value.class)
|
49
|
-
@param = Param.new(value, info)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,277 +0,0 @@
|
|
1
|
-
require 'soap/mapping'
|
2
|
-
require 'xsd/ns'
|
3
|
-
|
4
|
-
module WS
|
5
|
-
module Marshaling
|
6
|
-
SoapEncodingNS = 'http://schemas.xmlsoap.org/soap/encoding/'
|
7
|
-
|
8
|
-
class SoapError < WSError
|
9
|
-
end
|
10
|
-
|
11
|
-
class SoapMarshaler < AbstractMarshaler
|
12
|
-
attr :registry
|
13
|
-
attr_accessor :type_namespace
|
14
|
-
|
15
|
-
def initialize(type_namespace='')
|
16
|
-
@type_namespace = type_namespace
|
17
|
-
@registry = SOAP::Mapping::Registry.new
|
18
|
-
@spec2binding = {}
|
19
|
-
end
|
20
|
-
|
21
|
-
def marshal(param)
|
22
|
-
annotate_arrays(param.info.data, param.value)
|
23
|
-
if param.value.is_a?(Exception)
|
24
|
-
detail = SOAP::Mapping::SOAPException.new(param.value)
|
25
|
-
soap_obj = SOAP::SOAPFault.new(
|
26
|
-
SOAP::SOAPQName.new('%s:%s' % [SOAP::SOAPNamespaceTag, 'Server']),
|
27
|
-
SOAP::SOAPString.new(param.value.to_s),
|
28
|
-
SOAP::SOAPString.new(self.class.name),
|
29
|
-
SOAP::Mapping.obj2soap(detail))
|
30
|
-
else
|
31
|
-
soap_obj = SOAP::Mapping.obj2soap(param.value, @registry)
|
32
|
-
end
|
33
|
-
SoapForeignObject.new(param, soap_obj)
|
34
|
-
end
|
35
|
-
|
36
|
-
def unmarshal(obj)
|
37
|
-
param = obj.param
|
38
|
-
soap_object = obj.soap_object
|
39
|
-
soap_type = soap_object ? soap_object.type : nil
|
40
|
-
value = soap_object ? SOAP::Mapping.soap2obj(soap_object, @registry) : nil
|
41
|
-
param.value = value
|
42
|
-
param.info.type = value.class
|
43
|
-
mapping = @registry.find_mapped_soap_class(param.info.type) rescue nil
|
44
|
-
if soap_type && soap_type.name == 'Array' && soap_type.namespace == SoapEncodingNS
|
45
|
-
param.info.data = SoapBinding.new(self, soap_object.arytype, Array, mapping)
|
46
|
-
else
|
47
|
-
param.info.data = SoapBinding.new(self, soap_type, value.class, mapping)
|
48
|
-
end
|
49
|
-
param
|
50
|
-
end
|
51
|
-
|
52
|
-
def register_type(spec)
|
53
|
-
if @spec2binding.has_key?(spec)
|
54
|
-
return @spec2binding[spec]
|
55
|
-
end
|
56
|
-
|
57
|
-
klass = BaseTypes.canonical_param_type_class(spec)
|
58
|
-
if klass.is_a?(Array)
|
59
|
-
type_class = klass[0]
|
60
|
-
else
|
61
|
-
type_class = klass
|
62
|
-
end
|
63
|
-
|
64
|
-
type_binding = nil
|
65
|
-
if (mapping = @registry.find_mapped_soap_class(type_class) rescue nil)
|
66
|
-
qname = mapping[2] ? mapping[2][:type] : nil
|
67
|
-
qname ||= soap_base_type_name(mapping[0])
|
68
|
-
type_binding = SoapBinding.new(self, qname, type_class, mapping)
|
69
|
-
else
|
70
|
-
qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name))
|
71
|
-
@registry.add(type_class,
|
72
|
-
SOAP::SOAPStruct,
|
73
|
-
typed_struct_factory(type_class),
|
74
|
-
{ :type => qname })
|
75
|
-
mapping = @registry.find_mapped_soap_class(type_class)
|
76
|
-
type_binding = SoapBinding.new(self, qname, type_class, mapping)
|
77
|
-
end
|
78
|
-
|
79
|
-
array_binding = nil
|
80
|
-
if klass.is_a?(Array)
|
81
|
-
array_mapping = @registry.find_mapped_soap_class(Array) rescue nil
|
82
|
-
if (array_mapping && !array_mapping[1].is_a?(SoapTypedArrayFactory)) || array_mapping.nil?
|
83
|
-
@registry.set(Array,
|
84
|
-
SOAP::SOAPArray,
|
85
|
-
SoapTypedArrayFactory.new)
|
86
|
-
array_mapping = @registry.find_mapped_soap_class(Array)
|
87
|
-
end
|
88
|
-
qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name) + 'Array')
|
89
|
-
array_binding = SoapBinding.new(self, qname, Array, array_mapping, type_binding)
|
90
|
-
end
|
91
|
-
|
92
|
-
@spec2binding[spec] = array_binding ? array_binding : type_binding
|
93
|
-
@spec2binding[spec]
|
94
|
-
end
|
95
|
-
|
96
|
-
protected
|
97
|
-
def annotate_arrays(binding, value)
|
98
|
-
if binding.is_typed_array?
|
99
|
-
mark_typed_array(value, binding.element_binding.qname)
|
100
|
-
if binding.element_binding.is_custom_type?
|
101
|
-
value.each do |element|
|
102
|
-
annotate_arrays(register_type(element.class), element)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
elsif binding.is_typed_struct?
|
106
|
-
if binding.type_class.respond_to?(:members)
|
107
|
-
binding.type_class.members.each do |name, spec|
|
108
|
-
member_binding = register_type(spec)
|
109
|
-
member_value = value.send(name)
|
110
|
-
if member_binding.is_custom_type?
|
111
|
-
annotate_arrays(member_binding, member_value)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def mark_typed_array(array, qname)
|
119
|
-
(class << array; self; end).class_eval do
|
120
|
-
define_method(:arytype) do
|
121
|
-
qname
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def typed_struct_factory(type_class)
|
127
|
-
if Object.const_defined?('ActiveRecord')
|
128
|
-
if WS.derived_from?(ActiveRecord::Base, type_class)
|
129
|
-
qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name))
|
130
|
-
type_class.instance_variable_set('@qname', qname)
|
131
|
-
return SoapActiveRecordStructFactory.new
|
132
|
-
end
|
133
|
-
end
|
134
|
-
SOAP::Mapping::Registry::TypedStructFactory
|
135
|
-
end
|
136
|
-
|
137
|
-
def soap_type_name(type_name)
|
138
|
-
type_name.gsub(/::/, '..')
|
139
|
-
end
|
140
|
-
|
141
|
-
def soap_base_type_name(type)
|
142
|
-
xsd_type = type.ancestors.find{|c| c.const_defined? 'Type'}
|
143
|
-
xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
class SoapForeignObject
|
148
|
-
attr_accessor :param
|
149
|
-
attr_accessor :soap_object
|
150
|
-
|
151
|
-
def initialize(param, soap_object)
|
152
|
-
@param = param
|
153
|
-
@soap_object = soap_object
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
class SoapBinding
|
158
|
-
attr :qname
|
159
|
-
attr :type_class
|
160
|
-
attr :mapping
|
161
|
-
attr :element_binding
|
162
|
-
|
163
|
-
def initialize(marshaler, qname, type_class, mapping, element_binding=nil)
|
164
|
-
@marshaler = marshaler
|
165
|
-
@qname = qname
|
166
|
-
@type_class = type_class
|
167
|
-
@mapping = mapping
|
168
|
-
@element_binding = element_binding
|
169
|
-
end
|
170
|
-
|
171
|
-
def is_custom_type?
|
172
|
-
is_typed_array? || is_typed_struct?
|
173
|
-
end
|
174
|
-
|
175
|
-
def is_typed_array?
|
176
|
-
@mapping[1].is_a?(WS::Marshaling::SoapTypedArrayFactory)
|
177
|
-
end
|
178
|
-
|
179
|
-
def is_typed_struct?
|
180
|
-
@mapping[1] == SOAP::Mapping::Registry::TypedStructFactory || \
|
181
|
-
@mapping[1].is_a?(WS::Marshaling::SoapActiveRecordStructFactory)
|
182
|
-
end
|
183
|
-
|
184
|
-
def each_member(&block)
|
185
|
-
if is_typed_struct?
|
186
|
-
if @mapping[1] == SOAP::Mapping::Registry::TypedStructFactory
|
187
|
-
if @type_class.respond_to?(:members)
|
188
|
-
@type_class.members.each do |name, spec|
|
189
|
-
yield name, spec
|
190
|
-
end
|
191
|
-
end
|
192
|
-
elsif @mapping[1].is_a?(WS::Marshaling::SoapActiveRecordStructFactory)
|
193
|
-
@type_class.columns.each do |column|
|
194
|
-
yield column.name, column.klass
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def type_name
|
201
|
-
is_custom_type? ? @qname.name : nil
|
202
|
-
end
|
203
|
-
|
204
|
-
def qualified_type_name(ns=nil)
|
205
|
-
if is_custom_type?
|
206
|
-
"#{ns ? ns : @qname.namespace}:#{@qname.name}"
|
207
|
-
else
|
208
|
-
ns = XSD::NS.new
|
209
|
-
ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
|
210
|
-
xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')}
|
211
|
-
return ns.name(XSD::AnyTypeName) unless xsd_klass
|
212
|
-
ns.name(xsd_klass.const_get('Type'))
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
class SoapActiveRecordStructFactory < SOAP::Mapping::Factory
|
218
|
-
def obj2soap(soap_class, obj, info, map)
|
219
|
-
unless obj.is_a?(ActiveRecord::Base)
|
220
|
-
return nil
|
221
|
-
end
|
222
|
-
soap_obj = soap_class.new(obj.class.instance_variable_get('@qname'))
|
223
|
-
obj.class.columns.each do |column|
|
224
|
-
key = column.name.to_s
|
225
|
-
value = obj.send(key)
|
226
|
-
soap_obj[key] = SOAP::Mapping._obj2soap(value, map)
|
227
|
-
end
|
228
|
-
soap_obj
|
229
|
-
end
|
230
|
-
|
231
|
-
def soap2obj(obj_class, node, info, map)
|
232
|
-
unless node.type == obj_class.instance_variable_get('@qname')
|
233
|
-
return false
|
234
|
-
end
|
235
|
-
obj = obj_class.new
|
236
|
-
node.each do |key, value|
|
237
|
-
obj[key] = value.data
|
238
|
-
end
|
239
|
-
obj.instance_variable_set('@new_record', false)
|
240
|
-
return true, obj
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
class SoapTypedArrayFactory < SOAP::Mapping::Factory
|
245
|
-
def obj2soap(soap_class, obj, info, map)
|
246
|
-
unless obj.respond_to?(:arytype)
|
247
|
-
return nil
|
248
|
-
end
|
249
|
-
soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype)
|
250
|
-
mark_marshalled_obj(obj, soap_obj)
|
251
|
-
obj.each do |item|
|
252
|
-
child = SOAP::Mapping._obj2soap(item, map)
|
253
|
-
soap_obj.add(child)
|
254
|
-
end
|
255
|
-
soap_obj
|
256
|
-
end
|
257
|
-
|
258
|
-
def soap2obj(obj_class, node, info, map)
|
259
|
-
return false
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
module ActiveRecordSoapMarshallable
|
264
|
-
def allocate
|
265
|
-
obj = super
|
266
|
-
attrs = {}
|
267
|
-
self.columns.each{|c| attrs[c.name.to_s] = c.default}
|
268
|
-
obj.instance_variable_set('@attributes', attrs)
|
269
|
-
obj
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
if Object.const_defined?('ActiveRecord')
|
274
|
-
ActiveRecord::Base.extend(ActiveRecordSoapMarshallable)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|