1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
nahi 2003-10-14 15:14:02 +00:00
parent 0b841783b5
commit 9cba39a1a1
21 changed files with 716 additions and 402 deletions

View file

@ -40,10 +40,17 @@ public
end end
###
## Marker of SOAP/DM types.
#
module SOAPType; end
### ###
## Mix-in module for SOAP base type instances. ## Mix-in module for SOAP base type instances.
# #
module SOAPBasetype module SOAPBasetype
include SOAPType
include SOAP include SOAP
attr_accessor :encodingstyle attr_accessor :encodingstyle
@ -75,6 +82,7 @@ end
## Mix-in module for SOAP compound type instances. ## Mix-in module for SOAP compound type instances.
# #
module SOAPCompoundtype module SOAPCompoundtype
include SOAPType
include SOAP include SOAP
attr_accessor :encodingstyle attr_accessor :encodingstyle
@ -168,7 +176,7 @@ public
d d
end end
def SOAPReference.create_refid(obj) def self.create_refid(obj)
'id' << obj.__id__.to_s 'id' << obj.__id__.to_s
end end
end end
@ -597,7 +605,7 @@ public
data = retrieve(idxary[0, idxary.size - 1]) data = retrieve(idxary[0, idxary.size - 1])
data[idxary.last] = value 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') value.elename = value.elename.dup_name('item')
# Sync type # Sync type

View file

@ -84,17 +84,17 @@ public
end end
end end
def encode(buf, ns, attrs = {}, indent = '') def encode(generator, ns, attrs = {})
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace) SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace) SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
name = ns.name(@elename) name = ns.name(@elename)
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
yield(self.faultcode, false) yield(self.faultcode, false)
yield(self.faultstring, false) yield(self.faultstring, false)
yield(self.faultactor, false) yield(self.faultactor, false)
yield(self.detail, false) if self.detail yield(self.detail, false) if self.detail
SOAPGenerator.encode_tag_end(buf, name, indent, true) generator.encode_tag_end(name, true)
end end
end end
@ -112,9 +112,9 @@ public
@is_fault = is_fault @is_fault = is_fault
end end
def encode(buf, ns, attrs = {}, indent = '') def encode(generator, ns, attrs = {})
name = ns.name(@elename) name = ns.name(@elename)
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
if @is_fault if @is_fault
yield(@data, true) yield(@data, true)
else else
@ -122,7 +122,7 @@ public
yield(data, true) yield(data, true)
end end
end end
SOAPGenerator.encode_tag_end(buf, name, indent, true) generator.encode_tag_end(name, true)
end end
def root_node def root_node
@ -160,7 +160,7 @@ public
@encodingstyle = encodingstyle || LiteralNamespace @encodingstyle = encodingstyle || LiteralNamespace
end end
def encode(buf, ns, attrs = {}, indent = '') def encode(generator, ns, attrs = {})
attrs.each do |key, value| attrs.each do |key, value|
@content.attr[key] = value @content.attr[key] = value
end end
@ -185,13 +185,13 @@ class SOAPHeader < SOAPArray
@encodingstyle = nil @encodingstyle = nil
end end
def encode(buf, ns, attrs = {}, indent = '') def encode(generator, ns, attrs = {})
name = ns.name(@elename) name = ns.name(@elename)
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
@data.each do |data| @data.each do |data|
yield(data, true) yield(data, true)
end end
SOAPGenerator.encode_tag_end(buf, name, indent, true) generator.encode_tag_end(name, true)
end end
def length def length
@ -215,16 +215,16 @@ class SOAPEnvelope < XSD::NSDBase
@body = body @body = body
end end
def encode(buf, ns, attrs = {}, indent = '') def encode(generator, ns, attrs = {})
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace, SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace,
SOAPNamespaceTag) SOAPNamespaceTag)
name = ns.name(@elename) 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(@header, true) if @header and @header.length > 0
yield(@body, true) yield(@body, true)
SOAPGenerator.encode_tag_end(buf, name, indent, true) generator.encode_tag_end(name, true)
end end
end end

View file

@ -38,7 +38,7 @@ class ASPDotNetHandler < Handler
### ###
## encode interface. ## encode interface.
# #
def encode_data(buf, ns, qualified, data, parent, indent = '') def encode_data(generator, ns, qualified, data, parent)
attrs = {} attrs = {}
name = if qualified and data.elename.namespace name = if qualified and data.elename.namespace
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace) SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
@ -49,17 +49,16 @@ class ASPDotNetHandler < Handler
case data case data
when SOAPRawString when SOAPRawString
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << data.to_s generator.encode_rawstring(data.to_s)
when XSD::XSDString when XSD::XSDString
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << SOAPGenerator.encode_str(@charset ? generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType when XSD::XSDAnySimpleType
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << SOAPGenerator.encode_str(data.to_s) generator.encode_string(data.to_s)
when SOAPStruct when SOAPStruct
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
data.each do |key, value| data.each do |key, value|
if !value.elename.namespace if !value.elename.namespace
value.elename.namespace = data.elename.namespace value.elename.namespace = data.elename.namespace
@ -67,7 +66,7 @@ class ASPDotNetHandler < Handler
yield(value, true) yield(value, true)
end end
when SOAPArray when SOAPArray
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
data.traverse do |child, *rank| data.traverse do |child, *rank|
data.position = nil data.position = nil
yield(child, true) yield(child, true)
@ -78,14 +77,14 @@ yle.")
end end
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 name = if qualified and data.elename.namespace
ns.name(data.elename) ns.name(data.elename)
else else
data.elename.name data.elename.name
end end
cr = data.is_a?(SOAPCompoundtype) cr = data.is_a?(SOAPCompoundtype)
SOAPGenerator.encode_tag_end(buf, name, indent, cr) generator.encode_tag_end(name, cr)
end end

View file

@ -69,11 +69,11 @@ class Handler
## encode interface. ## encode interface.
# #
# Returns a XML instance as a string. # 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.') raise NotImplementError.new('Method encode_data must be defined in derived class.')
end 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.') raise NotImplementError.new('Method encode_data must be defined in derived class.')
end end

View file

@ -37,7 +37,7 @@ class LiteralHandler < Handler
### ###
## encode interface. ## encode interface.
# #
def encode_data(buf, ns, qualified, data, parent, indent = '') def encode_data(generator, ns, qualified, data, parent)
attrs = {} attrs = {}
name = if qualified and data.elename.namespace name = if qualified and data.elename.namespace
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace) SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
@ -48,31 +48,29 @@ class LiteralHandler < Handler
case data case data
when SOAPRawString when SOAPRawString
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << data.to_s generator.encode_rawstring(data.to_s)
when XSD::XSDString when XSD::XSDString
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << SOAPGenerator.encode_str(@charset ? generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType when XSD::XSDAnySimpleType
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << SOAPGenerator.encode_str(data.to_s) generator.encode_string(data.to_s)
when SOAPStruct when SOAPStruct
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
data.each do |key, value| data.each do |key, value|
value.elename.namespace = data.elename.namespace if !value.elename.namespace value.elename.namespace = data.elename.namespace if !value.elename.namespace
yield(value, true) yield(value, true)
end end
when SOAPArray when SOAPArray
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
data.traverse do |child, *rank| data.traverse do |child, *rank|
data.position = nil data.position = nil
yield(child, true) yield(child, true)
end end
when SOAPElement when SOAPElement
SOAPGenerator.encode_tag(buf, name, attrs.update(data.extraattr), generator.encode_tag(name, attrs.update(data.extraattr))
indent) generator.encode_rawstring(data.text) if data.text
buf << data.text if data.text
data.each do |key, value| data.each do |key, value|
value.elename.namespace = data.elename.namespace if !value.elename.namespace value.elename.namespace = data.elename.namespace if !value.elename.namespace
#yield(value, data.qualified) #yield(value, data.qualified)
@ -83,13 +81,13 @@ class LiteralHandler < Handler
end end
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 name = if qualified and data.elename.namespace
ns.name(data.elename) ns.name(data.elename)
else else
data.elename.name data.elename.name
end end
SOAPGenerator.encode_tag_end(buf, name, indent) generator.encode_tag_end(name)
end end

View file

@ -40,8 +40,8 @@ class SOAPHandler < Handler
### ###
## encode interface. ## encode interface.
# #
def encode_data(buf, ns, qualified, data, parent, indent = '') def encode_data(generator, ns, qualified, data, parent)
attrs = encode_attrs(ns, qualified, data, parent) attrs = encode_attrs(generator, ns, data, parent)
if parent && parent.is_a?(SOAPArray) && parent.position if parent && parent.is_a?(SOAPArray) && parent.position
attrs[ns.name(AttrPositionName)] = '[' << parent.position.join(',') << ']' attrs[ns.name(AttrPositionName)] = '[' << parent.position.join(',') << ']'
@ -55,32 +55,26 @@ class SOAPHandler < Handler
name = data.elename.name name = data.elename.name
end end
if data.respond_to?(:encode)
SOAPGenerator.encode_tag(buf, name, attrs, indent)
return data.encode(buf, ns, attrs, indent)
end
case data case data
when SOAPReference when SOAPReference
attrs['href'] = '#' << data.refid attrs['href'] = '#' << data.refid
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
when SOAPRawString when SOAPRawString
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << data.to_s generator.encode_rawstring(data.to_s)
when XSD::XSDString when XSD::XSDString
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << SOAPGenerator.encode_str(@charset ? generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType when XSD::XSDAnySimpleType
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
buf << SOAPGenerator.encode_str(data.to_s) generator.encode_string(data.to_s)
when SOAPStruct when SOAPStruct
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
data.each do |key, value| data.each do |key, value|
yield(value, false) yield(value, false)
end end
when SOAPArray when SOAPArray
SOAPGenerator.encode_tag(buf, name, attrs, indent) generator.encode_tag(name, attrs)
data.traverse do |child, *rank| data.traverse do |child, *rank|
data.position = data.sparse ? rank : nil data.position = data.sparse ? rank : nil
yield(child, false) yield(child, false)
@ -91,14 +85,14 @@ class SOAPHandler < Handler
end end
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 name = if qualified and data.elename.namespace
ns.name(data.elename) ns.name(data.elename)
else else
data.elename.name data.elename.name
end end
cr = data.is_a?(SOAPCompoundtype) cr = data.is_a?(SOAPCompoundtype)
SOAPGenerator.encode_tag_end(buf, name, indent, cr) generator.encode_tag_end(name, cr)
end end
@ -292,7 +286,7 @@ private
content_typename(data.arytype.name) << '[' << data.size.join(',') << ']') content_typename(data.arytype.name) << '[' << data.size.join(',') << ']')
end end
def encode_attrs(ns, qualified, data, parent) def encode_attrs(generator, ns, data, parent)
return {} if data.is_a?(SOAPReference) return {} if data.is_a?(SOAPReference)
attrs = {} attrs = {}
@ -330,7 +324,7 @@ private
data.extraattr.each do |key, value| data.extraattr.each do |key, value|
SOAPGenerator.assign_ns(attrs, ns, key.namespace) 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 end
if data.id if data.id
attrs['id'] = data.id attrs['id'] = data.id
@ -338,6 +332,17 @@ private
attrs attrs
end 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) def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr)
if parent.class == SOAPBody if parent.class == SOAPBody
# Unqualified name is allowed here. # Unqualified name is allowed here.
@ -423,12 +428,14 @@ private
end end
if (klass = TypeMap[type]) if (klass = TypeMap[type])
klass.decode(elename) node = klass.decode(elename)
else node.extraattr.update(extraattr)
return node
end
# Unknown type... Struct or String # Unknown type... Struct or String
SOAPUnknown.new(self, elename, type, extraattr) SOAPUnknown.new(self, elename, type, extraattr)
end end
end
def decode_textbuf(node) def decode_textbuf(node)
case node case node
@ -508,12 +515,22 @@ private
id = value id = value
next next
end end
extraattr[qname] = value extraattr[qname] = decode_attr_value(ns, qname, value)
end end
return is_nil, type, arytype, root, offset, position, href, id, extraattr return is_nil, type, arytype, root, offset, position, href, id, extraattr
end 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) def decode_arypos(position)
/^\[(.+)\]$/ =~ position /^\[(.+)\]$/ =~ position
$1.split(',').collect { |s| s.to_i } $1.split(',').collect { |s| s.to_i }
@ -524,7 +541,7 @@ private
while !@refpool.empty? && count > 0 while !@refpool.empty? && count > 0
@refpool = @refpool.find_all { |ref| @refpool = @refpool.find_all { |ref|
o = @idpool.find { |item| o = @idpool.find { |item|
('#' << item.id == ref.refid) '#' + item.id == ref.refid
} }
unless o unless o
raise EncodingStyleError.new("Unresolved reference: #{ ref.refid }.") raise EncodingStyleError.new("Unresolved reference: #{ ref.refid }.")

View file

@ -39,7 +39,6 @@ public
attr_accessor :charset attr_accessor :charset
attr_accessor :default_encodingstyle attr_accessor :default_encodingstyle
attr_accessor :generate_explicit_type attr_accessor :generate_explicit_type
attr_accessor :pretty
def initialize(opt = {}) def initialize(opt = {})
@reftarget = nil @reftarget = nil
@ -48,37 +47,38 @@ public
@default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace @default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
@generate_explicit_type = @generate_explicit_type =
opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true
@pretty = true # opt[:pretty] @buf = @indent = @curr = nil
end end
def generate(obj, io = nil) def generate(obj, io = nil)
@buf = io || ''
@indent = ''
prologue prologue
@handlers.each do |uri, handler| @handlers.each do |uri, handler|
handler.encode_prologue handler.encode_prologue
end end
io = '' if io.nil?
ns = XSD::NS.new ns = XSD::NS.new
io << xmldecl @buf << xmldecl
encode_data(io, ns, true, obj, nil, 0) encode_data(ns, true, obj, nil)
@handlers.each do |uri, handler| @handlers.each do |uri, handler|
handler.encode_epilogue handler.encode_epilogue
end end
epilogue epilogue
io @buf
end end
def encode_data(buf, ns, qualified, obj, parent, indent) def encode_data(ns, qualified, obj, parent)
if obj.is_a?(SOAPEnvelopeElement) if obj.is_a?(SOAPEnvelopeElement)
encode_element(buf, ns, qualified, obj, parent, indent) encode_element(ns, qualified, obj, parent)
return return
end end
if @reftarget && !obj.precedents.empty? if @reftarget && !obj.precedents.empty?
@reftarget.add(obj.elename.name, obj) add_reftarget(obj.elename.name, obj)
ref = SOAPReference.new ref = SOAPReference.new
ref.elename.name = obj.elename.name ref.elename.name = obj.elename.name
ref.__setobj__(obj) ref.__setobj__(obj)
@ -102,22 +102,29 @@ public
raise FormatEncodeError.new("Element name not defined: #{ obj }.") raise FormatEncodeError.new("Element name not defined: #{ obj }.")
end end
indent_str = ' ' * indent handler.encode_data(self, ns, qualified, obj, parent) do |child, child_q|
child_indent = @pretty ? indent + 2 : indent indent_backup, @indent = @indent, @indent + ' '
handler.encode_data(buf, ns, qualified, obj, parent, indent_str) do |child, child_q| encode_data(ns.clone_ns, child_q, child, obj)
encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent) @indent = indent_backup
end end
handler.encode_data_end(buf, ns, qualified, obj, parent, indent_str) handler.encode_data_end(self, ns, qualified, obj, parent)
end end
def encode_element(buf, ns, qualified, obj, parent, indent) def add_reftarget(name, node)
indent_str = ' ' * indent unless @reftarget
child_indent = @pretty ? indent + 2 : indent raise FormatEncodeError.new("Reftarget is not defined.")
end
@reftarget.add(name, node)
end
def encode_element(ns, qualified, obj, parent)
attrs = {} attrs = {}
if obj.is_a?(SOAPBody) if obj.is_a?(SOAPBody)
@reftarget = obj @reftarget = obj
obj.encode(buf, ns, attrs, indent_str) do |child, child_q| obj.encode(self, ns, attrs) do |child, child_q|
encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent) indent_backup, @indent = @indent, @indent + ' '
encode_data(ns.clone_ns, child_q, child, obj)
@indent = indent_backup
end end
@reftarget = nil @reftarget = nil
else else
@ -129,39 +136,38 @@ public
SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag) SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag)
end end
end end
obj.encode(buf, ns, attrs, indent_str) do |child, child_q| obj.encode(self, ns, attrs) do |child, child_q|
encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent) indent_backup, @indent = @indent, @indent + ' '
encode_data(ns.clone_ns, child_q, child, obj)
@indent = indent_backup
end end
end end
end end
def self.assign_ns(attrs, ns, namespace, tag = nil) def encode_tag(elename, attrs = 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 = '')
if attrs if attrs
buf << "\n#{ indent }<#{ elename }" << @buf << "\n#{ @indent }<#{ elename }" <<
attrs.collect { |key, value| attrs.collect { |key, value|
%Q[ #{ key }="#{ value }"] %Q[ #{ key }="#{ value }"]
}.join << }.join <<
'>' '>'
else else
buf << "\n#{ indent }<#{ elename }>" @buf << "\n#{ @indent }<#{ elename }>"
end end
end end
def self.encode_tag_end(buf, elename, indent = '', cr = nil) def encode_tag_end(elename, cr = nil)
if cr if cr
buf << "\n#{ indent }</#{ elename }>" @buf << "\n#{ @indent }</#{ elename }>"
else else
buf << "</#{ elename }>" @buf << "</#{ elename }>"
end end
end end
def encode_rawstring(str)
@buf << str
end
EncodeMap = { EncodeMap = {
'&' => '&amp;', '&' => '&amp;',
'<' => '&lt;', '<' => '&lt;',
@ -171,8 +177,15 @@ public
"\r" => '&#xd;' "\r" => '&#xd;'
} }
EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]") EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]")
def self.encode_str(str) def encode_string(str)
str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] } @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 end
private private

View file

@ -24,6 +24,10 @@ module Mapping
class Factory class Factory
include TraverseSupport include TraverseSupport
def initialize
# nothing to do
end
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
raise NotImplementError.new raise NotImplementError.new
# return soap_obj # return soap_obj
@ -48,24 +52,13 @@ class Factory
end end
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) def setiv2obj(obj, node, map)
return if node.nil? return if node.nil?
vars = {} vars = {}
node.each do |name, value| node.each do |name, value|
vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map) vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
end end
set_instance_vars(obj, vars) Mapping.set_instance_vars(obj, vars)
end end
def setiv2soap(node, obj, map) def setiv2soap(node, obj, map)
@ -76,13 +69,6 @@ class Factory
end end
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]. # It breaks Thread.current[:SOAPMarshalDataKey].
def mark_marshalled_obj(obj, soap_obj) def mark_marshalled_obj(obj, soap_obj)
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
@ -103,14 +89,21 @@ class Factory
end end
class StringFactory_ < Factory class StringFactory_ < Factory
def initialize(allow_original_mapping = false)
super()
@allow_original_mapping = allow_original_mapping
end
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
begin if !@allow_original_mapping and !obj.instance_variables.empty?
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 return nil
end end
begin
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 rescue XSD::ValueSpaceError
return nil return nil
end end
@ -119,14 +112,24 @@ class StringFactory_ < Factory
end end
def soap2obj(obj_class, node, info, map) 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) mark_unmarshalled_obj(node, obj)
return true, obj return true, obj
end end
end end
class BasetypeFactory_ < Factory class BasetypeFactory_ < Factory
def initialize(allow_original_mapping = false)
super()
@allow_original_mapping = allow_original_mapping
end
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
if !@allow_original_mapping and !obj.instance_variables.empty?
return nil
end
soap_obj = nil soap_obj = nil
begin begin
soap_obj = soap_class.new(obj) soap_obj = soap_class.new(obj)
@ -145,7 +148,16 @@ class BasetypeFactory_ < Factory
end end
class DateTimeFactory_ < Factory class DateTimeFactory_ < Factory
def initialize(allow_original_mapping = false)
super()
@allow_original_mapping = allow_original_mapping
end
def obj2soap(soap_class, obj, info, map) 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 soap_obj = nil
begin begin
soap_obj = soap_class.new(obj) soap_obj = soap_class.new(obj)
@ -176,6 +188,7 @@ end
class Base64Factory_ < Factory class Base64Factory_ < Factory
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
return nil unless obj.instance_variables.empty?
soap_obj = soap_class.new(obj) soap_obj = soap_class.new(obj)
mark_marshalled_obj(obj, soap_obj) if soap_obj mark_marshalled_obj(obj, soap_obj) if soap_obj
soap_obj soap_obj
@ -189,9 +202,17 @@ class Base64Factory_ < Factory
end end
class ArrayFactory_ < Factory 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. # [[1], [2]] is converted to Array of Array, not 2-D Array.
# To create M-D Array, you must call Mapping.ary2md. # To create M-D Array, you must call Mapping.ary2md.
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
if !@allow_original_mapping and !obj.instance_variables.empty?
return nil
end
arytype = Mapping.obj2element(obj) arytype = Mapping.obj2element(obj)
if arytype.name if arytype.name
arytype.namespace ||= RubyTypeNamespace arytype.namespace ||= RubyTypeNamespace
@ -217,7 +238,15 @@ class ArrayFactory_ < Factory
end end
class TypedArrayFactory_ < Factory class TypedArrayFactory_ < Factory
def initialize(allow_original_mapping = false)
super()
@allow_original_mapping = allow_original_mapping
end
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
if !@allow_original_mapping and !obj.instance_variables.empty?
return nil
end
arytype = info[:type] || info[0] arytype = info[:type] || info[0]
param = SOAPArray.new(ValueArrayName, 1, arytype) param = SOAPArray.new(ValueArrayName, 1, arytype)
mark_marshalled_obj(obj, param) mark_marshalled_obj(obj, param)
@ -271,8 +300,16 @@ end
MapQName = XSD::QName.new(ApacheSOAPTypeNamespace, 'Map') MapQName = XSD::QName.new(ApacheSOAPTypeNamespace, 'Map')
class HashFactory_ < Factory class HashFactory_ < Factory
def initialize(allow_original_mapping = false)
super()
@allow_original_mapping = allow_original_mapping
end
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
if obj.default or 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) (obj.respond_to?(:default_proc) and obj.default_proc)
return nil return nil
end end

View file

@ -129,6 +129,16 @@ module Mapping
return registry.soap2obj(node.class, node) return registry.soap2obj(node.class, node)
end 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. # Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
# Caution: '.' is not allowed here. # Caution: '.' is not allowed here.

View file

@ -39,6 +39,8 @@ module MappedException; end
RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType') RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType')
RubyExtendName = XSD::QName.new(RubyTypeInstanceNamespace, 'extends')
RubyIVarName = XSD::QName.new(RubyTypeInstanceNamespace, 'ivars')
# Inner class to pass an exception. # Inner class to pass an exception.
@ -217,11 +219,11 @@ class Registry
[::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory], [::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory], [::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::String, ::SOAP::SOAPString, StringFactory], [::String, ::SOAP::SOAPString, StringFactory],
[::DateTime, ::SOAP::SOAPDateTime, BasetypeFactory], [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
[::Date, ::SOAP::SOAPDateTime, BasetypeFactory], [::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
[::Date, ::SOAP::SOAPDate, BasetypeFactory], [::Date, ::SOAP::SOAPDate, DateTimeFactory],
[::Time, ::SOAP::SOAPDateTime, BasetypeFactory], [::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
[::Time, ::SOAP::SOAPTime, BasetypeFactory], [::Time, ::SOAP::SOAPTime, DateTimeFactory],
[::Float, ::SOAP::SOAPDouble, BasetypeFactory, [::Float, ::SOAP::SOAPDouble, BasetypeFactory,
{:derived_class => true}], {:derived_class => true}],
[::Float, ::SOAP::SOAPFloat, BasetypeFactory, [::Float, ::SOAP::SOAPFloat, BasetypeFactory,
@ -261,11 +263,11 @@ class Registry
[::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory], [::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory], [::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
[::String, ::SOAP::SOAPString, StringFactory], [::String, ::SOAP::SOAPString, StringFactory],
[::DateTime, ::SOAP::SOAPDateTime, BasetypeFactory], [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
[::Date, ::SOAP::SOAPDateTime, BasetypeFactory], [::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
[::Date, ::SOAP::SOAPDate, BasetypeFactory], [::Date, ::SOAP::SOAPDate, DateTimeFactory],
[::Time, ::SOAP::SOAPDateTime, BasetypeFactory], [::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
[::Time, ::SOAP::SOAPTime, BasetypeFactory], [::Time, ::SOAP::SOAPTime, DateTimeFactory],
[::Float, ::SOAP::SOAPDouble, BasetypeFactory, [::Float, ::SOAP::SOAPDouble, BasetypeFactory,
{:derived_class => true}], {:derived_class => true}],
[::Float, ::SOAP::SOAPFloat, BasetypeFactory, [::Float, ::SOAP::SOAPFloat, BasetypeFactory,
@ -304,18 +306,18 @@ class Registry
@config = config @config = config
@map = Map.new(self) @map = Map.new(self)
if @config[:allow_original_mapping] if @config[:allow_original_mapping]
allow_original_mapping = true @allow_original_mapping = true
@map.init(RubyOriginalMap) @map.init(RubyOriginalMap)
else else
allow_original_mapping = false @allow_original_mapping = false
@map.init(SOAPBaseMap) @map.init(SOAPBaseMap)
end end
allow_untyped_struct = @config.key?(:allow_untyped_struct) ? @allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
@config[:allow_untyped_struct] : true @config[:allow_untyped_struct] : true
@rubytype_factory = RubytypeFactory.new( @rubytype_factory = RubytypeFactory.new(
:allow_untyped_struct => allow_untyped_struct, :allow_untyped_struct => @allow_untyped_struct,
:allow_original_mapping => allow_original_mapping :allow_original_mapping => @allow_original_mapping
) )
@default_factory = @rubytype_factory @default_factory = @rubytype_factory
@excn_handler_obj2soap = nil @excn_handler_obj2soap = nil
@ -329,53 +331,20 @@ class Registry
# This mapping registry ignores type hint. # This mapping registry ignores type hint.
def obj2soap(klass, obj, type = nil) def obj2soap(klass, obj, type = nil)
ret = nil soap = _obj2soap(klass, obj, type)
if obj.is_a?(SOAPStruct) || obj.is_a?(SOAPArray) if @allow_original_mapping
obj.replace do |ele| addextend2soap(soap, obj)
Mapping._obj2soap(ele, self)
end end
return obj soap
elsif obj.is_a?(SOAPBasetype)
return obj
end
begin
ret = @map.obj2soap(klass, obj) ||
@default_factory.obj2soap(klass, obj, nil, self)
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 end
def soap2obj(klass, node) def soap2obj(klass, node)
if node.extraattr.key?(RubyTypeName) obj = _soap2obj(klass, node)
conv, obj = @rubytype_factory.soap2obj(klass, node, nil, self) if @allow_original_mapping
return obj if conv addextend2obj(obj, node.extraattr[RubyExtendName])
else addiv2obj(obj, node.extraattr[RubyIVarName])
conv, obj = @map.soap2obj(klass, node)
return obj if conv
conv, obj = @default_factory.soap2obj(klass, node, nil, self)
return obj if conv
end end
obj
if @excn_handler_soap2obj
begin
return @excn_handler_soap2obj.call(node) { |yield_node|
Mapping._soap2obj(yield_node, self)
}
rescue Exception
end
end
raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
end end
def default_factory=(factory) def default_factory=(factory)
@ -397,6 +366,86 @@ class Registry
def find_mapped_obj_class(soap_class) def find_mapped_obj_class(soap_class)
@map.find_mapped_obj_class(soap_class) @map.find_mapped_obj_class(soap_class)
end end
private
def _obj2soap(klass, obj, type)
ret = nil
if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
obj.replace do |ele|
Mapping._obj2soap(ele, self)
end
return obj
elsif obj.is_a?(SOAPBasetype)
return obj
end
begin
ret = @map.obj2soap(klass, obj) ||
@default_factory.obj2soap(klass, obj, nil, self)
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
# 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
else
conv, obj = @map.soap2obj(klass, node)
return obj if conv
conv, obj = @default_factory.soap2obj(klass, node, nil, self)
return obj if conv
end
if @excn_handler_soap2obj
begin
return @excn_handler_soap2obj.call(node) { |yield_node|
Mapping._soap2obj(yield_node, self)
}
rescue Exception
end
end
raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
end
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 addextend2obj(obj, attr)
return unless attr
attr.split(/ /).reverse_each do |mstr|
obj.extend(Mapping.class_from_name(mstr))
end
end
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
end end

View file

@ -22,15 +22,16 @@ module Mapping
class RubytypeFactory < Factory class RubytypeFactory < Factory
TYPE_STRING = 'String' TYPE_STRING = XSD::QName.new(RubyTypeNamespace, 'String')
TYPE_ARRAY = 'Array' TYPE_TIME = XSD::QName.new(RubyTypeNamespace, 'Time')
TYPE_REGEXP = 'Regexp' TYPE_ARRAY = XSD::QName.new(RubyTypeNamespace, 'Array')
TYPE_RANGE = 'Range' TYPE_REGEXP = XSD::QName.new(RubyTypeNamespace, 'Regexp')
TYPE_CLASS = 'Class' TYPE_RANGE = XSD::QName.new(RubyTypeNamespace, 'Range')
TYPE_MODULE = 'Module' TYPE_CLASS = XSD::QName.new(RubyTypeNamespace, 'Class')
TYPE_SYMBOL = 'Symbol' TYPE_MODULE = XSD::QName.new(RubyTypeNamespace, 'Module')
TYPE_STRUCT = 'Struct' TYPE_SYMBOL = XSD::QName.new(RubyTypeNamespace, 'Symbol')
TYPE_HASH = 'Map' TYPE_STRUCT = XSD::QName.new(RubyTypeNamespace, 'Struct')
TYPE_HASH = XSD::QName.new(RubyTypeNamespace, 'Map')
def initialize(config = {}) def initialize(config = {})
@config = config @config = config
@ -38,6 +39,11 @@ class RubytypeFactory < Factory
@config[:allow_untyped_struct] : true @config[:allow_untyped_struct] : true
@allow_original_mapping = @config.key?(:allow_original_mapping) ? @allow_original_mapping = @config.key?(:allow_original_mapping) ?
@config[:allow_original_mapping] : false @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 end
def obj2soap(soap_class, obj, info, map) def obj2soap(soap_class, obj, info, map)
@ -47,48 +53,83 @@ class RubytypeFactory < Factory
unless @allow_original_mapping unless @allow_original_mapping
return nil return nil
end end
unless XSD::Charset.is_ces(obj, $KCODE) param = @string_factory.obj2soap(SOAPString, obj, info, map)
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 if obj.class != String
param.extraattr[RubyTypeName] = obj.class.name param.extraattr[RubyTypeName] = obj.class.name
end end
addiv2soap(param, obj, map) addiv2soapattr(param, obj, map)
when Time
unless @allow_original_mapping
return nil
end
param = @datetime_factory.obj2soap(SOAPDateTime, obj, info, map)
if obj.class != Time
param.extraattr[RubyTypeName] = obj.class.name
end
addiv2soapattr(param, obj, map)
when Array when Array
unless @allow_original_mapping unless @allow_original_mapping
return nil return nil
end end
arytype = Mapping.obj2element(obj) param = @array_factory.obj2soap(nil, obj, info, map)
if arytype.name
arytype.namespace ||= RubyTypeNamespace
else
arytype = XSD::AnyTypeName
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)
end
if obj.class != Array if obj.class != Array
param.extraattr[RubyTypeName] = obj.class.name param.extraattr[RubyTypeName] = obj.class.name
end end
addiv2soapattr(param, obj, map)
when NilClass
unless @allow_original_mapping
return nil
end
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 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) mark_marshalled_obj(obj, param)
if obj.class != Regexp if obj.class != Regexp
param.extraattr[RubyTypeName] = obj.class.name param.extraattr[RubyTypeName] = obj.class.name
@ -119,9 +160,12 @@ class RubytypeFactory < Factory
end end
end end
param.add('options', SOAPInt.new(options)) param.add('options', SOAPInt.new(options))
addiv2soap(param, obj, map) addiv2soapattr(param, obj, map)
when Range 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) mark_marshalled_obj(obj, param)
if obj.class != Range if obj.class != Range
param.extraattr[RubyTypeName] = obj.class.name param.extraattr[RubyTypeName] = obj.class.name
@ -129,57 +173,42 @@ class RubytypeFactory < Factory
param.add('begin', Mapping._obj2soap(obj.begin, map)) param.add('begin', Mapping._obj2soap(obj.begin, map))
param.add('end', Mapping._obj2soap(obj.end, map)) param.add('end', Mapping._obj2soap(obj.end, map))
param.add('exclude_end', SOAP::SOAPBoolean.new(obj.exclude_end?)) param.add('exclude_end', SOAP::SOAPBoolean.new(obj.exclude_end?))
addiv2soap(param, obj, map) addiv2soapattr(param, obj, map)
when Hash when Class
unless @allow_original_mapping unless @allow_original_mapping
return nil return nil
end 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? if obj.name.empty?
raise TypeError.new("Can't dump anonymous class #{ obj }.") raise TypeError.new("Can't dump anonymous class #{ obj }.")
end end
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_CLASS)) param = SOAPStruct.new(TYPE_CLASS)
mark_marshalled_obj(obj, param) mark_marshalled_obj(obj, param)
param.add('name', SOAPString.new(obj.name)) param.add('name', SOAPString.new(obj.name))
addiv2soap(param, obj, map) addiv2soapattr(param, obj, map)
when Module when Module
unless @allow_original_mapping
return nil
end
if obj.name.empty? if obj.name.empty?
raise TypeError.new("Can't dump anonymous module #{ obj }.") raise TypeError.new("Can't dump anonymous module #{ obj }.")
end end
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_MODULE)) param = SOAPStruct.new(TYPE_MODULE)
mark_marshalled_obj(obj, param) mark_marshalled_obj(obj, param)
param.add('name', SOAPString.new(obj.name)) param.add('name', SOAPString.new(obj.name))
addiv2soap(param, obj, map) addiv2soapattr(param, obj, map)
when Symbol 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) mark_marshalled_obj(obj, param)
param.add('id', SOAPString.new(obj.id2name)) param.add('id', SOAPString.new(obj.id2name))
addiv2soap(param, obj, map) 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)
param.add('message', Mapping._obj2soap(obj.message, map))
param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
addiv2soap(param, obj, map)
when Struct 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) mark_marshalled_obj(obj, param)
param.add('type', ele_type = SOAPString.new(obj.class.to_s)) param.add('type', ele_type = SOAPString.new(obj.class.to_s))
ele_member = SOAPStruct.new ele_member = SOAPStruct.new
@ -188,29 +217,23 @@ class RubytypeFactory < Factory
Mapping._obj2soap(obj[member], map)) Mapping._obj2soap(obj[member], map))
end end
param.add('member', ele_member) param.add('member', ele_member)
addiv2soap(param, obj, map) addiv2soapattr(param, obj, map)
when IO, Binding, Continuation, Data, Dir, File::Stat, MatchData, Method, when IO, Binding, Continuation, Data, Dir, File::Stat, MatchData, Method,
Proc, Thread, ThreadGroup Proc, Thread, ThreadGroup # from 1.8: Process::Status, UnboundMethod
return nil return nil
when ::SOAP::Mapping::Object when ::SOAP::Mapping::Object
param = SOAPStruct.new(XSD::AnyTypeName) param = SOAPStruct.new(XSD::AnyTypeName)
mark_marshalled_obj(obj, param) mark_marshalled_obj(obj, param)
setiv2soap(param, obj, map) # addiv2soap? addiv2soapattr(param, obj, map)
else when Exception
if obj.class.name.empty? typestr = Mapping.name2elename(obj.class.to_s)
raise TypeError.new("Can't dump anonymous class #{ obj }.") param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
end
if check_singleton(obj)
raise TypeError.new("singleton can't be dumped #{ obj }")
end
type = Mapping.class2element(obj.class)
param = SOAPStruct.new(type)
mark_marshalled_obj(obj, param) mark_marshalled_obj(obj, param)
if obj.class <= Marshallable param.add('message', Mapping._obj2soap(obj.message, map))
setiv2soap(param, obj, map) param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
addiv2soapattr(param, obj, map)
else else
setiv2soap(param, obj, map) # Should not be marshalled? param = unknownobj2soap(soap_class, obj, info, map)
end
end end
param param
end end
@ -218,26 +241,42 @@ class RubytypeFactory < Factory
def soap2obj(obj_class, node, info, map) def soap2obj(obj_class, node, info, map)
rubytype = node.extraattr[RubyTypeName] rubytype = node.extraattr[RubyTypeName]
if rubytype or node.type.namespace == RubyTypeNamespace 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 elsif node.type == XSD::AnyTypeName or node.type == XSD::AnySimpleTypeName
anytype2obj(node, map) anytype2obj(node, info, map)
else else
unknowntype2obj(node, map) unknowntype2obj(node, info, map)
end end
end end
private private
def check_singleton(obj) def addiv2soapattr(node, obj, map)
unless singleton_methods_true(obj).empty? return if obj.instance_variables.empty?
return true 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 end
singleton_class = class << obj; self; end singleton_class = class << obj; self; end
if !singleton_class.instance_variables.empty? or if !singleton_methods_true(obj).empty? or
!(singleton_class.ancestors - obj.class.ancestors).empty? !singleton_class.instance_variables.empty?
return true raise TypeError.new("singleton can't be dumped #{ obj }")
end end
false 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
param = SOAPStruct.new(type)
mark_marshalled_obj(obj, param)
setiv2soap(param, obj, map)
param
end end
if RUBY_VERSION >= '1.8.0' if RUBY_VERSION >= '1.8.0'
@ -250,53 +289,36 @@ private
end end
end end
def rubytype2obj(node, map, rubytype) def rubytype2obj(node, info, map, rubytype)
klass = rubytype ? Mapping.class_from_name(rubytype) : nil
obj = nil obj = nil
case node.class case node
when SOAPString when SOAPString
obj = string2obj(node, map, rubytype) return @string_factory.soap2obj(klass || String, node, info, map)
obj.replace(node.data) 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 return true, obj
when SOAPArray when SOAPArray
obj = array2obj(node, map, rubytype) return @array_factory.soap2obj(klass || Array, node, info, map)
node.soap2array(obj) do |elem| when SOAPNil, SOAPBoolean, SOAPInt, SOAPInteger, SOAPDecimal, SOAPDouble
elem ? Mapping._soap2obj(elem, map) : nil return @basetype_factory.soap2obj(nil, node, info, map)
when SOAPStruct
return rubytypestruct2obj(node, info, map, rubytype)
else
raise
end end
return true, obj
end end
case node.type.name def rubytypestruct2obj(node, info, map, rubytype)
when TYPE_STRING klass = rubytype ? Mapping.class_from_name(rubytype) : nil
obj = string2obj(node, map, rubytype) obj = nil
obj.replace(node['string'].data) case node.type
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)
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)
when TYPE_RANGE
klass = rubytype ? Mapping.class_from_name(rubytype) : Range
obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj)
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 when TYPE_HASH
unless @allow_original_mapping
return false
end
klass = rubytype ? Mapping.class_from_name(rubytype) : Hash klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
obj = create_empty_object(klass) obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj) mark_unmarshalled_obj(node, obj)
@ -308,16 +330,27 @@ private
if node.key?('default') if node.key?('default')
obj.default = Mapping._soap2obj(node['default'], map) obj.default = Mapping._soap2obj(node['default'], map)
end end
setiv2obj(obj, node['ivars'], map) 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
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)
mark_unmarshalled_obj(node, obj)
first = Mapping._soap2obj(node['begin'], map)
last = Mapping._soap2obj(node['end'], map)
exclude_end = node['exclude_end'].data
Range.instance_method(:initialize).bind(obj).call(first, last, exclude_end)
when TYPE_CLASS when TYPE_CLASS
obj = Mapping.class_from_name(node['name'].data) obj = Mapping.class_from_name(node['name'].data)
setiv2obj(obj, node['ivars'], map)
when TYPE_MODULE when TYPE_MODULE
obj = Mapping.class_from_name(node['name'].data) obj = Mapping.class_from_name(node['name'].data)
setiv2obj(obj, node['ivars'], map)
when TYPE_SYMBOL when TYPE_SYMBOL
obj = node['id'].data.intern obj = node['id'].data.intern
setiv2obj(obj, node['ivars'], map)
when TYPE_STRUCT when TYPE_STRUCT
typestr = Mapping.elename2name(node['type'].data) typestr = Mapping.elename2name(node['type'].data)
klass = Mapping.class_from_name(typestr) klass = Mapping.class_from_name(typestr)
@ -333,40 +366,15 @@ private
obj = create_empty_object(klass) obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj) mark_unmarshalled_obj(node, obj)
node['member'].each do |name, value| node['member'].each do |name, value|
obj[Mapping.elename2name(name)] = obj[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
Mapping._soap2obj(value, map)
end end
setiv2obj(obj, node['ivars'], map)
else else
conv, obj = exception2obj(node, map) return unknowntype2obj(node, info, map)
unless conv
return false
end
setiv2obj(obj, node['ivars'], map)
end end
return true, obj return true, obj
end end
def exception2obj(node, map) def anytype2obj(node, info, 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)
case node case node
when SOAPBasetype when SOAPBasetype
return true, node.data return true, node.data
@ -383,22 +391,24 @@ private
end end
end end
def unknowntype2obj(node, map) def unknowntype2obj(node, info, map)
if node.is_a?(SOAPStruct) if node.is_a?(SOAPStruct)
obj = struct2obj(node, map) obj = unknownstruct2obj(node, info, map)
return true, obj if obj return true, obj if obj
if !@allow_untyped_struct if !@allow_untyped_struct
return false return false
end end
return anytype2obj(node, map) return anytype2obj(node, info, map)
else else
# Basetype which is not defined... # Basetype which is not defined...
return false return false
end end
end end
def struct2obj(node, map) def unknownstruct2obj(node, info, map)
obj = nil unless node.type.name
return nil
end
typestr = Mapping.elename2name(node.type.name) typestr = Mapping.elename2name(node.type.name)
klass = Mapping.class_from_name(typestr) klass = Mapping.class_from_name(typestr)
if klass.nil? if klass.nil?
@ -407,6 +417,9 @@ private
if klass.nil? if klass.nil?
return nil return nil
end end
if klass <= ::Exception
return exception2obj(klass, node, map)
end
klass_type = Mapping.class2qname(klass) klass_type = Mapping.class2qname(klass)
return nil unless node.type.match(klass_type) return nil unless node.type.match(klass_type)
obj = create_empty_object(klass) obj = create_empty_object(klass)
@ -415,6 +428,16 @@ private
obj obj
end 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. # Only creates empty array. Do String#replace it with real string.
def array2obj(node, map, rubytype) def array2obj(node, map, rubytype)
klass = rubytype ? Mapping.class_from_name(rubytype) : Array klass = rubytype ? Mapping.class_from_name(rubytype) : Array

View file

@ -58,10 +58,10 @@ module Marshal
def unmarshal(stream, mapping_registry = MarshalMappingRegistry) def unmarshal(stream, mapping_registry = MarshalMappingRegistry)
header, body = SOAP::Processor.unmarshal(stream) header, body = SOAP::Processor.unmarshal(stream)
#Mapping.soap2obj(body.root_node, mapping_registry)
Mapping.soap2obj(body.root_node, mapping_registry) Mapping.soap2obj(body.root_node, mapping_registry)
end end
end end
end end

View file

@ -50,6 +50,7 @@ class StandaloneServer < Logger::Application
def initialize(app_name, namespace, host = "0.0.0.0", port = 8080) def initialize(app_name, namespace, host = "0.0.0.0", port = 8080)
super(app_name) super(app_name)
self.level = Logger::Severity::INFO
@namespace = namespace @namespace = namespace
@host = host @host = host
@port = port @port = port

View file

@ -223,7 +223,8 @@ class WSDLDriver
@endpoint_url = nil @endpoint_url = nil
@wiredump_dev = nil @wiredump_dev = nil
@wiredump_file_base = 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_elements = @wsdl.collect_elements
@wsdl_types = @wsdl.collect_complextypes @wsdl_types = @wsdl.collect_complextypes

View file

@ -485,7 +485,7 @@ module XSDDateTimeImpl
def to_time def to_time
begin begin
if @data.of * SecInDay == Time.now.utc_offset if @data.offset * SecInDay == Time.now.utc_offset
d = @data d = @data
usec = (d.sec_fraction * SecInDay * 1000000).to_f usec = (d.sec_fraction * SecInDay * 1000000).to_f
Time.local(d.year, d.month, d.mday, d.hour, d.min, d.sec, usec) Time.local(d.year, d.month, d.mday, d.hour, d.min, d.sec, usec)
@ -643,7 +643,7 @@ private
s = format('%02d:%02d:%02d', @data.hour, @data.min, @data.sec) s = format('%02d:%02d:%02d', @data.hour, @data.min, @data.sec)
if @data.sec_fraction.nonzero? if @data.sec_fraction.nonzero?
fr = @data.sec_fraction * SecInDay fr = @data.sec_fraction * SecInDay
shiftsize = fr.denominator.to_s.size shiftsize = fr.denominator.to_s.size + 1
fr_s = (fr * (10 ** shiftsize)).to_i.to_s fr_s = (fr * (10 ** shiftsize)).to_i.to_s
s << '.' << '0' * (shiftsize - fr_s.size) << fr_s.sub(/0+$/, '') s << '.' << '0' * (shiftsize - fr_s.size) << fr_s.sub(/0+$/, '')
end end

View file

@ -61,6 +61,10 @@ class NamedElements
self self
end end
def delete(rhs)
@elements.delete(rhs)
end
def +(rhs) def +(rhs)
o = NamedElements.new o = NamedElements.new
o.elements = @elements + rhs.elements o.elements = @elements + rhs.elements

View file

@ -39,8 +39,7 @@ STDERR.reopen(File.open(errout, "w"))
STDERR.sync = true STDERR.sync = true
Dir.chdir(#{q(DIR)}) Dir.chdir(#{q(DIR)})
cmd = "\\"#{ruby}\\" \\"endblockwarn.rb\\"" cmd = "\\"#{ruby}\\" \\"endblockwarn.rb\\""
exec(cmd) system(cmd)
exit!("must not reach here")
EOF EOF
launcher.close launcher.close
launcherpath = launcher.path launcherpath = launcher.path

View file

@ -252,6 +252,19 @@ module MarshalTestLib
marshal_equal(o) {|obj| class << obj; ancestors end} marshal_equal(o) {|obj| class << obj; ancestors end}
end end
def test_extend_string
o = String.new
o.extend Mod1
marshal_equal(o) { |obj| obj.kind_of? Mod1 }
o = String.new
o.extend Module.new
assert_raises(TypeError) { marshaltest(o) }
o = String.new
o.extend Mod1
o.extend Mod2
marshal_equal(o) {|obj| class << obj; ancestors end}
end
def test_anonymous def test_anonymous
c = Class.new c = Class.new
assert_raises(TypeError) { marshaltest(c) } assert_raises(TypeError) { marshaltest(c) }

View file

@ -7,6 +7,10 @@ module Marshal
module MarshalTestLib module MarshalTestLib
module Mod1; end
module Mod2; end
def encode(o) def encode(o)
SOAPMarshal.dump(o) SOAPMarshal.dump(o)
end end
@ -23,19 +27,20 @@ module MarshalTestLib
o2 o2
end end
def marshal_equal(o1) def marshal_equal(o1, msg = nil)
msg = msg ? msg + "(#{ caller[0] })" : caller[0]
o2 = marshaltest(o1) o2 = marshaltest(o1)
assert_equal(o1.class, o2.class, caller[0]) assert_equal(o1.class, o2.class, msg)
iv1 = o1.instance_variables.sort iv1 = o1.instance_variables.sort
iv2 = o2.instance_variables.sort iv2 = o2.instance_variables.sort
assert_equal(iv1, iv2) assert_equal(iv1, iv2)
val1 = iv1.map {|var| o1.instance_eval {eval var}} val1 = iv1.map {|var| o1.instance_eval {eval var}}
val2 = iv1.map {|var| o2.instance_eval {eval var}} val2 = iv1.map {|var| o2.instance_eval {eval var}}
assert_equal(val1, val2, caller[0]) assert_equal(val1, val2, msg)
if block_given? if block_given?
assert_equal(yield(o1), yield(o2), caller[0]) assert_equal(yield(o1), yield(o2), msg)
else else
assert_equal(o1, o2, caller[0]) assert_equal(o1, o2, msg)
end end
end end
@ -50,6 +55,30 @@ module MarshalTestLib
marshal_equal(MyObject.new(2)) {|o| o.v} marshal_equal(MyObject.new(2)) {|o| o.v}
end end
def test_object_extend
o1 = Object.new
o1.extend(Mod1)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
o1.extend(Mod2)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
end
def test_object_subclass_extend
o1 = MyObject.new(2)
o1.extend(Mod1)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
o1.extend(Mod2)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
end
class MyArray < Array; def initialize(v, *args) super args; @v = v; end end class MyArray < Array; def initialize(v, *args) super args; @v = v; end end
def test_array def test_array
marshal_equal([1,2,3]) marshal_equal([1,2,3])
@ -59,6 +88,12 @@ module MarshalTestLib
marshal_equal(MyArray.new(0, 1,2,3)) marshal_equal(MyArray.new(0, 1,2,3))
end end
def test_array_ivar
o1 = Array.new
o1.instance_eval { @iv = 1 }
marshal_equal(o1) {|o| o.instance_eval { @iv }}
end
class MyException < Exception; def initialize(v, *args) super(*args); @v = v; end; attr_reader :v; end class MyException < Exception; def initialize(v, *args) super(*args); @v = v; end; attr_reader :v; end
def test_exception def test_exception
marshal_equal(Exception.new('foo')) {|o| o.message} marshal_equal(Exception.new('foo')) {|o| o.message}
@ -94,6 +129,36 @@ module MarshalTestLib
assert_raises(TypeError) { marshaltest(h) } assert_raises(TypeError) { marshaltest(h) }
end end
def test_hash_ivar
o1 = Hash.new
o1.instance_eval { @iv = 1 }
marshal_equal(o1) {|o| o.instance_eval { @iv }}
end
def test_hash_extend
o1 = Hash.new
o1.extend(Mod1)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
o1.extend(Mod2)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
end
def test_hash_subclass_extend
o1 = MyHash.new(2)
o1.extend(Mod1)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
o1.extend(Mod2)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
end
def test_bignum def test_bignum
marshal_equal(-0x4000_0000_0000_0001) marshal_equal(-0x4000_0000_0000_0001)
marshal_equal(-0x4000_0001) marshal_equal(-0x4000_0001)
@ -122,6 +187,24 @@ module MarshalTestLib
marshal_equal(-0.0) {|o| 1.0/o} marshal_equal(-0.0) {|o| 1.0/o}
end end
def test_float_ivar
o1 = 1.23
o1.instance_eval { @iv = 1 }
marshal_equal(o1) {|o| o.instance_eval { @iv }}
end
def test_float_extend
o1 = 0.0/0.0
o1.extend(Mod1)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
o1.extend(Mod2)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
end
class MyRange < Range; def initialize(v, *args) super(*args); @v = v; end end class MyRange < Range; def initialize(v, *args) super(*args); @v = v; end end
def test_range def test_range
marshal_equal(1..2) marshal_equal(1..2)
@ -129,19 +212,17 @@ module MarshalTestLib
end end
def test_range_subclass def test_range_subclass
STDERR.puts("test_range_subclass: known bug should be fixed.")
return
marshal_equal(MyRange.new(4,5,8, false)) marshal_equal(MyRange.new(4,5,8, false))
end end
class MyRegexp < Regexp; def initialize(v, *args) super(*args); @v = v; end end class MyRegexp < Regexp; def initialize(v, *args) super(*args); @v = v; end end
def test_regexp def test_regexp
marshal_equal(/a/) marshal_equal(/a/)
marshal_equal(/A/i)
marshal_equal(/A/mx)
end end
def test_regexp_subclass def test_regexp_subclass
STDERR.puts("test_regexp_subclass: known bug should be fixed.")
return
marshal_equal(MyRegexp.new(10, "a")) marshal_equal(MyRegexp.new(10, "a"))
end end
@ -150,10 +231,34 @@ module MarshalTestLib
marshal_equal("abc") marshal_equal("abc")
end end
def test_string_ivar
o1 = String.new
o1.instance_eval { @iv = 1 }
marshal_equal(o1) {|o| o.instance_eval { @iv }}
end
def test_string_subclass def test_string_subclass
marshal_equal(MyString.new(10, "a")) marshal_equal(MyString.new(10, "a"))
end end
def test_string_subclass_cycle
str = MyString.new(10, "b")
str.instance_eval { @v = str }
marshal_equal(str) { |o|
assert_equal(o.__id__, o.instance_eval { @v }.__id__)
o.instance_eval { @v }
}
end
def test_string_subclass_extend
o = "abc"
o.extend(Mod1)
str = MyString.new(o, "c")
marshal_equal(str) { |o|
assert(o.instance_eval { @v }).kind_of?(Mod1)
}
end
MyStruct = Struct.new("MyStruct", :a, :b) MyStruct = Struct.new("MyStruct", :a, :b)
class MySubStruct < MyStruct; def initialize(v, *args) super(*args); @v = v; end end class MySubStruct < MyStruct; def initialize(v, *args) super(*args); @v = v; end end
def test_struct def test_struct
@ -164,6 +269,24 @@ module MarshalTestLib
marshal_equal(MySubStruct.new(10,1,2)) marshal_equal(MySubStruct.new(10,1,2))
end end
def test_struct_ivar
o1 = MyStruct.new
o1.instance_eval { @iv = 1 }
marshal_equal(o1) {|o| o.instance_eval { @iv }}
end
def test_struct_subclass_extend
o1 = MyStruct.new
o1.extend(Mod1)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
o1.extend(Mod2)
marshal_equal(o1) { |o|
(class << self; self; end).ancestors
}
end
def test_symbol def test_symbol
marshal_equal(:a) marshal_equal(:a)
marshal_equal(:a?) marshal_equal(:a?)
@ -201,16 +324,21 @@ module MarshalTestLib
def test_time def test_time
# once there was a bug caused by usec overflow. try a little harder. # once there was a bug caused by usec overflow. try a little harder.
10.times do 10.times do
marshal_equal(Time.now) t = Time.now
marshal_equal(t, t.usec.to_s)
end end
end end
def test_time_subclass def test_time_subclass
STDERR.puts("test_time_subclass: known bug should be fixed.")
return
marshal_equal(MyTime.new(10)) marshal_equal(MyTime.new(10))
end end
def test_time_ivar
o1 = Time.now
o1.instance_eval { @iv = 1 }
marshal_equal(o1) {|o| o.instance_eval { @iv }}
end
def test_true def test_true
marshal_equal(true) marshal_equal(true)
end end
@ -250,15 +378,7 @@ module MarshalTestLib
assert_raises(TypeError) { marshaltest(ENV) } assert_raises(TypeError) { marshaltest(ENV) }
end end
module Mod1 end
module Mod2 end
def test_extend def test_extend
o = Object.new
o.extend Module.new
assert_raises(TypeError) { marshaltest(o) }
STDERR.puts("test_range_subclass: known bug should be fixed.")
return
o = Object.new o = Object.new
o.extend Mod1 o.extend Mod1
marshal_equal(o) { |obj| obj.kind_of? Mod1 } marshal_equal(o) { |obj| obj.kind_of? Mod1 }
@ -266,6 +386,22 @@ module MarshalTestLib
o.extend Mod1 o.extend Mod1
o.extend Mod2 o.extend Mod2
marshal_equal(o) {|obj| class << obj; ancestors end} marshal_equal(o) {|obj| class << obj; ancestors end}
o = Object.new
o.extend Module.new
assert_raises(TypeError) { marshaltest(o) }
end
def test_extend_string
o = String.new
o.extend Mod1
marshal_equal(o) { |obj| obj.kind_of? Mod1 }
o = String.new
o.extend Mod1
o.extend Mod2
marshal_equal(o) {|obj| class << obj; ancestors end}
o = String.new
o.extend Module.new
assert_raises(TypeError) { marshaltest(o) }
end end
def test_anonymous def test_anonymous

View file

@ -8,7 +8,6 @@
xmlns:i2="http://www.winfessor.com/SoapBoxWebService/ExceptionDataSet.xsd" xmlns:i2="http://www.winfessor.com/SoapBoxWebService/ExceptionDataSet.xsd"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:i0="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd" xmlns:i0="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://www.winfessor.com/SoapBoxWebService/SoapBoxWebService" targetNamespace="http://www.winfessor.com/SoapBoxWebService/SoapBoxWebService"
xmlns="http://schemas.xmlsoap.org/wsdl/"> xmlns="http://schemas.xmlsoap.org/wsdl/">

View file

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:mstns="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd" id="MessageDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:schema
<xs:element msdata:IsDataSet="true" name="MessageDataSet"> xmlns:mstns="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd"
xmlns="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd"
attributeFormDefault="qualified"
elementFormDefault="qualified"
targetNamespace="http://www.winfessor.com/SoapBoxWebService/MessageDataSet.xsd"
id="MessageDataSet"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="MessageDataSet">
<xs:complexType> <xs:complexType>
<xs:choice maxOccurs="unbounded" /> <xs:choice maxOccurs="unbounded" />
</xs:complexType> </xs:complexType>