actionwebservice 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|