summaryrefslogtreecommitdiff
path: root/lib/soap
diff options
context:
space:
mode:
authornahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-10-14 15:14:02 +0000
committernahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-10-14 15:14:02 +0000
commit9cba39a1a1b09f94a5d890e0ad6f4c74bb9f36bf (patch)
tree559f6780e94880fc3e7c37678fbe8b49ff0556d7 /lib/soap
parent0b841783b508c9bddb1c0117b1970fc7c350843b (diff)
* lib/soap/baseData.rb: Introduce SOAPType as the common ancestor of
SOAPBasetype and SOAPCompoundtype. * lib/soap/generator.rb, lib/soap/element.rb, lib/soap/encodingstyle/*: Encoding methods signature change. Pass SOAPGenerator as a parameter. * lib/soap/mapping/*, test/soap/marshal/test_marshal.rb: Refactoring for better marshalling/unmarshalling support. Now I think SOAP marshaller supports all kind of object graph which is supported by Ruby's original marshaller. Of course there could be bugs as always. Find it. :-) * lib/soap/rpc/standaloneServer.rb: Set severity threshould to INFO. DEBUG is too noisy. * lib/xsd/datatypes.rb: DateTime#of is obsoleted. Use DateTime#offset. * test/wsdl/emptycomplextype.wsdl, test/xsd/xmlschema.xml: Avoid useless warning. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4760 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/soap')
-rw-r--r--lib/soap/baseData.rb12
-rw-r--r--lib/soap/element.rb26
-rw-r--r--lib/soap/encodingstyle/aspDotNetHandler.rb23
-rw-r--r--lib/soap/encodingstyle/handler.rb4
-rw-r--r--lib/soap/encodingstyle/literalHandler.rb28
-rw-r--r--lib/soap/encodingstyle/soapHandler.rb71
-rw-r--r--lib/soap/generator.rb87
-rw-r--r--lib/soap/mapping/factory.rb91
-rw-r--r--lib/soap/mapping/mapping.rb10
-rw-r--r--lib/soap/mapping/registry.rb119
-rw-r--r--lib/soap/mapping/rubytypeFactory.rb377
-rw-r--r--lib/soap/marshal.rb2
-rw-r--r--lib/soap/rpc/standaloneServer.rb1
-rw-r--r--lib/soap/wsdlDriver.rb3
14 files changed, 505 insertions, 349 deletions
diff --git a/lib/soap/baseData.rb b/lib/soap/baseData.rb
index 30f3bce767..c175072e4d 100644
--- a/lib/soap/baseData.rb
+++ b/lib/soap/baseData.rb
@@ -41,9 +41,16 @@ end
###
+## Marker of SOAP/DM types.
+#
+module SOAPType; end
+
+
+###
## Mix-in module for SOAP base type instances.
#
module SOAPBasetype
+ include SOAPType
include SOAP
attr_accessor :encodingstyle
@@ -75,6 +82,7 @@ end
## Mix-in module for SOAP compound type instances.
#
module SOAPCompoundtype
+ include SOAPType
include SOAP
attr_accessor :encodingstyle
@@ -168,7 +176,7 @@ public
d
end
- def SOAPReference.create_refid(obj)
+ def self.create_refid(obj)
'id' << obj.__id__.to_s
end
end
@@ -597,7 +605,7 @@ public
data = retrieve(idxary[0, idxary.size - 1])
data[idxary.last] = value
- if value.is_a?(SOAPBasetype) || value.is_a?(SOAPCompoundtype)
+ if value.is_a?(SOAPType)
value.elename = value.elename.dup_name('item')
# Sync type
diff --git a/lib/soap/element.rb b/lib/soap/element.rb
index 640eafb0e4..561cb1b071 100644
--- a/lib/soap/element.rb
+++ b/lib/soap/element.rb
@@ -84,17 +84,17 @@ public
end
end
- def encode(buf, ns, attrs = {}, indent = '')
+ def encode(generator, ns, attrs = {})
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
name = ns.name(@elename)
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
yield(self.faultcode, false)
yield(self.faultstring, false)
yield(self.faultactor, false)
yield(self.detail, false) if self.detail
- SOAPGenerator.encode_tag_end(buf, name, indent, true)
+ generator.encode_tag_end(name, true)
end
end
@@ -112,9 +112,9 @@ public
@is_fault = is_fault
end
- def encode(buf, ns, attrs = {}, indent = '')
+ def encode(generator, ns, attrs = {})
name = ns.name(@elename)
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
if @is_fault
yield(@data, true)
else
@@ -122,7 +122,7 @@ public
yield(data, true)
end
end
- SOAPGenerator.encode_tag_end(buf, name, indent, true)
+ generator.encode_tag_end(name, true)
end
def root_node
@@ -160,7 +160,7 @@ public
@encodingstyle = encodingstyle || LiteralNamespace
end
- def encode(buf, ns, attrs = {}, indent = '')
+ def encode(generator, ns, attrs = {})
attrs.each do |key, value|
@content.attr[key] = value
end
@@ -185,13 +185,13 @@ class SOAPHeader < SOAPArray
@encodingstyle = nil
end
- def encode(buf, ns, attrs = {}, indent = '')
+ def encode(generator, ns, attrs = {})
name = ns.name(@elename)
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
@data.each do |data|
yield(data, true)
end
- SOAPGenerator.encode_tag_end(buf, name, indent, true)
+ generator.encode_tag_end(name, true)
end
def length
@@ -215,16 +215,16 @@ class SOAPEnvelope < XSD::NSDBase
@body = body
end
- def encode(buf, ns, attrs = {}, indent = '')
+ def encode(generator, ns, attrs = {})
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace,
SOAPNamespaceTag)
name = ns.name(@elename)
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
yield(@header, true) if @header and @header.length > 0
yield(@body, true)
- SOAPGenerator.encode_tag_end(buf, name, indent, true)
+ generator.encode_tag_end(name, true)
end
end
diff --git a/lib/soap/encodingstyle/aspDotNetHandler.rb b/lib/soap/encodingstyle/aspDotNetHandler.rb
index fdce42a48a..b00084e3a9 100644
--- a/lib/soap/encodingstyle/aspDotNetHandler.rb
+++ b/lib/soap/encodingstyle/aspDotNetHandler.rb
@@ -38,7 +38,7 @@ class ASPDotNetHandler < Handler
###
## encode interface.
#
- def encode_data(buf, ns, qualified, data, parent, indent = '')
+ def encode_data(generator, ns, qualified, data, parent)
attrs = {}
name = if qualified and data.elename.namespace
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
@@ -49,17 +49,16 @@ class ASPDotNetHandler < Handler
case data
when SOAPRawString
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << data.to_s
+ generator.encode_tag(name, attrs)
+ generator.encode_rawstring(data.to_s)
when XSD::XSDString
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << SOAPGenerator.encode_str(@charset ?
- XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
+ generator.encode_tag(name, attrs)
+ generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << SOAPGenerator.encode_str(data.to_s)
+ generator.encode_tag(name, attrs)
+ generator.encode_string(data.to_s)
when SOAPStruct
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
data.each do |key, value|
if !value.elename.namespace
value.elename.namespace = data.elename.namespace
@@ -67,7 +66,7 @@ class ASPDotNetHandler < Handler
yield(value, true)
end
when SOAPArray
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
data.traverse do |child, *rank|
data.position = nil
yield(child, true)
@@ -78,14 +77,14 @@ yle.")
end
end
- def encode_data_end(buf, ns, qualified, data, parent, indent = "")
+ def encode_data_end(generator, ns, qualified, data, parent)
name = if qualified and data.elename.namespace
ns.name(data.elename)
else
data.elename.name
end
cr = data.is_a?(SOAPCompoundtype)
- SOAPGenerator.encode_tag_end(buf, name, indent, cr)
+ generator.encode_tag_end(name, cr)
end
diff --git a/lib/soap/encodingstyle/handler.rb b/lib/soap/encodingstyle/handler.rb
index 1ab9d86ec5..2cbbd893d8 100644
--- a/lib/soap/encodingstyle/handler.rb
+++ b/lib/soap/encodingstyle/handler.rb
@@ -69,11 +69,11 @@ class Handler
## encode interface.
#
# Returns a XML instance as a string.
- def encode_data(buf, ns, qualified, data, parent, indent)
+ def encode_data(generator, ns, qualified, data, parent)
raise NotImplementError.new('Method encode_data must be defined in derived class.')
end
- def encode_data_end(buf, ns, qualified, data, parent, indent)
+ def encode_data_end(generator, ns, qualified, data, parent)
raise NotImplementError.new('Method encode_data must be defined in derived class.')
end
diff --git a/lib/soap/encodingstyle/literalHandler.rb b/lib/soap/encodingstyle/literalHandler.rb
index b5d0d464d7..5ff0e5dd66 100644
--- a/lib/soap/encodingstyle/literalHandler.rb
+++ b/lib/soap/encodingstyle/literalHandler.rb
@@ -37,7 +37,7 @@ class LiteralHandler < Handler
###
## encode interface.
#
- def encode_data(buf, ns, qualified, data, parent, indent = '')
+ def encode_data(generator, ns, qualified, data, parent)
attrs = {}
name = if qualified and data.elename.namespace
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
@@ -48,31 +48,29 @@ class LiteralHandler < Handler
case data
when SOAPRawString
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << data.to_s
+ generator.encode_tag(name, attrs)
+ generator.encode_rawstring(data.to_s)
when XSD::XSDString
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << SOAPGenerator.encode_str(@charset ?
- XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
+ generator.encode_tag(name, attrs)
+ generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << SOAPGenerator.encode_str(data.to_s)
+ generator.encode_tag(name, attrs)
+ generator.encode_string(data.to_s)
when SOAPStruct
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
data.each do |key, value|
value.elename.namespace = data.elename.namespace if !value.elename.namespace
yield(value, true)
end
when SOAPArray
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
data.traverse do |child, *rank|
data.position = nil
yield(child, true)
end
when SOAPElement
- SOAPGenerator.encode_tag(buf, name, attrs.update(data.extraattr),
- indent)
- buf << data.text if data.text
+ generator.encode_tag(name, attrs.update(data.extraattr))
+ generator.encode_rawstring(data.text) if data.text
data.each do |key, value|
value.elename.namespace = data.elename.namespace if !value.elename.namespace
#yield(value, data.qualified)
@@ -83,13 +81,13 @@ class LiteralHandler < Handler
end
end
- def encode_data_end(buf, ns, qualified, data, parent, indent)
+ def encode_data_end(generator, ns, qualified, data, parent)
name = if qualified and data.elename.namespace
ns.name(data.elename)
else
data.elename.name
end
- SOAPGenerator.encode_tag_end(buf, name, indent)
+ generator.encode_tag_end(name)
end
diff --git a/lib/soap/encodingstyle/soapHandler.rb b/lib/soap/encodingstyle/soapHandler.rb
index b1b5072e49..85d8642b8c 100644
--- a/lib/soap/encodingstyle/soapHandler.rb
+++ b/lib/soap/encodingstyle/soapHandler.rb
@@ -40,8 +40,8 @@ class SOAPHandler < Handler
###
## encode interface.
#
- def encode_data(buf, ns, qualified, data, parent, indent = '')
- attrs = encode_attrs(ns, qualified, data, parent)
+ def encode_data(generator, ns, qualified, data, parent)
+ attrs = encode_attrs(generator, ns, data, parent)
if parent && parent.is_a?(SOAPArray) && parent.position
attrs[ns.name(AttrPositionName)] = '[' << parent.position.join(',') << ']'
@@ -55,32 +55,26 @@ class SOAPHandler < Handler
name = data.elename.name
end
- if data.respond_to?(:encode)
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- return data.encode(buf, ns, attrs, indent)
- end
-
case data
when SOAPReference
attrs['href'] = '#' << data.refid
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
when SOAPRawString
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << data.to_s
+ generator.encode_tag(name, attrs)
+ generator.encode_rawstring(data.to_s)
when XSD::XSDString
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << SOAPGenerator.encode_str(@charset ?
- XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
+ generator.encode_tag(name, attrs)
+ generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
- buf << SOAPGenerator.encode_str(data.to_s)
+ generator.encode_tag(name, attrs)
+ generator.encode_string(data.to_s)
when SOAPStruct
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
data.each do |key, value|
yield(value, false)
end
when SOAPArray
- SOAPGenerator.encode_tag(buf, name, attrs, indent)
+ generator.encode_tag(name, attrs)
data.traverse do |child, *rank|
data.position = data.sparse ? rank : nil
yield(child, false)
@@ -91,14 +85,14 @@ class SOAPHandler < Handler
end
end
- def encode_data_end(buf, ns, qualified, data, parent, indent = '')
+ def encode_data_end(generator, ns, qualified, data, parent)
name = if qualified and data.elename.namespace
ns.name(data.elename)
else
data.elename.name
end
cr = data.is_a?(SOAPCompoundtype)
- SOAPGenerator.encode_tag_end(buf, name, indent, cr)
+ generator.encode_tag_end(name, cr)
end
@@ -292,7 +286,7 @@ private
content_typename(data.arytype.name) << '[' << data.size.join(',') << ']')
end
- def encode_attrs(ns, qualified, data, parent)
+ def encode_attrs(generator, ns, data, parent)
return {} if data.is_a?(SOAPReference)
attrs = {}
@@ -330,7 +324,7 @@ private
data.extraattr.each do |key, value|
SOAPGenerator.assign_ns(attrs, ns, key.namespace)
- attrs[ns.name(key)] = value # ns.name(value) ?
+ attrs[ns.name(key)] = encode_attr_value(generator, ns, key, value)
end
if data.id
attrs['id'] = data.id
@@ -338,6 +332,17 @@ private
attrs
end
+ def encode_attr_value(generator, ns, qname, value)
+ if value.is_a?(SOAPType)
+ refid = SOAPReference.create_refid(value)
+ value.id = refid
+ generator.add_reftarget(qname.name, value)
+ '#' + refid
+ else
+ value.to_s
+ end
+ end
+
def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr)
if parent.class == SOAPBody
# Unqualified name is allowed here.
@@ -423,11 +428,13 @@ private
end
if (klass = TypeMap[type])
- klass.decode(elename)
- else
- # Unknown type... Struct or String
- SOAPUnknown.new(self, elename, type, extraattr)
+ node = klass.decode(elename)
+ node.extraattr.update(extraattr)
+ return node
end
+
+ # Unknown type... Struct or String
+ SOAPUnknown.new(self, elename, type, extraattr)
end
def decode_textbuf(node)
@@ -508,12 +515,22 @@ private
id = value
next
end
- extraattr[qname] = value
+ extraattr[qname] = decode_attr_value(ns, qname, value)
end
return is_nil, type, arytype, root, offset, position, href, id, extraattr
end
+ def decode_attr_value(ns, qname, value)
+ if /\A#/ =~ value
+ o = SOAPReference.new(value)
+ @refpool << o
+ o
+ else
+ value
+ end
+ end
+
def decode_arypos(position)
/^\[(.+)\]$/ =~ position
$1.split(',').collect { |s| s.to_i }
@@ -524,7 +541,7 @@ private
while !@refpool.empty? && count > 0
@refpool = @refpool.find_all { |ref|
o = @idpool.find { |item|
- ('#' << item.id == ref.refid)
+ '#' + item.id == ref.refid
}
unless o
raise EncodingStyleError.new("Unresolved reference: #{ ref.refid }.")
diff --git a/lib/soap/generator.rb b/lib/soap/generator.rb
index 6707aef195..e0ac484c42 100644
--- a/lib/soap/generator.rb
+++ b/lib/soap/generator.rb
@@ -39,7 +39,6 @@ public
attr_accessor :charset
attr_accessor :default_encodingstyle
attr_accessor :generate_explicit_type
- attr_accessor :pretty
def initialize(opt = {})
@reftarget = nil
@@ -48,37 +47,38 @@ public
@default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
@generate_explicit_type =
opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true
- @pretty = true # opt[:pretty]
+ @buf = @indent = @curr = nil
end
def generate(obj, io = nil)
+ @buf = io || ''
+ @indent = ''
+
prologue
@handlers.each do |uri, handler|
handler.encode_prologue
end
- io = '' if io.nil?
-
ns = XSD::NS.new
- io << xmldecl
- encode_data(io, ns, true, obj, nil, 0)
+ @buf << xmldecl
+ encode_data(ns, true, obj, nil)
@handlers.each do |uri, handler|
handler.encode_epilogue
end
epilogue
- io
+ @buf
end
- def encode_data(buf, ns, qualified, obj, parent, indent)
+ def encode_data(ns, qualified, obj, parent)
if obj.is_a?(SOAPEnvelopeElement)
- encode_element(buf, ns, qualified, obj, parent, indent)
+ encode_element(ns, qualified, obj, parent)
return
end
if @reftarget && !obj.precedents.empty?
- @reftarget.add(obj.elename.name, obj)
+ add_reftarget(obj.elename.name, obj)
ref = SOAPReference.new
ref.elename.name = obj.elename.name
ref.__setobj__(obj)
@@ -102,22 +102,29 @@ public
raise FormatEncodeError.new("Element name not defined: #{ obj }.")
end
- indent_str = ' ' * indent
- child_indent = @pretty ? indent + 2 : indent
- handler.encode_data(buf, ns, qualified, obj, parent, indent_str) do |child, child_q|
- encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent)
+ handler.encode_data(self, ns, qualified, obj, parent) do |child, child_q|
+ indent_backup, @indent = @indent, @indent + ' '
+ encode_data(ns.clone_ns, child_q, child, obj)
+ @indent = indent_backup
+ end
+ handler.encode_data_end(self, ns, qualified, obj, parent)
+ end
+
+ def add_reftarget(name, node)
+ unless @reftarget
+ raise FormatEncodeError.new("Reftarget is not defined.")
end
- handler.encode_data_end(buf, ns, qualified, obj, parent, indent_str)
+ @reftarget.add(name, node)
end
- def encode_element(buf, ns, qualified, obj, parent, indent)
- indent_str = ' ' * indent
- child_indent = @pretty ? indent + 2 : indent
+ def encode_element(ns, qualified, obj, parent)
attrs = {}
if obj.is_a?(SOAPBody)
@reftarget = obj
- obj.encode(buf, ns, attrs, indent_str) do |child, child_q|
- encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent)
+ obj.encode(self, ns, attrs) do |child, child_q|
+ indent_backup, @indent = @indent, @indent + ' '
+ encode_data(ns.clone_ns, child_q, child, obj)
+ @indent = indent_backup
end
@reftarget = nil
else
@@ -129,39 +136,38 @@ public
SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag)
end
end
- obj.encode(buf, ns, attrs, indent_str) do |child, child_q|
- encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent)
+ obj.encode(self, ns, attrs) do |child, child_q|
+ indent_backup, @indent = @indent, @indent + ' '
+ encode_data(ns.clone_ns, child_q, child, obj)
+ @indent = indent_backup
end
end
end
- def self.assign_ns(attrs, ns, namespace, tag = nil)
- unless ns.assigned?(namespace)
- tag = ns.assign(namespace, tag)
- attrs['xmlns:' << tag] = namespace
- end
- end
-
- def self.encode_tag(buf, elename, attrs = nil, indent = '')
+ def encode_tag(elename, attrs = nil)
if attrs
- buf << "\n#{ indent }<#{ elename }" <<
+ @buf << "\n#{ @indent }<#{ elename }" <<
attrs.collect { |key, value|
%Q[ #{ key }="#{ value }"]
}.join <<
'>'
else
- buf << "\n#{ indent }<#{ elename }>"
+ @buf << "\n#{ @indent }<#{ elename }>"
end
end
- def self.encode_tag_end(buf, elename, indent = '', cr = nil)
+ def encode_tag_end(elename, cr = nil)
if cr
- buf << "\n#{ indent }</#{ elename }>"
+ @buf << "\n#{ @indent }</#{ elename }>"
else
- buf << "</#{ elename }>"
+ @buf << "</#{ elename }>"
end
end
+ def encode_rawstring(str)
+ @buf << str
+ end
+
EncodeMap = {
'&' => '&amp;',
'<' => '&lt;',
@@ -171,8 +177,15 @@ public
"\r" => '&#xd;'
}
EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]")
- def self.encode_str(str)
- str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] }
+ def encode_string(str)
+ @buf << str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] }
+ end
+
+ def self.assign_ns(attrs, ns, namespace, tag = nil)
+ if namespace and !ns.assigned?(namespace)
+ tag = ns.assign(namespace, tag)
+ attrs['xmlns:' << tag] = namespace
+ end
end
private
diff --git a/lib/soap/mapping/factory.rb b/lib/soap/mapping/factory.rb
index 2e5ddc1f15..6a34da55a8 100644
--- a/lib/soap/mapping/factory.rb
+++ b/lib/soap/mapping/factory.rb
@@ -24,6 +24,10 @@ module Mapping
class Factory
include TraverseSupport
+ def initialize
+ # nothing to do
+ end
+
def obj2soap(soap_class, obj, info, map)
raise NotImplementError.new
# return soap_obj
@@ -48,24 +52,13 @@ class Factory
end
end
- def set_instance_vars(obj, values)
- values.each do |name, value|
- setter = name + "="
- if obj.respond_to?(setter)
- obj.__send__(setter, value)
- else
- obj.instance_eval("@#{ name } = value")
- end
- end
- end
-
def setiv2obj(obj, node, map)
return if node.nil?
vars = {}
node.each do |name, value|
vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
end
- set_instance_vars(obj, vars)
+ Mapping.set_instance_vars(obj, vars)
end
def setiv2soap(node, obj, map)
@@ -76,13 +69,6 @@ class Factory
end
end
- def addiv2soap(node, obj, map)
- return if obj.instance_variables.empty?
- ivars = SOAPStruct.new # Undefined type.
- setiv2soap(ivars, obj, map)
- node.add('ivars', ivars)
- end
-
# It breaks Thread.current[:SOAPMarshalDataKey].
def mark_marshalled_obj(obj, soap_obj)
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
@@ -103,14 +89,21 @@ class Factory
end
class StringFactory_ < Factory
+ def initialize(allow_original_mapping = false)
+ super()
+ @allow_original_mapping = allow_original_mapping
+ end
+
def obj2soap(soap_class, obj, info, map)
+ if !@allow_original_mapping and !obj.instance_variables.empty?
+ return nil
+ end
begin
- if XSD::Charset.is_ces(obj, $KCODE)
- encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding)
- soap_obj = soap_class.new(encoded)
- else
- return nil
+ unless XSD::Charset.is_ces(obj, $KCODE)
+ return nil
end
+ encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding)
+ soap_obj = soap_class.new(encoded)
rescue XSD::ValueSpaceError
return nil
end
@@ -119,14 +112,24 @@ class StringFactory_ < Factory
end
def soap2obj(obj_class, node, info, map)
- obj = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding, $KCODE)
+ obj = create_empty_object(obj_class)
+ decoded = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding, $KCODE)
+ obj.replace(decoded)
mark_unmarshalled_obj(node, obj)
return true, obj
end
end
class BasetypeFactory_ < Factory
+ def initialize(allow_original_mapping = false)
+ super()
+ @allow_original_mapping = allow_original_mapping
+ end
+
def obj2soap(soap_class, obj, info, map)
+ if !@allow_original_mapping and !obj.instance_variables.empty?
+ return nil
+ end
soap_obj = nil
begin
soap_obj = soap_class.new(obj)
@@ -145,7 +148,16 @@ class BasetypeFactory_ < Factory
end
class DateTimeFactory_ < Factory
+ def initialize(allow_original_mapping = false)
+ super()
+ @allow_original_mapping = allow_original_mapping
+ end
+
def obj2soap(soap_class, obj, info, map)
+ if !@allow_original_mapping and
+ Time === obj and !obj.instance_variables.empty?
+ return nil
+ end
soap_obj = nil
begin
soap_obj = soap_class.new(obj)
@@ -176,6 +188,7 @@ end
class Base64Factory_ < Factory
def obj2soap(soap_class, obj, info, map)
+ return nil unless obj.instance_variables.empty?
soap_obj = soap_class.new(obj)
mark_marshalled_obj(obj, soap_obj) if soap_obj
soap_obj
@@ -189,9 +202,17 @@ class Base64Factory_ < Factory
end
class ArrayFactory_ < Factory
+ def initialize(allow_original_mapping = false)
+ super()
+ @allow_original_mapping = allow_original_mapping
+ end
+
# [[1], [2]] is converted to Array of Array, not 2-D Array.
# To create M-D Array, you must call Mapping.ary2md.
def obj2soap(soap_class, obj, info, map)
+ if !@allow_original_mapping and !obj.instance_variables.empty?
+ return nil
+ end
arytype = Mapping.obj2element(obj)
if arytype.name
arytype.namespace ||= RubyTypeNamespace
@@ -217,7 +238,15 @@ class ArrayFactory_ < Factory
end
class TypedArrayFactory_ < Factory
+ def initialize(allow_original_mapping = false)
+ super()
+ @allow_original_mapping = allow_original_mapping
+ end
+
def obj2soap(soap_class, obj, info, map)
+ if !@allow_original_mapping and !obj.instance_variables.empty?
+ return nil
+ end
arytype = info[:type] || info[0]
param = SOAPArray.new(ValueArrayName, 1, arytype)
mark_marshalled_obj(obj, param)
@@ -271,9 +300,17 @@ end
MapQName = XSD::QName.new(ApacheSOAPTypeNamespace, 'Map')
class HashFactory_ < Factory
+ def initialize(allow_original_mapping = false)
+ super()
+ @allow_original_mapping = allow_original_mapping
+ end
+
def obj2soap(soap_class, obj, info, map)
- if obj.default or
- (obj.respond_to?(:default_proc) and obj.default_proc)
+ if !@allow_original_mapping and !obj.instance_variables.empty?
+ return nil
+ end
+ if !obj.default.nil? or
+ (obj.respond_to?(:default_proc) and obj.default_proc)
return nil
end
param = SOAPStruct.new(MapQName)
diff --git a/lib/soap/mapping/mapping.rb b/lib/soap/mapping/mapping.rb
index 19eca5dab0..f660c2c63f 100644
--- a/lib/soap/mapping/mapping.rb
+++ b/lib/soap/mapping/mapping.rb
@@ -129,6 +129,16 @@ module Mapping
return registry.soap2obj(node.class, node)
end
+ def self.set_instance_vars(obj, values)
+ values.each do |name, value|
+ setter = name + "="
+ if obj.respond_to?(setter)
+ obj.__send__(setter, value)
+ else
+ obj.instance_eval("@#{ name } = value")
+ end
+ end
+ end
# Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
# Caution: '.' is not allowed here.
diff --git a/lib/soap/mapping/registry.rb b/lib/soap/mapping/registry.rb
index 568f34ac3e..bdf14d4fc6 100644
--- a/lib/soap/mapping/registry.rb
+++ b/lib/soap/mapping/registry.rb
@@ -39,6 +39,8 @@ module MappedException; end
RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType')
+RubyExtendName = XSD::QName.new(RubyTypeInstanceNamespace, 'extends')
+RubyIVarName = XSD::QName.new(RubyTypeInstanceNamespace, 'ivars')
# Inner class to pass an exception.
@@ -217,11 +219,11 @@ class Registry
[::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::String, ::SOAP::SOAPString, StringFactory],
- [::DateTime, ::SOAP::SOAPDateTime, BasetypeFactory],
- [::Date, ::SOAP::SOAPDateTime, BasetypeFactory],
- [::Date, ::SOAP::SOAPDate, BasetypeFactory],
- [::Time, ::SOAP::SOAPDateTime, BasetypeFactory],
- [::Time, ::SOAP::SOAPTime, BasetypeFactory],
+ [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
+ [::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
+ [::Date, ::SOAP::SOAPDate, DateTimeFactory],
+ [::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
+ [::Time, ::SOAP::SOAPTime, DateTimeFactory],
[::Float, ::SOAP::SOAPDouble, BasetypeFactory,
{:derived_class => true}],
[::Float, ::SOAP::SOAPFloat, BasetypeFactory,
@@ -261,11 +263,11 @@ class Registry
[::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::String, ::SOAP::SOAPString, StringFactory],
- [::DateTime, ::SOAP::SOAPDateTime, BasetypeFactory],
- [::Date, ::SOAP::SOAPDateTime, BasetypeFactory],
- [::Date, ::SOAP::SOAPDate, BasetypeFactory],
- [::Time, ::SOAP::SOAPDateTime, BasetypeFactory],
- [::Time, ::SOAP::SOAPTime, BasetypeFactory],
+ [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
+ [::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
+ [::Date, ::SOAP::SOAPDate, DateTimeFactory],
+ [::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
+ [::Time, ::SOAP::SOAPTime, DateTimeFactory],
[::Float, ::SOAP::SOAPDouble, BasetypeFactory,
{:derived_class => true}],
[::Float, ::SOAP::SOAPFloat, BasetypeFactory,
@@ -304,18 +306,18 @@ class Registry
@config = config
@map = Map.new(self)
if @config[:allow_original_mapping]
- allow_original_mapping = true
+ @allow_original_mapping = true
@map.init(RubyOriginalMap)
else
- allow_original_mapping = false
+ @allow_original_mapping = false
@map.init(SOAPBaseMap)
end
- allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
+ @allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
@config[:allow_untyped_struct] : true
@rubytype_factory = RubytypeFactory.new(
- :allow_untyped_struct => allow_untyped_struct,
- :allow_original_mapping => allow_original_mapping
+ :allow_untyped_struct => @allow_untyped_struct,
+ :allow_original_mapping => @allow_original_mapping
)
@default_factory = @rubytype_factory
@excn_handler_obj2soap = nil
@@ -329,8 +331,47 @@ class Registry
# This mapping registry ignores type hint.
def obj2soap(klass, obj, type = nil)
+ soap = _obj2soap(klass, obj, type)
+ if @allow_original_mapping
+ addextend2soap(soap, obj)
+ end
+ soap
+ end
+
+ def soap2obj(klass, node)
+ obj = _soap2obj(klass, node)
+ if @allow_original_mapping
+ addextend2obj(obj, node.extraattr[RubyExtendName])
+ addiv2obj(obj, node.extraattr[RubyIVarName])
+ end
+ obj
+ end
+
+ def default_factory=(factory)
+ @default_factory = factory
+ end
+
+ def excn_handler_obj2soap=(handler)
+ @excn_handler_obj2soap = handler
+ end
+
+ def excn_handler_soap2obj=(handler)
+ @excn_handler_soap2obj = handler
+ end
+
+ def find_mapped_soap_class(obj_class)
+ @map.find_mapped_soap_class(obj_class)
+ end
+
+ def find_mapped_obj_class(soap_class)
+ @map.find_mapped_obj_class(soap_class)
+ end
+
+private
+
+ def _obj2soap(klass, obj, type)
ret = nil
- if obj.is_a?(SOAPStruct) || obj.is_a?(SOAPArray)
+ if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
obj.replace do |ele|
Mapping._obj2soap(ele, self)
end
@@ -344,18 +385,17 @@ class Registry
rescue MappingError
end
return ret if ret
-
if @excn_handler_obj2soap
ret = @excn_handler_obj2soap.call(obj) { |yield_obj|
Mapping._obj2soap(yield_obj, self)
}
end
return ret if ret
-
raise MappingError.new("Cannot map #{ klass.name } to SOAP/OM.")
end
- def soap2obj(klass, node)
+ # Might return nil as a mapping result.
+ def _soap2obj(klass, node)
if node.extraattr.key?(RubyTypeName)
conv, obj = @rubytype_factory.soap2obj(klass, node, nil, self)
return obj if conv
@@ -369,34 +409,43 @@ class Registry
if @excn_handler_soap2obj
begin
return @excn_handler_soap2obj.call(node) { |yield_node|
- Mapping._soap2obj(yield_node, self)
- }
+ Mapping._soap2obj(yield_node, self)
+ }
rescue Exception
end
end
-
raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
end
- def default_factory=(factory)
- @default_factory = factory
- end
-
- def excn_handler_obj2soap=(handler)
- @excn_handler_obj2soap = handler
+ def addiv2obj(obj, attr)
+ return unless attr
+ vars = {}
+ attr.__getobj__.each do |name, value|
+ vars[name] = Mapping._soap2obj(value, self)
+ end
+ Mapping.set_instance_vars(obj, vars)
end
- def excn_handler_soap2obj=(handler)
- @excn_handler_soap2obj = handler
+ def addextend2obj(obj, attr)
+ return unless attr
+ attr.split(/ /).reverse_each do |mstr|
+ obj.extend(Mapping.class_from_name(mstr))
+ end
end
- def find_mapped_soap_class(obj_class)
- @map.find_mapped_soap_class(obj_class)
+ def addextend2soap(node, obj)
+ return if obj.is_a?(Symbol) or obj.is_a?(Fixnum)
+ list = (class << obj; self; end).ancestors - obj.class.ancestors
+ unless list.empty?
+ node.extraattr[RubyExtendName] = list.collect { |c|
+ if c.name.empty?
+ raise TypeError.new("singleton can't be dumped #{ obj }")
+ end
+ c.name
+ }.join(" ")
+ end
end
- def find_mapped_obj_class(soap_class)
- @map.find_mapped_obj_class(soap_class)
- end
end
diff --git a/lib/soap/mapping/rubytypeFactory.rb b/lib/soap/mapping/rubytypeFactory.rb
index 0a3f502dfe..3ebb799220 100644
--- a/lib/soap/mapping/rubytypeFactory.rb
+++ b/lib/soap/mapping/rubytypeFactory.rb
@@ -22,22 +22,28 @@ module Mapping
class RubytypeFactory < Factory
- TYPE_STRING = 'String'
- TYPE_ARRAY = 'Array'
- TYPE_REGEXP = 'Regexp'
- TYPE_RANGE = 'Range'
- TYPE_CLASS = 'Class'
- TYPE_MODULE = 'Module'
- TYPE_SYMBOL = 'Symbol'
- TYPE_STRUCT = 'Struct'
- TYPE_HASH = 'Map'
-
+ TYPE_STRING = XSD::QName.new(RubyTypeNamespace, 'String')
+ TYPE_TIME = XSD::QName.new(RubyTypeNamespace, 'Time')
+ TYPE_ARRAY = XSD::QName.new(RubyTypeNamespace, 'Array')
+ TYPE_REGEXP = XSD::QName.new(RubyTypeNamespace, 'Regexp')
+ TYPE_RANGE = XSD::QName.new(RubyTypeNamespace, 'Range')
+ TYPE_CLASS = XSD::QName.new(RubyTypeNamespace, 'Class')
+ TYPE_MODULE = XSD::QName.new(RubyTypeNamespace, 'Module')
+ TYPE_SYMBOL = XSD::QName.new(RubyTypeNamespace, 'Symbol')
+ TYPE_STRUCT = XSD::QName.new(RubyTypeNamespace, 'Struct')
+ TYPE_HASH = XSD::QName.new(RubyTypeNamespace, 'Map')
+
def initialize(config = {})
@config = config
@allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
@config[:allow_untyped_struct] : true
@allow_original_mapping = @config.key?(:allow_original_mapping) ?
@config[:allow_original_mapping] : false
+ @string_factory = StringFactory_.new(true)
+ @basetype_factory = BasetypeFactory_.new(true)
+ @datetime_factory = DateTimeFactory_.new(true)
+ @array_factory = ArrayFactory_.new(true)
+ @hash_factory = HashFactory_.new(true)
end
def obj2soap(soap_class, obj, info, map)
@@ -47,48 +53,83 @@ class RubytypeFactory < Factory
unless @allow_original_mapping
return nil
end
- unless XSD::Charset.is_ces(obj, $KCODE)
+ param = @string_factory.obj2soap(SOAPString, obj, info, map)
+ if obj.class != String
+ param.extraattr[RubyTypeName] = obj.class.name
+ end
+ addiv2soapattr(param, obj, map)
+ when Time
+ unless @allow_original_mapping
return nil
end
- encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding)
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_STRING))
- mark_marshalled_obj(obj, param)
- param.add('string', SOAPString.new(encoded))
- if obj.class != String
+ param = @datetime_factory.obj2soap(SOAPDateTime, obj, info, map)
+ if obj.class != Time
param.extraattr[RubyTypeName] = obj.class.name
end
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Array
unless @allow_original_mapping
return nil
end
- arytype = Mapping.obj2element(obj)
- if arytype.name
- arytype.namespace ||= RubyTypeNamespace
- else
- arytype = XSD::AnyTypeName
+ param = @array_factory.obj2soap(nil, obj, info, map)
+ if obj.class != Array
+ param.extraattr[RubyTypeName] = obj.class.name
end
- if obj.instance_variables.empty?
- param = SOAPArray.new(ValueArrayName, 1, arytype)
- mark_marshalled_obj(obj, param)
- obj.each do |var|
- param.add(Mapping._obj2soap(var, map))
- end
- else
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_ARRAY))
- mark_marshalled_obj(obj, param)
- ary = SOAPArray.new(ValueArrayName, 1, arytype)
- obj.each do |var|
- ary.add(Mapping._obj2soap(var, map))
- end
- param.add('array', ary)
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
+ when NilClass
+ unless @allow_original_mapping
+ return nil
end
- if obj.class != Array
+ param = @basetype_factory.obj2soap(SOAPNil, obj, info, map)
+ addiv2soapattr(param, obj, map)
+ when FalseClass, TrueClass
+ unless @allow_original_mapping
+ return nil
+ end
+ param = @basetype_factory.obj2soap(SOAPBoolean, obj, info, map)
+ addiv2soapattr(param, obj, map)
+ when Integer
+ unless @allow_original_mapping
+ return nil
+ end
+ param = @basetype_factory.obj2soap(SOAPInt, obj, info, map)
+ param ||= @basetype_factory.obj2soap(SOAPInteger, obj, info, map)
+ param ||= @basetype_factory.obj2soap(SOAPDecimal, obj, info, map)
+ addiv2soapattr(param, obj, map)
+ when Float
+ unless @allow_original_mapping
+ return nil
+ end
+ param = @basetype_factory.obj2soap(SOAPDouble, obj, info, map)
+ if obj.class != Float
param.extraattr[RubyTypeName] = obj.class.name
end
+ addiv2soapattr(param, obj, map)
+ when Hash
+ unless @allow_original_mapping
+ return nil
+ end
+ if obj.respond_to?(:default_proc) && obj.default_proc
+ raise TypeError.new("cannot dump hash with default proc")
+ end
+ param = SOAPStruct.new(TYPE_HASH)
+ mark_marshalled_obj(obj, param)
+ if obj.class != Hash
+ param.extraattr[RubyTypeName] = obj.class.name
+ end
+ obj.each do |key, value|
+ elem = SOAPStruct.new # Undefined type.
+ elem.add("key", Mapping._obj2soap(key, map))
+ elem.add("value", Mapping._obj2soap(value, map))
+ param.add("item", elem)
+ end
+ param.add('default', Mapping._obj2soap(obj.default, map))
+ addiv2soapattr(param, obj, map)
when Regexp
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_REGEXP))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_REGEXP)
mark_marshalled_obj(obj, param)
if obj.class != Regexp
param.extraattr[RubyTypeName] = obj.class.name
@@ -119,9 +160,12 @@ class RubytypeFactory < Factory
end
end
param.add('options', SOAPInt.new(options))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Range
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_RANGE))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_RANGE)
mark_marshalled_obj(obj, param)
if obj.class != Range
param.extraattr[RubyTypeName] = obj.class.name
@@ -129,57 +173,42 @@ class RubytypeFactory < Factory
param.add('begin', Mapping._obj2soap(obj.begin, map))
param.add('end', Mapping._obj2soap(obj.end, map))
param.add('exclude_end', SOAP::SOAPBoolean.new(obj.exclude_end?))
- addiv2soap(param, obj, map)
- when Hash
+ addiv2soapattr(param, obj, map)
+ when Class
unless @allow_original_mapping
return nil
end
- if obj.respond_to?(:default_proc) && obj.default_proc
- raise TypeError.new("cannot dump hash with default proc")
- end
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_HASH))
- mark_marshalled_obj(obj, param)
- if obj.class != Hash
- param.extraattr[RubyTypeName] = obj.class.name
- end
- obj.each do |key, value|
- elem = SOAPStruct.new # Undefined type.
- elem.add("key", Mapping._obj2soap(key, map))
- elem.add("value", Mapping._obj2soap(value, map))
- param.add("item", elem)
- end
- param.add('default', Mapping._obj2soap(obj.default, map))
- addiv2soap(param, obj, map)
- when Class
if obj.name.empty?
raise TypeError.new("Can't dump anonymous class #{ obj }.")
end
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_CLASS))
+ param = SOAPStruct.new(TYPE_CLASS)
mark_marshalled_obj(obj, param)
param.add('name', SOAPString.new(obj.name))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Module
+ unless @allow_original_mapping
+ return nil
+ end
if obj.name.empty?
raise TypeError.new("Can't dump anonymous module #{ obj }.")
end
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_MODULE))
+ param = SOAPStruct.new(TYPE_MODULE)
mark_marshalled_obj(obj, param)
param.add('name', SOAPString.new(obj.name))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Symbol
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_SYMBOL))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_SYMBOL)
mark_marshalled_obj(obj, param)
param.add('id', SOAPString.new(obj.id2name))
- addiv2soap(param, obj, map)
- when Exception
- typestr = Mapping.name2elename(obj.class.to_s)
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
- mark_marshalled_obj(obj, param)
- param.add('message', Mapping._obj2soap(obj.message, map))
- param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Struct
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_STRUCT))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_STRUCT)
mark_marshalled_obj(obj, param)
param.add('type', ele_type = SOAPString.new(obj.class.to_s))
ele_member = SOAPStruct.new
@@ -188,29 +217,23 @@ class RubytypeFactory < Factory
Mapping._obj2soap(obj[member], map))
end
param.add('member', ele_member)
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when IO, Binding, Continuation, Data, Dir, File::Stat, MatchData, Method,
- Proc, Thread, ThreadGroup
+ Proc, Thread, ThreadGroup # from 1.8: Process::Status, UnboundMethod
return nil
when ::SOAP::Mapping::Object
param = SOAPStruct.new(XSD::AnyTypeName)
mark_marshalled_obj(obj, param)
- setiv2soap(param, obj, map) # addiv2soap?
- else
- if obj.class.name.empty?
- raise TypeError.new("Can't dump anonymous class #{ obj }.")
- end
- if check_singleton(obj)
- raise TypeError.new("singleton can't be dumped #{ obj }")
- end
- type = Mapping.class2element(obj.class)
- param = SOAPStruct.new(type)
+ addiv2soapattr(param, obj, map)
+ when Exception
+ typestr = Mapping.name2elename(obj.class.to_s)
+ param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
mark_marshalled_obj(obj, param)
- if obj.class <= Marshallable
- setiv2soap(param, obj, map)
- else
- setiv2soap(param, obj, map) # Should not be marshalled?
- end
+ param.add('message', Mapping._obj2soap(obj.message, map))
+ param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
+ addiv2soapattr(param, obj, map)
+ else
+ param = unknownobj2soap(soap_class, obj, info, map)
end
param
end
@@ -218,26 +241,42 @@ class RubytypeFactory < Factory
def soap2obj(obj_class, node, info, map)
rubytype = node.extraattr[RubyTypeName]
if rubytype or node.type.namespace == RubyTypeNamespace
- rubytype2obj(node, map, rubytype)
+ rubytype2obj(node, info, map, rubytype)
elsif node.type == XSD::AnyTypeName or node.type == XSD::AnySimpleTypeName
- anytype2obj(node, map)
+ anytype2obj(node, info, map)
else
- unknowntype2obj(node, map)
+ unknowntype2obj(node, info, map)
end
end
private
- def check_singleton(obj)
- unless singleton_methods_true(obj).empty?
- return true
+ def addiv2soapattr(node, obj, map)
+ return if obj.instance_variables.empty?
+ ivars = SOAPStruct.new # Undefined type.
+ setiv2soap(ivars, obj, map)
+ node.extraattr[RubyIVarName] = ivars
+ end
+
+ def unknownobj2soap(soap_class, obj, info, map)
+ if obj.class.name.empty?
+ raise TypeError.new("Can't dump anonymous class #{ obj }.")
end
singleton_class = class << obj; self; end
- if !singleton_class.instance_variables.empty? or
- !(singleton_class.ancestors - obj.class.ancestors).empty?
- return true
+ if !singleton_methods_true(obj).empty? or
+ !singleton_class.instance_variables.empty?
+ raise TypeError.new("singleton can't be dumped #{ obj }")
+ end
+ if !(singleton_class.ancestors - obj.class.ancestors).empty?
+ typestr = Mapping.name2elename(obj.class.to_s)
+ type = XSD::QName.new(RubyTypeNamespace, typestr)
+ else
+ type = Mapping.class2element(obj.class)
end
- false
+ param = SOAPStruct.new(type)
+ mark_marshalled_obj(obj, param)
+ setiv2soap(param, obj, map)
+ param
end
if RUBY_VERSION >= '1.8.0'
@@ -250,40 +289,54 @@ private
end
end
- def rubytype2obj(node, map, rubytype)
+ def rubytype2obj(node, info, map, rubytype)
+ klass = rubytype ? Mapping.class_from_name(rubytype) : nil
obj = nil
- case node.class
+ case node
when SOAPString
- obj = string2obj(node, map, rubytype)
- obj.replace(node.data)
+ return @string_factory.soap2obj(klass || String, node, info, map)
+ when SOAPDateTime
+ #return @datetime_factory.soap2obj(klass || Time, node, info, map)
+ klass ||= Time
+ t = node.to_time
+ arg = [t.year, t.month, t.mday, t.hour, t.min, t.sec, t.usec]
+ obj = t.gmt? ? klass.gm(*arg) : klass.local(*arg)
+ mark_unmarshalled_obj(node, obj)
return true, obj
when SOAPArray
- obj = array2obj(node, map, rubytype)
- node.soap2array(obj) do |elem|
- elem ? Mapping._soap2obj(elem, map) : nil
- end
- return true, obj
+ return @array_factory.soap2obj(klass || Array, node, info, map)
+ when SOAPNil, SOAPBoolean, SOAPInt, SOAPInteger, SOAPDecimal, SOAPDouble
+ return @basetype_factory.soap2obj(nil, node, info, map)
+ when SOAPStruct
+ return rubytypestruct2obj(node, info, map, rubytype)
+ else
+ raise
end
+ end
- case node.type.name
- when TYPE_STRING
- obj = string2obj(node, map, rubytype)
- obj.replace(node['string'].data)
- setiv2obj(obj, node['ivars'], map)
- when TYPE_ARRAY
- obj = array2obj(node, map, rubytype)
- node['array'].soap2array(obj) do |elem|
- elem ? Mapping._soap2obj(elem, map) : nil
- end
- setiv2obj(obj, node['ivars'], map)
+ def rubytypestruct2obj(node, info, map, rubytype)
+ klass = rubytype ? Mapping.class_from_name(rubytype) : nil
+ obj = nil
+ case node.type
+ when TYPE_HASH
+ klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
+ obj = create_empty_object(klass)
+ mark_unmarshalled_obj(node, obj)
+ node.each do |key, value|
+ next unless key == 'item'
+ obj[Mapping._soap2obj(value['key'], map)] =
+ Mapping._soap2obj(value['value'], map)
+ end
+ if node.key?('default')
+ obj.default = Mapping._soap2obj(node['default'], map)
+ end
when TYPE_REGEXP
klass = rubytype ? Mapping.class_from_name(rubytype) : Regexp
obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj)
source = node['source'].string
options = node['options'].data || 0
- obj.instance_eval { initialize(source, options) }
- setiv2obj(obj, node['ivars'], map)
+ Regexp.instance_method(:initialize).bind(obj).call(source, options)
when TYPE_RANGE
klass = rubytype ? Mapping.class_from_name(rubytype) : Range
obj = create_empty_object(klass)
@@ -291,33 +344,13 @@ private
first = Mapping._soap2obj(node['begin'], map)
last = Mapping._soap2obj(node['end'], map)
exclude_end = node['exclude_end'].data
- obj.instance_eval { initialize(first, last, exclude_end) }
- setiv2obj(obj, node['ivars'], map)
- when TYPE_HASH
- unless @allow_original_mapping
- return false
- end
- klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
- obj = create_empty_object(klass)
- mark_unmarshalled_obj(node, obj)
- node.each do |key, value|
- next unless key == 'item'
- obj[Mapping._soap2obj(value['key'], map)] =
- Mapping._soap2obj(value['value'], map)
- end
- if node.key?('default')
- obj.default = Mapping._soap2obj(node['default'], map)
- end
- setiv2obj(obj, node['ivars'], map)
+ Range.instance_method(:initialize).bind(obj).call(first, last, exclude_end)
when TYPE_CLASS
obj = Mapping.class_from_name(node['name'].data)
- setiv2obj(obj, node['ivars'], map)
when TYPE_MODULE
obj = Mapping.class_from_name(node['name'].data)
- setiv2obj(obj, node['ivars'], map)
when TYPE_SYMBOL
obj = node['id'].data.intern
- setiv2obj(obj, node['ivars'], map)
when TYPE_STRUCT
typestr = Mapping.elename2name(node['type'].data)
klass = Mapping.class_from_name(typestr)
@@ -333,40 +366,15 @@ private
obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj)
node['member'].each do |name, value|
- obj[Mapping.elename2name(name)] =
- Mapping._soap2obj(value, map)
+ obj[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
end
- setiv2obj(obj, node['ivars'], map)
else
- conv, obj = exception2obj(node, map)
- unless conv
- return false
- end
- setiv2obj(obj, node['ivars'], map)
+ return unknowntype2obj(node, info, map)
end
return true, obj
end
- def exception2obj(node, map)
- typestr = Mapping.elename2name(node.type.name)
- klass = Mapping.class_from_name(typestr)
- if klass.nil?
- return false
- end
- unless klass <= Exception
- return false
- end
- message = Mapping._soap2obj(node['message'], map)
- backtrace = Mapping._soap2obj(node['backtrace'], map)
- obj = create_empty_object(klass)
- obj = obj.exception(message)
- mark_unmarshalled_obj(node, obj)
- obj.set_backtrace(backtrace)
- setiv2obj(obj, node['ivars'], map)
- return true, obj
- end
-
- def anytype2obj(node, map)
+ def anytype2obj(node, info, map)
case node
when SOAPBasetype
return true, node.data
@@ -383,22 +391,24 @@ private
end
end
- def unknowntype2obj(node, map)
+ def unknowntype2obj(node, info, map)
if node.is_a?(SOAPStruct)
- obj = struct2obj(node, map)
+ obj = unknownstruct2obj(node, info, map)
return true, obj if obj
if !@allow_untyped_struct
return false
end
- return anytype2obj(node, map)
+ return anytype2obj(node, info, map)
else
# Basetype which is not defined...
return false
end
end
- def struct2obj(node, map)
- obj = nil
+ def unknownstruct2obj(node, info, map)
+ unless node.type.name
+ return nil
+ end
typestr = Mapping.elename2name(node.type.name)
klass = Mapping.class_from_name(typestr)
if klass.nil?
@@ -407,6 +417,9 @@ private
if klass.nil?
return nil
end
+ if klass <= ::Exception
+ return exception2obj(klass, node, map)
+ end
klass_type = Mapping.class2qname(klass)
return nil unless node.type.match(klass_type)
obj = create_empty_object(klass)
@@ -415,6 +428,16 @@ private
obj
end
+ def exception2obj(klass, node, map)
+ message = Mapping._soap2obj(node['message'], map)
+ backtrace = Mapping._soap2obj(node['backtrace'], map)
+ obj = create_empty_object(klass)
+ obj = obj.exception(message)
+ mark_unmarshalled_obj(node, obj)
+ obj.set_backtrace(backtrace)
+ obj
+ end
+
# Only creates empty array. Do String#replace it with real string.
def array2obj(node, map, rubytype)
klass = rubytype ? Mapping.class_from_name(rubytype) : Array
diff --git a/lib/soap/marshal.rb b/lib/soap/marshal.rb
index f45f80a0de..5c25fad0de 100644
--- a/lib/soap/marshal.rb
+++ b/lib/soap/marshal.rb
@@ -58,10 +58,10 @@ module Marshal
def unmarshal(stream, mapping_registry = MarshalMappingRegistry)
header, body = SOAP::Processor.unmarshal(stream)
+ #Mapping.soap2obj(body.root_node, mapping_registry)
Mapping.soap2obj(body.root_node, mapping_registry)
end
end
-
end
diff --git a/lib/soap/rpc/standaloneServer.rb b/lib/soap/rpc/standaloneServer.rb
index 346d6e196b..8862f7606e 100644
--- a/lib/soap/rpc/standaloneServer.rb
+++ b/lib/soap/rpc/standaloneServer.rb
@@ -50,6 +50,7 @@ class StandaloneServer < Logger::Application
def initialize(app_name, namespace, host = "0.0.0.0", port = 8080)
super(app_name)
+ self.level = Logger::Severity::INFO
@namespace = namespace
@host = host
@port = port
diff --git a/lib/soap/wsdlDriver.rb b/lib/soap/wsdlDriver.rb
index 849effcb0b..6ecc4b4f6e 100644
--- a/lib/soap/wsdlDriver.rb
+++ b/lib/soap/wsdlDriver.rb
@@ -223,7 +223,8 @@ class WSDLDriver
@endpoint_url = nil
@wiredump_dev = nil
@wiredump_file_base = nil
- @httpproxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
+ name = 'http_proxy'
+ @httpproxy = ENV[name] || ENV[name.upcase]
@wsdl_elements = @wsdl.collect_elements
@wsdl_types = @wsdl.collect_complextypes