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

* lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.5.

#nnn is a ticket number at http://dev.ctor.org/soap4r

          * SOAP

            * allow to configure an envelope namespace of SOAP request. (#124)
                TemporaryNamespace = 'http://www.w3.org/2003/05/soap-envelope'
                @client.options["soap.envelope.requestnamespace"] =
                  TemporaryNamespace
                @client.options["soap.envelope.responsenamespace"] =
                  TemporaryNamespace
                @client.do_proc(...)

            * let SOAP request XML indent space configuable.  see
              "soap.envelope.no_indent" option. (#130)

            * let external CES configuable.
              ex. client["soap.mapping.external_ces"] = 'SJIS'.  $KCODE is used
              by default. (#133)
                external CES ::= CES used in Ruby object of client and server
                internal CES ::= CES used in SOAP/OM

            * add iso-8859-1 external CES support. (#106)

            * fixed illegal 'qualified' handling of elements.  it caused
              ASP.NET inteoperability problem. (#144)

            * added 'soap.envelope.use_numeric_character_reference' (boolean)
              option to let query XML use numeric character reference in XML,
              not plain UTF-8 character.  !GoogleSearch server seems to not
              allow plain UTF-8 character since 2005-08-15 update. (#147)

            * SOAP::Header::SimpleHeader (de)serialization throws an exception
              on !SimpleHeader.on_(in|out)bound when header is a String.  so we
              could not use a simple single element headerItem.  fixed.  thanks
              to emil. (#129)

            * out parameter of rpc operation did not work.  (#132)

            * follow HTTP redirect only if using http-access2.  (#125) (#145)

            * add a workaround for importing an WSDL whose path begins with
              drive letter.  (#115)

          * WSDL

            * SOAP Data which is defined as a simpletype was not mapped
              correctly to Ruby obj when using wsdl2ruby.rb generated classdef
              file. (#123)

            * rpc/literal support. (#118)

            * re-implemented local element qualify/unqualify control.  handles
              elementFormDefault and form in WSDL.  (#119)

            * Array of an element which has simpleType causes a crash. (#128)

            * prarmeterOrder may not contain return part so it can be shorter
              than parts size.  Thanks to Hugh.  (#139)

          * Samples

            * added !BasicAuth client sample. (#117)

            * added Base64 client/server sample.

            * added Flickr SOAP interface client sample. (#122)

            * added !SalesForce client sample. (#135)

            * updated Thawte CA certificate for !GoogleAdWords sample.

            * updated a client script with the newer version made by Johan.
              thanks!

            * shortened long file names. (#120)

            * fixed typo in authheader sample. (#129)

            * updated deprecated method usage.  (#138)


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9171 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nahi 2005-09-15 14:47:07 +00:00
parent caf6ad3a76
commit 533c24268e
54 changed files with 920 additions and 617 deletions

View file

@ -1,3 +1,87 @@
Thu Sep 15 23:25:21 2005 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
* lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.5.
#nnn is a ticket number at http://dev.ctor.org/soap4r
* SOAP
* allow to configure an envelope namespace of SOAP request. (#124)
TemporaryNamespace = 'http://www.w3.org/2003/05/soap-envelope'
@client.options["soap.envelope.requestnamespace"] =
TemporaryNamespace
@client.options["soap.envelope.responsenamespace"] =
TemporaryNamespace
@client.do_proc(...)
* let SOAP request XML indent space configuable. see
"soap.envelope.no_indent" option. (#130)
* let external CES configuable.
ex. client["soap.mapping.external_ces"] = 'SJIS'. $KCODE is used
by default. (#133)
external CES ::= CES used in Ruby object of client and server
internal CES ::= CES used in SOAP/OM
* add iso-8859-1 external CES support. (#106)
* fixed illegal 'qualified' handling of elements. it caused
ASP.NET inteoperability problem. (#144)
* added 'soap.envelope.use_numeric_character_reference' (boolean)
option to let query XML use numeric character reference in XML,
not plain UTF-8 character. !GoogleSearch server seems to not
allow plain UTF-8 character since 2005-08-15 update. (#147)
* SOAP::Header::SimpleHeader (de)serialization throws an exception
on !SimpleHeader.on_(in|out)bound when header is a String. so we
could not use a simple single element headerItem. fixed. thanks
to emil. (#129)
* out parameter of rpc operation did not work. (#132)
* follow HTTP redirect only if using http-access2. (#125) (#145)
* add a workaround for importing an WSDL whose path begins with
drive letter. (#115)
* WSDL
* SOAP Data which is defined as a simpletype was not mapped
correctly to Ruby obj when using wsdl2ruby.rb generated classdef
file. (#123)
* rpc/literal support. (#118)
* re-implemented local element qualify/unqualify control. handles
elementFormDefault and form in WSDL. (#119)
* Array of an element which has simpleType causes a crash. (#128)
* prarmeterOrder may not contain return part so it can be shorter
than parts size. Thanks to Hugh. (#139)
* Samples
* added !BasicAuth client sample. (#117)
* added Base64 client/server sample.
* added Flickr SOAP interface client sample. (#122)
* added !SalesForce client sample. (#135)
* updated Thawte CA certificate for !GoogleAdWords sample.
* updated a client script with the newer version made by Johan.
thanks!
* shortened long file names. (#120)
* fixed typo in authheader sample. (#129)
* updated deprecated method usage. (#138)
Thu Sep 15 23:02:57 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> Thu Sep 15 23:02:57 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
* win32/win32.h (rb_w32_stat): added prototype. * win32/win32.h (rb_w32_stat): added prototype.

View file

@ -44,9 +44,9 @@ module SOAPType
attr_accessor :definedtype attr_accessor :definedtype
def initialize(*arg) def initialize(*arg)
super(*arg) super
@encodingstyle = nil @encodingstyle = nil
@elename = XSD::QName.new @elename = XSD::QName::EMPTY
@id = nil @id = nil
@precedents = [] @precedents = []
@root = false @root = false
@ -82,7 +82,7 @@ module SOAPBasetype
include SOAP include SOAP
def initialize(*arg) def initialize(*arg)
super(*arg) super
end end
end end
@ -95,7 +95,7 @@ module SOAPCompoundtype
include SOAP include SOAP
def initialize(*arg) def initialize(*arg)
super(*arg) super
end end
end end
@ -114,7 +114,7 @@ public
# Override the definition in SOAPBasetype. # Override the definition in SOAPBasetype.
def initialize(obj = nil) def initialize(obj = nil)
super() super()
@type = XSD::QName.new @type = XSD::QName::EMPTY
@refid = nil @refid = nil
@obj = nil @obj = nil
__setobj__(obj) if obj __setobj__(obj) if obj
@ -178,7 +178,7 @@ class SOAPExternalReference < XSD::NSDBase
def initialize def initialize
super() super()
@type = XSD::QName.new @type = XSD::QName::EMPTY
end end
def referred def referred
@ -399,7 +399,7 @@ public
def initialize(type = nil) def initialize(type = nil)
super() super()
@type = type || XSD::QName.new @type = type || XSD::QName::EMPTY
@array = [] @array = []
@data = [] @data = []
end end
@ -470,8 +470,10 @@ public
end end
def each def each
for i in 0..(@array.length - 1) idx = 0
yield(@array[i], @data[i]) while idx < @array.length
yield(@array[idx], @data[idx])
idx += 1
end end
end end
@ -529,7 +531,7 @@ class SOAPElement
@position = nil @position = nil
@extraattr = {} @extraattr = {}
@qualified = false @qualified = nil
@array = [] @array = []
@data = [] @data = []
@ -598,8 +600,10 @@ class SOAPElement
end end
def each def each
for i in 0..(@array.length - 1) idx = 0
yield(@array[i], @data[i]) while idx < @array.length
yield(@array[idx], @data[idx])
idx += 1
end end
end end
@ -737,27 +741,25 @@ public
" does not match rank: #{@rank}") " does not match rank: #{@rank}")
end end
for i in 0..(idxary.size - 1) idx = 0
if idxary[i] + 1 > @size[i] while idx < idxary.size
@size[i] = idxary[i] + 1 if idxary[idx] + 1 > @size[idx]
@size[idx] = idxary[idx] + 1
end end
idx += 1
end end
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?(SOAPType) if value.is_a?(SOAPType)
value.elename = value.elename.dup_name('item') value.elename = ITEM_NAME
# Sync type # Sync type
unless @type.name unless @type.name
@type = XSD::QName.new(value.type.namespace, @type = XSD::QName.new(value.type.namespace,
SOAPArray.create_arytype(value.type.name, @rank)) SOAPArray.create_arytype(value.type.name, @rank))
end end
value.type ||= @type
unless value.type
value.type = @type
end
end end
@offset = idxary @offset = idxary
@ -787,7 +789,7 @@ public
deep_map(ele, &block) deep_map(ele, &block)
else else
new_obj = block.call(ele) new_obj = block.call(ele)
new_obj.elename = new_obj.elename.dup_name('item') new_obj.elename = ITEM_NAME
new_obj new_obj
end end
end end
@ -815,13 +817,15 @@ public
def soap2array(ary) def soap2array(ary)
traverse_data(@data) do |v, *position| traverse_data(@data) do |v, *position|
iteary = ary iteary = ary
for rank in 1..(position.size - 1) rank = 1
while rank < position.size
idx = position[rank - 1] idx = position[rank - 1]
if iteary[idx].nil? if iteary[idx].nil?
iteary = iteary[idx] = Array.new iteary = iteary[idx] = Array.new
else else
iteary = iteary[idx] iteary = iteary[idx]
end end
rank += 1
end end
if block_given? if block_given?
iteary[position.last] = yield(v) iteary[position.last] = yield(v)
@ -837,21 +841,26 @@ public
private private
ITEM_NAME = XSD::QName.new(nil, 'item')
def retrieve(idxary) def retrieve(idxary)
data = @data data = @data
for rank in 1..(idxary.size) rank = 1
while rank <= idxary.size
idx = idxary[rank - 1] idx = idxary[rank - 1]
if data[idx].nil? if data[idx].nil?
data = data[idx] = Array.new data = data[idx] = Array.new
else else
data = data[idx] data = data[idx]
end end
rank += 1
end end
data data
end end
def traverse_data(data, rank = 1) def traverse_data(data, rank = 1)
for idx in 0..(ranksize(rank) - 1) idx = 0
while idx < ranksize(rank)
if rank < @rank if rank < @rank
traverse_data(data[idx], rank + 1) do |*v| traverse_data(data[idx], rank + 1) do |*v|
v[1, 0] = idx v[1, 0] = idx
@ -860,6 +869,7 @@ private
else else
yield(data[idx], idx) yield(data[idx], idx)
end end
idx += 1
end end
end end

View file

@ -83,10 +83,10 @@ public
attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
name = ns.name(@elename) name = ns.name(@elename)
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
yield(self.faultcode, false) yield(self.faultcode)
yield(self.faultstring, false) yield(self.faultstring)
yield(self.faultactor, false) yield(self.faultactor)
yield(self.detail, false) if self.detail yield(self.detail) if self.detail
generator.encode_tag_end(name, true) generator.encode_tag_end(name, true)
end end
end end
@ -115,10 +115,10 @@ class SOAPBody < SOAPStruct
name = ns.name(@elename) name = ns.name(@elename)
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
if @is_fault if @is_fault
yield(@data, true) yield(@data)
else else
@data.each do |data| @data.each do |data|
yield(data, true) yield(data)
end end
end end
generator.encode_tag_end(name, true) generator.encode_tag_end(name, true)
@ -171,7 +171,7 @@ public
@element.extraattr[ns.name(AttrEncodingStyleName)] = @encodingstyle @element.extraattr[ns.name(AttrEncodingStyleName)] = @encodingstyle
end end
@element.encodingstyle = @encodingstyle if !@element.encodingstyle @element.encodingstyle = @encodingstyle if !@element.encodingstyle
yield(@element, true) yield(@element)
end end
end end
@ -189,7 +189,7 @@ class SOAPHeader < SOAPStruct
name = ns.name(@elename) name = ns.name(@elename)
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
@data.each do |data| @data.each do |data|
yield(data, true) yield(data)
end end
generator.encode_tag_end(name, true) generator.encode_tag_end(name, true)
end end
@ -239,12 +239,12 @@ class SOAPEnvelope < XSD::NSDBase
end end
def encode(generator, ns, attrs = {}) def encode(generator, ns, attrs = {})
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace, SOAPNamespaceTag) SOAPGenerator.assign_ns(attrs, ns, elename.namespace, SOAPNamespaceTag)
name = ns.name(@elename) name = ns.name(@elename)
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
yield(@header, true) if @header and @header.length > 0 yield(@header) if @header and @header.length > 0
yield(@body, true) yield(@body)
generator.encode_tag_end(name, true) generator.encode_tag_end(name, true)
end end

View file

@ -27,38 +27,36 @@ class ASPDotNetHandler < Handler
### ###
## encode interface. ## encode interface.
# #
def encode_data(generator, ns, qualified, data, parent) def encode_data(generator, ns, data, parent)
attrs = {} attrs = {}
name = if qualified and data.elename.namespace # ASPDotNetHandler is intended to be used for accessing an ASP.NET doc/lit
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '') # service as an rpc/encoded service. in the situation, local elements
ns.name(data.elename) # should be qualified. propagate parent's namespace to children.
else if data.elename.namespace.nil?
data.elename.name data.elename.namespace = parent.elename.namespace
end end
name = generator.encode_name(ns, data, attrs)
case data case data
when SOAPRawString when SOAPRawString
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
generator.encode_rawstring(data.to_s) generator.encode_rawstring(data.to_s)
when XSD::XSDString when XSD::XSDString
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
generator.encode_string(@charset ? XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s) generator.encode_string(@charset ?
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
when XSD::XSDAnySimpleType when XSD::XSDAnySimpleType
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
generator.encode_string(data.to_s) generator.encode_string(data.to_s)
when SOAPStruct when SOAPStruct
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
data.each do |key, value| data.each do |key, value|
if !value.elename.namespace generator.encode_child(ns, value, data)
value.elename.namespace = data.elename.namespace
end
yield(value, true)
end end
when SOAPArray when SOAPArray
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
data.traverse do |child, *rank| data.traverse do |child, *rank|
data.position = nil data.position = nil
yield(child, true) generator.encode_child(ns, child, data)
end end
else else
raise EncodingStyleError.new( raise EncodingStyleError.new(
@ -66,12 +64,8 @@ class ASPDotNetHandler < Handler
end end
end end
def encode_data_end(generator, ns, qualified, data, parent) def encode_data_end(generator, ns, data, parent)
name = if qualified and data.elename.namespace name = generator.encode_name_end(ns, data)
ns.name(data.elename)
else
data.elename.name
end
cr = data.is_a?(SOAPCompoundtype) cr = data.is_a?(SOAPCompoundtype)
generator.encode_tag_end(name, cr) generator.encode_tag_end(name, cr)
end end

View file

@ -58,12 +58,12 @@ class Handler
## encode interface. ## encode interface.
# #
# Returns a XML instance as a string. # Returns a XML instance as a string.
def encode_data(generator, ns, qualified, data, parent) def encode_data(generator, ns, data, parent)
raise NotImplementError.new('Method encode_data must be defined in derived class.') raise NotImplementError
end end
def encode_data_end(generator, ns, qualified, data, parent) def encode_data_end(generator, ns, data, parent)
raise NotImplementError.new('Method encode_data must be defined in derived class.') raise NotImplementError
end end
def encode_prologue def encode_prologue

View file

@ -26,15 +26,11 @@ class LiteralHandler < Handler
### ###
## encode interface. ## encode interface.
# #
def encode_data(generator, ns, qualified, data, parent) def encode_data(generator, ns, data, parent)
attrs = {} attrs = {}
name = if qualified and data.elename.namespace name = generator.encode_name(ns, data, attrs)
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '')
ns.name(data.elename)
else
data.elename.name
end
data.extraattr.each do |k, v| data.extraattr.each do |k, v|
# ToDo: check generator.attributeformdefault here
if k.is_a?(XSD::QName) if k.is_a?(XSD::QName)
if k.namespace if k.namespace
SOAPGenerator.assign_ns(attrs, ns, k.namespace) SOAPGenerator.assign_ns(attrs, ns, k.namespace)
@ -45,7 +41,6 @@ class LiteralHandler < Handler
end end
attrs[k] = v attrs[k] = v
end end
case data case data
when SOAPRawString when SOAPRawString
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
@ -61,22 +56,25 @@ class LiteralHandler < Handler
when SOAPStruct when SOAPStruct
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
data.each do |key, value| data.each do |key, value|
if !value.elename.namespace generator.encode_child(ns, value, data)
value.elename.namespace = data.elename.namespace
end
yield(value, true)
end end
when SOAPArray when SOAPArray
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
data.traverse do |child, *rank| data.traverse do |child, *rank|
data.position = nil data.position = nil
yield(child, true) generator.encode_child(ns, child, data)
end end
when SOAPElement when SOAPElement
# passes 2 times for simplifying namespace definition
data.each do |key, value|
if value.elename.namespace
SOAPGenerator.assign_ns(attrs, ns, value.elename.namespace)
end
end
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
generator.encode_rawstring(data.text) if data.text generator.encode_rawstring(data.text) if data.text
data.each do |key, value| data.each do |key, value|
yield(value, qualified) generator.encode_child(ns, value, data)
end end
else else
raise EncodingStyleError.new( raise EncodingStyleError.new(
@ -84,12 +82,8 @@ class LiteralHandler < Handler
end end
end end
def encode_data_end(generator, ns, qualified, data, parent) def encode_data_end(generator, ns, data, parent)
name = if qualified and data.elename.namespace name = generator.encode_name_end(ns, data)
ns.name(data.elename)
else
data.elename.name
end
cr = (data.is_a?(SOAPCompoundtype) or cr = (data.is_a?(SOAPCompoundtype) or
(data.is_a?(SOAPElement) and !data.text)) (data.is_a?(SOAPElement) and !data.text))
generator.encode_tag_end(name, cr) generator.encode_tag_end(name, cr)

View file

@ -29,21 +29,12 @@ class SOAPHandler < Handler
### ###
## encode interface. ## encode interface.
# #
def encode_data(generator, ns, qualified, data, parent) def encode_data(generator, ns, data, parent)
attrs = encode_attrs(generator, ns, 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(',')}]"
end end
name = generator.encode_name(ns, data, attrs)
name = nil
if qualified and data.elename.namespace
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
name = ns.name(data.elename)
else
name = data.elename.name
end
case data case data
when SOAPReference when SOAPReference
attrs['href'] = data.refidstr attrs['href'] = data.refidstr
@ -65,13 +56,13 @@ class SOAPHandler < Handler
when SOAPStruct when SOAPStruct
generator.encode_tag(name, attrs) generator.encode_tag(name, attrs)
data.each do |key, value| data.each do |key, value|
yield(value, false) generator.encode_child(ns, value, data)
end end
when SOAPArray when SOAPArray
generator.encode_tag(name, attrs) 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) generator.encode_child(ns, child, data)
end end
else else
raise EncodingStyleError.new( raise EncodingStyleError.new(
@ -79,12 +70,8 @@ class SOAPHandler < Handler
end end
end end
def encode_data_end(generator, ns, qualified, data, parent) def encode_data_end(generator, ns, data, parent)
name = if qualified and data.elename.namespace name = generator.encode_name_end(ns, data)
ns.name(data.elename)
else
data.elename.name
end
cr = data.is_a?(SOAPCompoundtype) cr = data.is_a?(SOAPCompoundtype)
generator.encode_tag_end(name, cr) generator.encode_tag_end(name, cr)
end end
@ -268,8 +255,8 @@ private
end end
def encode_attrs(generator, ns, data, parent) def encode_attrs(generator, ns, data, parent)
return {} if data.is_a?(SOAPReference)
attrs = {} attrs = {}
return attrs if data.is_a?(SOAPReference)
if !parent || parent.encodingstyle != EncodingNamespace if !parent || parent.encodingstyle != EncodingNamespace
if @generate_explicit_type if @generate_explicit_type

View file

@ -1,5 +1,5 @@
# SOAP4R - SOAP XML Instance Generator library. # SOAP4R - SOAP XML Instance Generator library.
# Copyright (C) 2001, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. # Copyright (C) 2001, 2003, 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can # This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license; # redistribute it and/or modify it under the same terms of Ruby's license;
@ -28,14 +28,19 @@ 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 :use_numeric_character_reference
def initialize(opt = {}) def initialize(opt = {})
@reftarget = nil @reftarget = nil
@handlers = {} @handlers = {}
@charset = opt[:charset] || XSD::Charset.encoding_label @charset = opt[:charset] || XSD::Charset.xml_encoding_label
@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
@elementformdefault = opt[:elementformdefault]
@attributeformdefault = opt[:attributeformdefault]
@use_numeric_character_reference = opt[:use_numeric_character_reference]
@indentstr = opt[:no_indent] ? '' : ' '
@buf = @indent = @curr = nil @buf = @indent = @curr = nil
end end
@ -50,7 +55,7 @@ public
ns = XSD::NS.new ns = XSD::NS.new
@buf << xmldecl @buf << xmldecl
encode_data(ns, true, obj, nil) encode_data(ns, obj, nil)
@handlers.each do |uri, handler| @handlers.each do |uri, handler|
handler.encode_epilogue handler.encode_epilogue
@ -60,42 +65,33 @@ public
@buf @buf
end end
def encode_data(ns, qualified, obj, parent) def encode_data(ns, obj, parent)
if obj.is_a?(SOAPEnvelopeElement) if obj.is_a?(SOAPEnvelopeElement)
encode_element(ns, qualified, obj, parent) encode_element(ns, obj, parent)
return return
end end
if @reftarget && !obj.precedents.empty? if @reftarget && !obj.precedents.empty?
add_reftarget(obj.elename.name, obj) add_reftarget(obj.elename.name, obj)
ref = SOAPReference.new(obj) ref = SOAPReference.new(obj)
ref.elename.name = obj.elename.name ref.elename = ref.elename.dup_name(obj.elename.name)
obj.precedents.clear # Avoid cyclic delay. obj.precedents.clear # Avoid cyclic delay.
obj.encodingstyle = parent.encodingstyle obj.encodingstyle = parent.encodingstyle
# SOAPReference is encoded here. # SOAPReference is encoded here.
obj = ref obj = ref
end end
encodingstyle = obj.encodingstyle encodingstyle = obj.encodingstyle
# Children's encodingstyle is derived from its parent. # Children's encodingstyle is derived from its parent.
encodingstyle ||= parent.encodingstyle if parent encodingstyle ||= parent.encodingstyle if parent
obj.encodingstyle = encodingstyle obj.encodingstyle = encodingstyle
handler = find_handler(encodingstyle || @default_encodingstyle) handler = find_handler(encodingstyle || @default_encodingstyle)
unless handler unless handler
raise FormatEncodeError.new("Unknown encodingStyle: #{ encodingstyle }.") raise FormatEncodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
end end
if !obj.elename.name if !obj.elename.name
raise FormatEncodeError.new("Element name not defined: #{ obj }.") raise FormatEncodeError.new("Element name not defined: #{ obj }.")
end end
handler.encode_data(self, ns, obj, parent)
handler.encode_data(self, ns, qualified, obj, parent) do |child, nextq| handler.encode_data_end(self, ns, obj, parent)
indent_backup, @indent = @indent, @indent + ' '
encode_data(ns.clone_ns, nextq, child, obj)
@indent = indent_backup
end
handler.encode_data_end(self, ns, qualified, obj, parent)
end end
def add_reftarget(name, node) def add_reftarget(name, node)
@ -105,13 +101,19 @@ public
@reftarget.add(name, node) @reftarget.add(name, node)
end end
def encode_element(ns, qualified, obj, parent) def encode_child(ns, child, parent)
indent_backup, @indent = @indent, @indent + @indentstr
encode_data(ns.clone_ns, child, parent)
@indent = indent_backup
end
def encode_element(ns, obj, parent)
attrs = {} attrs = {}
if obj.is_a?(SOAPBody) if obj.is_a?(SOAPBody)
@reftarget = obj @reftarget = obj
obj.encode(self, ns, attrs) do |child, nextq| obj.encode(self, ns, attrs) do |child|
indent_backup, @indent = @indent, @indent + ' ' indent_backup, @indent = @indent, @indent + @indentstr
encode_data(ns.clone_ns, nextq, child, obj) encode_data(ns.clone_ns, child, obj)
@indent = indent_backup @indent = indent_backup
end end
@reftarget = nil @reftarget = nil
@ -124,14 +126,35 @@ public
SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag) SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag)
end end
end end
obj.encode(self, ns, attrs) do |child, nextq| obj.encode(self, ns, attrs) do |child|
indent_backup, @indent = @indent, @indent + ' ' indent_backup, @indent = @indent, @indent + @indentstr
encode_data(ns.clone_ns, nextq, child, obj) encode_data(ns.clone_ns, child, obj)
@indent = indent_backup @indent = indent_backup
end end
end end
end end
def encode_name(ns, data, attrs)
if element_local?(data)
data.elename.name
else
if element_qualified?(data)
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '')
else
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
end
ns.name(data.elename)
end
end
def encode_name_end(ns, data)
if element_local?(data)
data.elename.name
else
ns.name(data.elename)
end
end
def encode_tag(elename, attrs = nil) def encode_tag(elename, attrs = nil)
if !attrs or attrs.empty? if !attrs or attrs.empty?
@buf << "\n#{ @indent }<#{ elename }>" @buf << "\n#{ @indent }<#{ elename }>"
@ -142,7 +165,7 @@ public
@buf << "\n#{ @indent }<#{ elename } " << @buf << "\n#{ @indent }<#{ elename } " <<
attrs.collect { |key, value| attrs.collect { |key, value|
%Q[#{ key }="#{ value }"] %Q[#{ key }="#{ value }"]
}.join("\n#{ @indent } ") << }.join("\n#{ @indent }#{ @indentstr * 2 }") <<
'>' '>'
end end
end end
@ -169,11 +192,41 @@ public
} }
EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]") EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]")
def encode_string(str) def encode_string(str)
@buf << str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] } if @use_numeric_character_reference and !XSD::Charset.is_us_ascii(str)
str.gsub!(EncodeCharRegexp) { |c| EncodeMap[c] }
@buf << str.unpack("U*").collect { |c|
if c == 0x9 or c == 0xa or c == 0xd or (c >= 0x20 and c <= 0x7f)
c.chr
else
sprintf("&#x%x;", c)
end
}.join
else
@buf << str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] }
end
end
def element_local?(element)
element.elename.namespace.nil?
end
def element_qualified?(element)
if element.respond_to?(:qualified)
if element.qualified.nil?
@elementformdefault
else
element.qualified
end
else
@elementformdefault
end
end end
def self.assign_ns(attrs, ns, namespace, tag = nil) def self.assign_ns(attrs, ns, namespace, tag = nil)
if namespace and !ns.assigned?(namespace) if namespace.nil?
raise FormatEncodeError.new("empty namespace")
end
unless ns.assigned?(namespace)
tag = ns.assign(namespace, tag) tag = ns.assign(namespace, tag)
if tag == '' if tag == ''
attr = 'xmlns' attr = 'xmlns'

View file

@ -19,12 +19,12 @@ class SimpleHandler < SOAP::Header::Handler
super(elename) super(elename)
end end
# Should return a Hash or nil. # Should return a Hash, String or nil.
def on_simple_outbound def on_simple_outbound
nil nil
end end
# Given header is a Hash or nil. # Given header is a Hash, String or nil.
def on_simple_inbound(header, mustunderstand) def on_simple_inbound(header, mustunderstand)
end end
@ -34,7 +34,7 @@ class SimpleHandler < SOAP::Header::Handler
end end
def on_inbound(header, mustunderstand) def on_inbound(header, mustunderstand)
h = header.to_obj h = header.respond_to?(:to_obj) ? header.to_obj : header.data
on_simple_inbound(h, mustunderstand) on_simple_inbound(h, mustunderstand)
end end
end end

View file

@ -60,6 +60,9 @@ module_function
def set_ssl_config(client, ssl_config) def set_ssl_config(client, ssl_config)
ssl_config.each do |key, value| ssl_config.each do |key, value|
cfg = client.ssl_config cfg = client.ssl_config
if cfg.nil?
raise NotImplementedError.new("SSL not supported")
end
case key case key
when 'client_cert' when 'client_cert'
cfg.client_cert = cert_from_file(value) cfg.client_cert = cert_from_file(value)

View file

@ -87,10 +87,11 @@ class StringFactory_ < Factory
return nil return nil
end end
begin begin
unless XSD::Charset.is_ces(obj, $KCODE) unless XSD::Charset.is_ces(obj, Thread.current[:SOAPExternalCES])
return nil return nil
end end
encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) encoded = XSD::Charset.encoding_conv(obj,
Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
soap_obj = soap_class.new(encoded) soap_obj = soap_class.new(encoded)
rescue XSD::ValueSpaceError rescue XSD::ValueSpaceError
return nil return nil
@ -101,7 +102,8 @@ class StringFactory_ < Factory
def soap2obj(obj_class, node, info, map) def soap2obj(obj_class, node, info, map)
obj = Mapping.create_empty_object(obj_class) obj = Mapping.create_empty_object(obj_class)
decoded = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding, $KCODE) decoded = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding,
Thread.current[:SOAPExternalCES])
obj.replace(decoded) obj.replace(decoded)
mark_unmarshalled_obj(node, obj) mark_unmarshalled_obj(node, obj)
return true, obj return true, obj

View file

@ -49,8 +49,7 @@ class SOAPException; include Marshallable
e.set_backtrace(@cause.backtrace) e.set_backtrace(@cause.backtrace)
return e return e
end end
klass = Mapping.class_from_name( klass = Mapping.class_from_name(Mapping.elename2name(@excn_type_name.to_s))
Mapping.elename2name(@excn_type_name.to_s))
if klass.nil? or not klass <= ::Exception if klass.nil? or not klass <= ::Exception
return RuntimeError.new(@cause.inspect) return RuntimeError.new(@cause.inspect)
end end
@ -89,6 +88,10 @@ class Object; include Marshallable
@__xmlele.each do |k, v| @__xmlele.each do |k, v|
return v if k == qname return v if k == qname
end end
# fallback
@__xmlele.each do |k, v|
return v if k.name == qname.name
end
nil nil
end end

View file

@ -1,155 +0,0 @@
# SOAP4R - WSDL mapping registry.
# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
require 'soap/baseData'
require 'soap/mapping/mapping'
require 'soap/mapping/typeMap'
module SOAP
module Mapping
class WSDLRegistry
include TraverseSupport
attr_reader :definedtypes
def initialize(definedtypes, config = {})
@definedtypes = definedtypes
@config = config
@excn_handler_obj2soap = nil
# For mapping AnyType element.
@rubytype_factory = RubytypeFactory.new(
:allow_untyped_struct => true,
:allow_original_mapping => true
)
end
def obj2soap(klass, obj, type_qname)
soap_obj = nil
if obj.nil?
soap_obj = SOAPNil.new
elsif obj.is_a?(XSD::NSDBase)
soap_obj = soap2soap(obj, type_qname)
elsif type = @definedtypes[type_qname]
soap_obj = obj2type(obj, type)
elsif (type = TypeMap[type_qname])
soap_obj = base2soap(obj, type)
elsif type_qname == XSD::AnyTypeName
soap_obj = @rubytype_factory.obj2soap(nil, obj, nil, nil)
end
return soap_obj if soap_obj
if @excn_handler_obj2soap
soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
Mapping._obj2soap(yield_obj, self)
}
end
return soap_obj if soap_obj
raise MappingError.new("Cannot map #{ klass.name } to SOAP/OM.")
end
def soap2obj(klass, node)
raise RuntimeError.new("#{ self } is for obj2soap only.")
end
def excn_handler_obj2soap=(handler)
@excn_handler_obj2soap = handler
end
private
def soap2soap(obj, type_qname)
if obj.is_a?(SOAPBasetype)
obj
elsif obj.is_a?(SOAPStruct) && (type = @definedtypes[type_qname])
soap_obj = obj
mark_marshalled_obj(obj, soap_obj)
elements2soap(obj, soap_obj, type.content.elements)
soap_obj
elsif obj.is_a?(SOAPArray) && (type = @definedtypes[type_qname])
soap_obj = obj
contenttype = type.child_type
mark_marshalled_obj(obj, soap_obj)
obj.replace do |ele|
Mapping._obj2soap(ele, self, contenttype)
end
soap_obj
else
nil
end
end
def obj2type(obj, type)
if type.is_a?(::WSDL::XMLSchema::SimpleType)
simple2soap(obj, type)
else
complex2soap(obj, type)
end
end
def simple2soap(obj, type)
o = base2soap(obj, TypeMap[type.base])
if type.restriction.enumeration.empty?
STDERR.puts("#{type.name}: simpleType which is not enum type not supported.")
return o
end
type.check_lexical_format(obj)
o
end
def complex2soap(obj, type)
case type.compoundtype
when :TYPE_STRUCT
struct2soap(obj, type.name, type)
when :TYPE_ARRAY
array2soap(obj, type.name, type)
end
end
def base2soap(obj, type)
soap_obj = nil
if type <= XSD::XSDString
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ?
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj)
mark_marshalled_obj(obj, soap_obj)
else
soap_obj = type.new(obj)
end
soap_obj
end
def struct2soap(obj, type_qname, type)
soap_obj = SOAPStruct.new(type_qname)
mark_marshalled_obj(obj, soap_obj)
elements2soap(obj, soap_obj, type.content.elements)
soap_obj
end
def array2soap(obj, type_qname, type)
contenttype = type.child_type
soap_obj = SOAPArray.new(ValueArrayName, 1, contenttype)
mark_marshalled_obj(obj, soap_obj)
obj.each do |item|
soap_obj.add(Mapping._obj2soap(item, self, contenttype))
end
soap_obj
end
def elements2soap(obj, soap_obj, elements)
elements.each do |element|
name = element.name.name
child_obj = obj.instance_eval("@#{ name }")
soap_obj.add(name, Mapping._obj2soap(child_obj, self, element.type))
end
end
end
end
end

View file

@ -149,8 +149,9 @@ private
def base2soap(obj, type) def base2soap(obj, type)
soap_obj = nil soap_obj = nil
if type <= XSD::XSDString if type <= XSD::XSDString
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ? str = XSD::Charset.encoding_conv(obj.to_s,
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj) Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
soap_obj = type.new(str)
mark_marshalled_obj(obj, soap_obj) mark_marshalled_obj(obj, soap_obj)
else else
soap_obj = type.new(obj) soap_obj = type.new(obj)
@ -234,7 +235,9 @@ private
elements, as_array = schema_element_definition(obj.class) elements, as_array = schema_element_definition(obj.class)
vars = {} vars = {}
node.each do |name, value| node.each do |name, value|
if class_name = elements[name] item = elements.find { |k, v| k.name == name }
if item
elename, class_name = item
if klass = Mapping.class_from_name(class_name) if klass = Mapping.class_from_name(class_name)
# klass must be a SOAPBasetype or a class # klass must be a SOAPBasetype or a class
if klass.ancestors.include?(::SOAP::SOAPBasetype) if klass.ancestors.include?(::SOAP::SOAPBasetype)
@ -246,6 +249,14 @@ private
else else
child = Mapping._soap2obj(value, self, klass) child = Mapping._soap2obj(value, self, klass)
end end
elsif klass = Mapping.module_from_name(class_name)
# simpletype
if value.respond_to?(:data)
child = value.data
else
raise MappingError.new(
"cannot map to a module value: #{class_name}")
end
else else
raise MappingError.new("unknown class: #{class_name}") raise MappingError.new("unknown class: #{class_name}")
end end

View file

@ -38,14 +38,14 @@ class WSDLLiteralRegistry < Registry
if ele = @definedelements[qname] if ele = @definedelements[qname]
soap_obj = obj2elesoap(obj, ele) soap_obj = obj2elesoap(obj, ele)
elsif type = @definedtypes[qname] elsif type = @definedtypes[qname]
soap_obj = obj2typesoap(obj, type) soap_obj = obj2typesoap(obj, type, true)
else else
soap_obj = any2soap(obj, qname) soap_obj = any2soap(obj, qname)
end end
return soap_obj if soap_obj return soap_obj if soap_obj
if @excn_handler_obj2soap if @excn_handler_obj2soap
soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj| soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
Mapping._obj2soap(yield_obj, self) Mapping.obj2soap(yield_obj, nil, nil, MAPPING_OPT)
} }
return soap_obj if soap_obj return soap_obj if soap_obj
end end
@ -54,9 +54,7 @@ class WSDLLiteralRegistry < Registry
# node should be a SOAPElement # node should be a SOAPElement
def soap2obj(node, obj_class = nil) def soap2obj(node, obj_class = nil)
unless obj_class.nil? # obj_class is given when rpc/literal service. but ignored for now.
raise MappingError.new("must not reach here")
end
begin begin
return any2obj(node) return any2obj(node)
rescue MappingError rescue MappingError
@ -64,45 +62,50 @@ class WSDLLiteralRegistry < Registry
if @excn_handler_soap2obj if @excn_handler_soap2obj
begin begin
return @excn_handler_soap2obj.call(node) { |yield_node| return @excn_handler_soap2obj.call(node) { |yield_node|
Mapping._soap2obj(yield_node, self) Mapping.soap2obj(yield_node, nil, nil, MAPPING_OPT)
} }
rescue Exception rescue Exception
end end
end end
raise MappingError.new("cannot map #{node.type.name} to Ruby object") if node.respond_to?(:type)
raise MappingError.new("cannot map #{node.type.name} to Ruby object")
else
raise MappingError.new("cannot map #{node.elename.name} to Ruby object")
end
end end
private private
MAPPING_OPT = { :no_reference => true }
def obj2elesoap(obj, ele) def obj2elesoap(obj, ele)
o = nil o = nil
qualified = (ele.elementform == 'qualified')
if ele.type if ele.type
if type = @definedtypes[ele.type] if type = @definedtypes[ele.type]
o = obj2typesoap(obj, type) o = obj2typesoap(obj, type, qualified)
elsif type = TypeMap[ele.type] elsif type = TypeMap[ele.type]
o = base2soap(obj, type) o = base2soap(obj, type)
else else
raise MappingError.new("cannot find type #{ele.type}") raise MappingError.new("cannot find type #{ele.type}")
end end
o.elename = ele.name
elsif ele.local_complextype elsif ele.local_complextype
o = obj2typesoap(obj, ele.local_complextype) o = obj2typesoap(obj, ele.local_complextype, qualified)
o.elename = ele.name
add_attributes2soap(obj, o) add_attributes2soap(obj, o)
elsif ele.local_simpletype elsif ele.local_simpletype
o = obj2typesoap(obj, ele.local_simpletype) o = obj2typesoap(obj, ele.local_simpletype, qualified)
o.elename = ele.name
else else
raise MappingError.new('illegal schema?') raise MappingError.new('illegal schema?')
end end
o.elename = ele.name
o o
end end
def obj2typesoap(obj, type) def obj2typesoap(obj, type, qualified)
if type.is_a?(::WSDL::XMLSchema::SimpleType) if type.is_a?(::WSDL::XMLSchema::SimpleType)
simpleobj2soap(obj, type) simpleobj2soap(obj, type)
else else
complexobj2soap(obj, type) complexobj2soap(obj, type, qualified)
end end
end end
@ -113,15 +116,17 @@ private
o o
end end
def complexobj2soap(obj, type) def complexobj2soap(obj, type, qualified)
o = SOAPElement.new(type.name) o = SOAPElement.new(type.name)
o.qualified = qualified
type.each_element do |child_ele| type.each_element do |child_ele|
child = Mapping.get_attribute(obj, child_ele.name.name) child = Mapping.get_attribute(obj, child_ele.name.name)
if child.nil? if child.nil?
if child_ele.nillable if child_ele.nillable
# ToDo: test # ToDo: test
# add empty element # add empty element
o.add(obj2elesoap(nil)) child_soap = obj2elesoap(nil, child_ele)
o.add(child_soap)
elsif Integer(child_ele.minoccurs) == 0 elsif Integer(child_ele.minoccurs) == 0
# nothing to do # nothing to do
else else
@ -129,10 +134,12 @@ private
end end
elsif child_ele.map_as_array? elsif child_ele.map_as_array?
child.each do |item| child.each do |item|
o.add(obj2elesoap(item, child_ele)) child_soap = obj2elesoap(item, child_ele)
o.add(child_soap)
end end
else else
o.add(obj2elesoap(child, child_ele)) child_soap = obj2elesoap(child, child_ele)
o.add(child_soap)
end end
end end
o o
@ -153,7 +160,7 @@ private
# expected to be a basetype or an anyType. # expected to be a basetype or an anyType.
# SOAPStruct, etc. is used instead of SOAPElement. # SOAPStruct, etc. is used instead of SOAPElement.
begin begin
ele = Mapping.obj2soap(obj) ele = Mapping.obj2soap(obj, nil, nil, MAPPING_OPT)
ele.elename = qname ele.elename = qname
ele ele
rescue MappingError rescue MappingError
@ -170,6 +177,9 @@ private
def stubobj2soap(obj, qname) def stubobj2soap(obj, qname)
ele = SOAPElement.new(qname) ele = SOAPElement.new(qname)
ele.qualified =
(obj.class.class_variables.include?('@@schema_qualified') and
obj.class.class_eval('@@schema_qualified'))
add_elements2soap(obj, ele) add_elements2soap(obj, ele)
add_attributes2soap(obj, ele) add_attributes2soap(obj, ele)
ele ele
@ -196,15 +206,17 @@ private
elements, as_array = schema_element_definition(obj.class) elements, as_array = schema_element_definition(obj.class)
if elements if elements
elements.each do |elename, type| elements.each do |elename, type|
child = Mapping.get_attribute(obj, elename) if child = Mapping.get_attribute(obj, elename.name)
unless child.nil? if as_array.include?(elename.name)
name = XSD::QName.new(nil, elename)
if as_array.include?(type)
child.each do |item| child.each do |item|
ele.add(obj2soap(item, name)) ele.add(obj2soap(item, elename))
end end
else else
ele.add(obj2soap(child, name)) ele.add(obj2soap(child, elename))
end
elsif obj.is_a?(::Array) and as_array.include?(elename.name)
obj.each do |item|
ele.add(obj2soap(item, elename))
end end
end end
end end
@ -225,8 +237,9 @@ private
def base2soap(obj, type) def base2soap(obj, type)
soap_obj = nil soap_obj = nil
if type <= XSD::XSDString if type <= XSD::XSDString
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ? str = XSD::Charset.encoding_conv(obj.to_s,
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj) Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
soap_obj = type.new(str)
else else
soap_obj = type.new(obj) soap_obj = type.new(obj)
end end
@ -253,7 +266,7 @@ private
# SOAPArray for literal? # SOAPArray for literal?
soapele2plainobj(node) soapele2plainobj(node)
else else
obj = Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class) obj = Mapping.soap2obj(node, nil, obj_class, MAPPING_OPT)
add_attributes2plainobj(node, obj) add_attributes2plainobj(node, obj)
obj obj
end end
@ -277,8 +290,11 @@ private
elements, as_array = schema_element_definition(obj.class) elements, as_array = schema_element_definition(obj.class)
vars = {} vars = {}
node.each do |name, value| node.each do |name, value|
if class_name = elements[name] item = elements.find { |k, v| k.name == name }
if item
elename, class_name = item
if klass = Mapping.class_from_name(class_name) if klass = Mapping.class_from_name(class_name)
# klass must be a SOAPBasetype or a class
if klass.ancestors.include?(::SOAP::SOAPBasetype) if klass.ancestors.include?(::SOAP::SOAPBasetype)
if value.respond_to?(:data) if value.respond_to?(:data)
child = klass.new(value.data).data child = klass.new(value.data).data
@ -288,13 +304,21 @@ private
else else
child = any2obj(value, klass) child = any2obj(value, klass)
end end
elsif klass = Mapping.module_from_name(class_name)
# simpletype
if value.respond_to?(:data)
child = value.data
else
raise MappingError.new(
"cannot map to a module value: #{class_name}")
end
else else
raise MappingError.new("unknown class: #{class_name}") raise MappingError.new("unknown class/module: #{class_name}")
end end
else # untyped element is treated as anyType. else # untyped element is treated as anyType.
child = any2obj(value) child = any2obj(value)
end end
if as_array.include?(class_name) if as_array.include?(elename.name)
(vars[name] ||= []) << child (vars[name] ||= []) << child
else else
vars[name] = child vars[name] = child
@ -323,7 +347,7 @@ private
def add_elements2plainobj(node, obj) def add_elements2plainobj(node, obj)
node.each do |name, value| node.each do |name, value|
obj.__add_xmlele_value(XSD::QName.new(nil, name), any2obj(value)) obj.__add_xmlele_value(value.elename, any2obj(value))
end end
end end

View file

@ -112,6 +112,7 @@ class MIMEMessage
@headers = Headers.new @headers = Headers.new
@headers.add("Content-Transfer-Encoding", "8bit") @headers.add("Content-Transfer-Encoding", "8bit")
@body = nil @body = nil
@contentid = nil
end end
def self.parse(str) def self.parse(str)
@ -147,6 +148,7 @@ class MIMEMessage
def initialize def initialize
@parts = [] @parts = []
@headers = Headers.new @headers = Headers.new
@root = nil
end end
def self.parse(head, str) def self.parse(head, str)
@ -197,7 +199,7 @@ class MIMEMessage
def add_part(content) def add_part(content)
part = Part.new part = Part.new
part.headers.add("Content-Type", part.headers.add("Content-Type",
"text/xml; charset=" + XSD::Charset.encoding_label) "text/xml; charset=" + XSD::Charset.xml_encoding_label)
part.headers.add("Content-ID", Attachment.contentid(part)) part.headers.add("Content-ID", Attachment.contentid(part))
part.body = content part.body = content
@parts.unshift(part) @parts.unshift(part)

View file

@ -60,6 +60,7 @@ private
public public
attr_accessor :envelopenamespace
attr_accessor :default_encodingstyle attr_accessor :default_encodingstyle
attr_accessor :decode_typemap attr_accessor :decode_typemap
attr_accessor :allow_unqualified_element attr_accessor :allow_unqualified_element
@ -70,6 +71,7 @@ public
@parsestack = nil @parsestack = nil
@lastnode = nil @lastnode = nil
@handlers = {} @handlers = {}
@envelopenamespace = opt[:envelopenamespace] || EnvelopeNamespace
@default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace @default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
@decode_typemap = opt[:decode_typemap] || nil @decode_typemap = opt[:decode_typemap] || nil
@allow_unqualified_element = opt[:allow_unqualified_element] || false @allow_unqualified_element = opt[:allow_unqualified_element] || false
@ -134,10 +136,7 @@ public
lastframe = @parsestack.last lastframe = @parsestack.last
if lastframe if lastframe
# Need not to be cloned because character does not have attr. # Need not to be cloned because character does not have attr.
ns = lastframe.ns decode_text(lastframe.ns, text, lastframe.encodingstyle)
parent = lastframe.node
encodingstyle = lastframe.encodingstyle
decode_text(ns, text, encodingstyle)
else else
# Ignore Text outside of SOAP Envelope. # Ignore Text outside of SOAP Envelope.
p text if $DEBUG p text if $DEBUG
@ -157,7 +156,7 @@ private
def find_encodingstyle(ns, attrs) def find_encodingstyle(ns, attrs)
attrs.each do |key, value| attrs.each do |key, value|
if (ns.compare(EnvelopeNamespace, AttrEncodingStyle, key)) if (ns.compare(@envelopenamespace, AttrEncodingStyle, key))
return value return value
end end
end end
@ -168,7 +167,7 @@ private
ele = ns.parse(name) ele = ns.parse(name)
# Envelope based parsing. # Envelope based parsing.
if ((ele.namespace == EnvelopeNamespace) || if ((ele.namespace == @envelopenamespace) ||
(@allow_unqualified_element && ele.namespace.nil?)) (@allow_unqualified_element && ele.namespace.nil?))
o = decode_soap_envelope(ns, ele, attrs, parent) o = decode_soap_envelope(ns, ele, attrs, parent)
return o if o return o if o

View file

@ -205,7 +205,7 @@ private
opt.add_hook("protocol.wiredump_file_base") do |key, value| opt.add_hook("protocol.wiredump_file_base") do |key, value|
@wiredump_file_base = value @wiredump_file_base = value
end end
opt["protocol.http.charset"] ||= XSD::Charset.encoding_label opt["protocol.http.charset"] ||= XSD::Charset.xml_encoding_label
opt["protocol.http.proxy"] ||= Env::HTTP_PROXY opt["protocol.http.proxy"] ||= Env::HTTP_PROXY
opt["protocol.http.no_proxy"] ||= Env::NO_PROXY opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
opt opt

View file

@ -20,21 +20,25 @@ class SOAPBody < SOAPStruct
end end
def response def response
root = root_node
if !@is_fault if !@is_fault
if void? if root.nil?
nil nil
elsif root.is_a?(SOAPBasetype)
root
else else
# Initial element is [retval]. # Initial element is [retval].
root_node[0] root[0]
end end
else else
root_node root
end end
end end
def outparams def outparams
if !@is_fault and !void? root = root_node
op = root_node[1..-1] if !@is_fault and !root.nil? and !root.is_a?(SOAPBasetype)
op = root[1..-1]
op = nil if op && op.empty? op = nil if op && op.empty?
op op
else else
@ -42,10 +46,6 @@ class SOAPBody < SOAPStruct
end end
end end
def void?
root_node.nil?
end
def fault def fault
if @is_fault if @is_fault
self['fault'] self['fault']

View file

@ -92,6 +92,14 @@ public
opt[:response_style] ||= :document opt[:response_style] ||= :document
opt[:request_use] ||= :literal opt[:request_use] ||= :literal
opt[:response_use] ||= :literal opt[:response_use] ||= :literal
# default values of these values are unqualified in XML Schema.
# set true for backward compatibility.
unless opt.key?(:elementformdefault)
opt[:elementformdefault] = true
end
unless opt.key?(:attributeformdefault)
opt[:attributeformdefault] = true
end
@operation[name] = Operation.new(soapaction, param_def, opt) @operation[name] = Operation.new(soapaction, param_def, opt)
end end
@ -101,7 +109,7 @@ public
alias add_document_method add_document_operation alias add_document_method add_document_operation
def invoke(req_header, req_body, opt = nil) def invoke(req_header, req_body, opt = nil)
opt ||= create_options opt ||= create_encoding_opt
route(req_header, req_body, opt, opt) route(req_header, req_body, opt, opt)
end end
@ -109,15 +117,27 @@ public
unless op_info = @operation[name] unless op_info = @operation[name]
raise MethodDefinitionError, "method: #{name} not defined" raise MethodDefinitionError, "method: #{name} not defined"
end end
mapping_opt = create_mapping_opt
req_header = create_request_header req_header = create_request_header
req_body = SOAPBody.new( req_body = SOAPBody.new(
op_info.request_body(params, @mapping_registry, @literal_mapping_registry) op_info.request_body(params, @mapping_registry,
@literal_mapping_registry, mapping_opt)
) )
reqopt = create_options({ reqopt = create_encoding_opt(
:soapaction => op_info.soapaction || @soapaction, :soapaction => op_info.soapaction || @soapaction,
:default_encodingstyle => op_info.request_default_encodingstyle}) :envelopenamespace => @options["soap.envelope.requestnamespace"],
resopt = create_options({ :default_encodingstyle =>
:default_encodingstyle => op_info.response_default_encodingstyle}) @default_encodingstyle || op_info.request_default_encodingstyle,
:elementformdefault => op_info.elementformdefault,
:attributeformdefault => op_info.attributeformdefault
)
resopt = create_encoding_opt(
:envelopenamespace => @options["soap.envelope.responsenamespace"],
:default_encodingstyle =>
@default_encodingstyle || op_info.response_default_encodingstyle,
:elementformdefault => op_info.elementformdefault,
:attributeformdefault => op_info.attributeformdefault
)
env = route(req_header, req_body, reqopt, resopt) env = route(req_header, req_body, reqopt, resopt)
raise EmptyResponseError unless env raise EmptyResponseError unless env
receive_headers(env.header) receive_headers(env.header)
@ -126,11 +146,15 @@ public
rescue ::SOAP::FaultError => e rescue ::SOAP::FaultError => e
op_info.raise_fault(e, @mapping_registry, @literal_mapping_registry) op_info.raise_fault(e, @mapping_registry, @literal_mapping_registry)
end end
op_info.response_obj(env.body, @mapping_registry, @literal_mapping_registry) op_info.response_obj(env.body, @mapping_registry,
@literal_mapping_registry, mapping_opt)
end end
def route(req_header, req_body, reqopt, resopt) def route(req_header, req_body, reqopt, resopt)
req_env = SOAPEnvelope.new(req_header, req_body) req_env = ::SOAP::SOAPEnvelope.new(req_header, req_body)
unless reqopt[:envelopenamespace].nil?
set_envelopenamespace(req_env, reqopt[:envelopenamespace])
end
reqopt[:external_content] = nil reqopt[:external_content] = nil
conn_data = marshal(req_env, reqopt) conn_data = marshal(req_env, reqopt)
if ext = reqopt[:external_content] if ext = reqopt[:external_content]
@ -159,6 +183,16 @@ public
private private
def set_envelopenamespace(env, namespace)
env.elename = XSD::QName.new(namespace, env.elename.name)
if env.header
env.header.elename = XSD::QName.new(namespace, env.header.elename.name)
end
if env.body
env.body.elename = XSD::QName.new(namespace, env.body.elename.name)
end
end
def create_request_header def create_request_header
headers = @headerhandler.on_outbound headers = @headerhandler.on_outbound
if headers.empty? if headers.empty?
@ -201,6 +235,10 @@ private
::SOAP::StreamHandler.parse_media_type(contenttype) ::SOAP::StreamHandler.parse_media_type(contenttype)
env = Processor.unmarshal(conn_data.receive_string, opt) env = Processor.unmarshal(conn_data.receive_string, opt)
end end
unless env.is_a?(::SOAP::SOAPEnvelope)
raise ResponseFormatError.new(
"response is not a SOAP envelope: #{conn_data.receive_string}")
end
env env
end end
@ -212,11 +250,22 @@ private
header header
end end
def create_options(hash = nil) def create_encoding_opt(hash = nil)
opt = {} opt = {}
opt[:default_encodingstyle] = @default_encodingstyle opt[:default_encodingstyle] = @default_encodingstyle
opt[:allow_unqualified_element] = @allow_unqualified_element opt[:allow_unqualified_element] = @allow_unqualified_element
opt[:generate_explicit_type] = @generate_explicit_type opt[:generate_explicit_type] = @generate_explicit_type
opt[:no_indent] = @options["soap.envelope.no_indent"]
opt[:use_numeric_character_reference] =
@options["soap.envelope.use_numeric_character_reference"]
opt.update(hash) if hash
opt
end
def create_mapping_opt(hash = nil)
opt = {
:external_ces => @options["soap.mapping.external_ces"]
}
opt.update(hash) if hash opt.update(hash) if hash
opt opt
end end
@ -227,6 +276,8 @@ private
attr_reader :response_style attr_reader :response_style
attr_reader :request_use attr_reader :request_use
attr_reader :response_use attr_reader :response_use
attr_reader :elementformdefault
attr_reader :attributeformdefault
def initialize(soapaction, param_def, opt) def initialize(soapaction, param_def, opt)
@soapaction = soapaction @soapaction = soapaction
@ -234,6 +285,9 @@ private
@response_style = opt[:response_style] @response_style = opt[:response_style]
@request_use = opt[:request_use] @request_use = opt[:request_use]
@response_use = opt[:response_use] @response_use = opt[:response_use]
# set nil(unqualified) by default
@elementformdefault = opt[:elementformdefault]
@attributeformdefault = opt[:attributeformdefault]
check_style(@request_style) check_style(@request_style)
check_style(@response_style) check_style(@response_style)
check_use(@request_use) check_use(@request_use)
@ -247,17 +301,22 @@ private
RPC::SOAPMethodRequest.new(@rpc_request_qname, param_def, @soapaction) RPC::SOAPMethodRequest.new(@rpc_request_qname, param_def, @soapaction)
else else
@doc_request_qnames = [] @doc_request_qnames = []
@doc_request_qualified = []
@doc_response_qnames = [] @doc_response_qnames = []
param_def.each do |inout, paramname, typeinfo| @doc_response_qualified = []
param_def.each do |inout, paramname, typeinfo, eleinfo|
klass_not_used, nsdef, namedef = typeinfo klass_not_used, nsdef, namedef = typeinfo
qualified = eleinfo
if namedef.nil? if namedef.nil?
raise MethodDefinitionError.new("qname must be given") raise MethodDefinitionError.new("qname must be given")
end end
case inout case inout
when SOAPMethod::IN when SOAPMethod::IN
@doc_request_qnames << XSD::QName.new(nsdef, namedef) @doc_request_qnames << XSD::QName.new(nsdef, namedef)
@doc_request_qualified << qualified
when SOAPMethod::OUT when SOAPMethod::OUT
@doc_response_qnames << XSD::QName.new(nsdef, namedef) @doc_response_qnames << XSD::QName.new(nsdef, namedef)
@doc_response_qualified << qualified
else else
raise MethodDefinitionError.new( raise MethodDefinitionError.new(
"illegal inout definition for document style: #{inout}") "illegal inout definition for document style: #{inout}")
@ -274,19 +333,19 @@ private
(@response_use == :encoded) ? EncodingNamespace : LiteralNamespace (@response_use == :encoded) ? EncodingNamespace : LiteralNamespace
end end
def request_body(values, mapping_registry, literal_mapping_registry) def request_body(values, mapping_registry, literal_mapping_registry, opt)
if @request_style == :rpc if @request_style == :rpc
request_rpc(values, mapping_registry, literal_mapping_registry) request_rpc(values, mapping_registry, literal_mapping_registry, opt)
else else
request_doc(values, mapping_registry, literal_mapping_registry) request_doc(values, mapping_registry, literal_mapping_registry, opt)
end end
end end
def response_obj(body, mapping_registry, literal_mapping_registry) def response_obj(body, mapping_registry, literal_mapping_registry, opt)
if @response_style == :rpc if @response_style == :rpc
response_rpc(body, mapping_registry, literal_mapping_registry) response_rpc(body, mapping_registry, literal_mapping_registry, opt)
else else
response_doc(body, mapping_registry, literal_mapping_registry) response_doc(body, mapping_registry, literal_mapping_registry, opt)
end end
end end
@ -312,86 +371,89 @@ private
end end
end end
def request_rpc(values, mapping_registry, literal_mapping_registry) def request_rpc(values, mapping_registry, literal_mapping_registry, opt)
if @request_use == :encoded if @request_use == :encoded
request_rpc_enc(values, mapping_registry) request_rpc_enc(values, mapping_registry, opt)
else else
request_rpc_lit(values, literal_mapping_registry) request_rpc_lit(values, literal_mapping_registry, opt)
end end
end end
def request_doc(values, mapping_registry, literal_mapping_registry) def request_doc(values, mapping_registry, literal_mapping_registry, opt)
if @request_use == :encoded if @request_use == :encoded
request_doc_enc(values, mapping_registry) request_doc_enc(values, mapping_registry, opt)
else else
request_doc_lit(values, literal_mapping_registry) request_doc_lit(values, literal_mapping_registry, opt)
end end
end end
def request_rpc_enc(values, mapping_registry) def request_rpc_enc(values, mapping_registry, opt)
method = @rpc_method_factory.dup method = @rpc_method_factory.dup
names = method.input_params names = method.input_params
obj = create_request_obj(names, values) obj = create_request_obj(names, values)
soap = Mapping.obj2soap(obj, mapping_registry, @rpc_request_qname) soap = Mapping.obj2soap(obj, mapping_registry, @rpc_request_qname, opt)
method.set_param(soap) method.set_param(soap)
method method
end end
def request_rpc_lit(values, mapping_registry) def request_rpc_lit(values, mapping_registry, opt)
method = @rpc_method_factory.dup method = @rpc_method_factory.dup
params = {} params = {}
idx = 0 idx = 0
method.input_params.each do |name| method.input_params.each do |name|
params[name] = Mapping.obj2soap(values[idx], mapping_registry, params[name] = Mapping.obj2soap(values[idx], mapping_registry,
XSD::QName.new(nil, name)) XSD::QName.new(nil, name), opt)
idx += 1 idx += 1
end end
method.set_param(params) method.set_param(params)
method method
end end
def request_doc_enc(values, mapping_registry) def request_doc_enc(values, mapping_registry, opt)
(0...values.size).collect { |idx| (0...values.size).collect { |idx|
ele = Mapping.obj2soap(values[idx], mapping_registry) ele = Mapping.obj2soap(values[idx], mapping_registry, nil, opt)
ele.elename = @doc_request_qnames[idx] ele.elename = @doc_request_qnames[idx]
ele ele
} }
end end
def request_doc_lit(values, mapping_registry) def request_doc_lit(values, mapping_registry, opt)
(0...values.size).collect { |idx| (0...values.size).collect { |idx|
ele = Mapping.obj2soap(values[idx], mapping_registry, ele = Mapping.obj2soap(values[idx], mapping_registry,
@doc_request_qnames[idx]) @doc_request_qnames[idx], opt)
ele.encodingstyle = LiteralNamespace ele.encodingstyle = LiteralNamespace
if ele.respond_to?(:qualified)
ele.qualified = @doc_request_qualified[idx]
end
ele ele
} }
end end
def response_rpc(body, mapping_registry, literal_mapping_registry) def response_rpc(body, mapping_registry, literal_mapping_registry, opt)
if @response_use == :encoded if @response_use == :encoded
response_rpc_enc(body, mapping_registry) response_rpc_enc(body, mapping_registry, opt)
else else
response_rpc_lit(body, literal_mapping_registry) response_rpc_lit(body, literal_mapping_registry, opt)
end end
end end
def response_doc(body, mapping_registry, literal_mapping_registry) def response_doc(body, mapping_registry, literal_mapping_registry, opt)
if @response_use == :encoded if @response_use == :encoded
return *response_doc_enc(body, mapping_registry) return *response_doc_enc(body, mapping_registry, opt)
else else
return *response_doc_lit(body, literal_mapping_registry) return *response_doc_lit(body, literal_mapping_registry, opt)
end end
end end
def response_rpc_enc(body, mapping_registry) def response_rpc_enc(body, mapping_registry, opt)
ret = nil ret = nil
if body.response if body.response
ret = Mapping.soap2obj(body.response, mapping_registry, ret = Mapping.soap2obj(body.response, mapping_registry,
@rpc_method_factory.retval_class_name) @rpc_method_factory.retval_class_name, opt)
end end
if body.outparams if body.outparams
outparams = body.outparams.collect { |outparam| outparams = body.outparams.collect { |outparam|
Mapping.soap2obj(outparam, mapping_regisry) Mapping.soap2obj(outparam, mapping_registry, nil, opt)
} }
[ret].concat(outparams) [ret].concat(outparams)
else else
@ -399,20 +461,20 @@ private
end end
end end
def response_rpc_lit(body, mapping_registry) def response_rpc_lit(body, mapping_registry, opt)
body.root_node.collect { |key, value| body.root_node.collect { |key, value|
Mapping.soap2obj(value, mapping_registry, Mapping.soap2obj(value, mapping_registry,
@rpc_method_factory.retval_class_name) @rpc_method_factory.retval_class_name, opt)
} }
end end
def response_doc_enc(body, mapping_registry) def response_doc_enc(body, mapping_registry, opt)
body.collect { |key, value| body.collect { |key, value|
Mapping.soap2obj(value, mapping_registry) Mapping.soap2obj(value, mapping_registry, nil, opt)
} }
end end
def response_doc_lit(body, mapping_registry) def response_doc_lit(body, mapping_registry, opt)
body.collect { |key, value| body.collect { |key, value|
Mapping.soap2obj(value, mapping_registry) Mapping.soap2obj(value, mapping_registry)
} }
@ -420,8 +482,10 @@ private
def create_request_obj(names, params) def create_request_obj(names, params)
o = Object.new o = Object.new
for idx in 0 ... params.length idx = 0
while idx < params.length
o.instance_variable_set('@' + names[idx], params[idx]) o.instance_variable_set('@' + names[idx], params[idx])
idx += 1
end end
o o
end end

View file

@ -28,6 +28,7 @@ class Router
attr_accessor :mapping_registry attr_accessor :mapping_registry
attr_accessor :literal_mapping_registry attr_accessor :literal_mapping_registry
attr_accessor :generate_explicit_type attr_accessor :generate_explicit_type
attr_accessor :external_ces
def initialize(actor) def initialize(actor)
@actor = actor @actor = actor
@ -35,6 +36,7 @@ class Router
@headerhandler = Header::HandlerSet.new @headerhandler = Header::HandlerSet.new
@literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new @literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
@generate_explicit_type = true @generate_explicit_type = true
@external_ces = nil
@operation_by_soapaction = {} @operation_by_soapaction = {}
@operation_by_qname = {} @operation_by_qname = {}
@headerhandlerfactory = [] @headerhandlerfactory = []
@ -163,7 +165,8 @@ class Router
soap_response = default_encodingstyle = nil soap_response = default_encodingstyle = nil
begin begin
soap_response = soap_response =
op.call(env.body, @mapping_registry, @literal_mapping_registry) op.call(env.body, @mapping_registry, @literal_mapping_registry,
create_mapping_opt)
default_encodingstyle = op.response_default_encodingstyle default_encodingstyle = op.response_default_encodingstyle
rescue Exception rescue Exception
soap_response = fault($!) soap_response = fault($!)
@ -240,7 +243,8 @@ private
return op return op
end end
if soapaction if soapaction
raise RPCRoutingError.new("operation: #{soapaction} not supported") raise RPCRoutingError.new(
"operation: #{soapaction} #{qname} not supported")
else else
raise RPCRoutingError.new("operation: #{qname} not supported") raise RPCRoutingError.new("operation: #{qname} not supported")
end end
@ -323,6 +327,10 @@ private
Mapping.obj2soap(detail, @mapping_registry)) Mapping.obj2soap(detail, @mapping_registry))
end end
def create_mapping_opt
{ :external_ces => @external_ces }
end
class Operation class Operation
attr_reader :name attr_reader :name
attr_reader :soapaction attr_reader :soapaction
@ -349,14 +357,19 @@ private
@rpc_response_qname = opt[:response_qname] @rpc_response_qname = opt[:response_qname]
else else
@doc_request_qnames = [] @doc_request_qnames = []
@doc_request_qualified = []
@doc_response_qnames = [] @doc_response_qnames = []
param_def.each do |inout, paramname, typeinfo| @doc_response_qualified = []
param_def.each do |inout, paramname, typeinfo, eleinfo|
klass, nsdef, namedef = typeinfo klass, nsdef, namedef = typeinfo
qualified = eleinfo
case inout case inout
when SOAPMethod::IN when SOAPMethod::IN
@doc_request_qnames << XSD::QName.new(nsdef, namedef) @doc_request_qnames << XSD::QName.new(nsdef, namedef)
@doc_request_qualified << qualified
when SOAPMethod::OUT when SOAPMethod::OUT
@doc_response_qnames << XSD::QName.new(nsdef, namedef) @doc_response_qnames << XSD::QName.new(nsdef, namedef)
@doc_response_qualified << qualified
else else
raise ArgumentError.new( raise ArgumentError.new(
"illegal inout definition for document style: #{inout}") "illegal inout definition for document style: #{inout}")
@ -373,18 +386,20 @@ private
(@response_use == :encoded) ? EncodingNamespace : LiteralNamespace (@response_use == :encoded) ? EncodingNamespace : LiteralNamespace
end end
def call(body, mapping_registry, literal_mapping_registry) def call(body, mapping_registry, literal_mapping_registry, opt)
if @request_style == :rpc if @request_style == :rpc
values = request_rpc(body, mapping_registry, literal_mapping_registry) values = request_rpc(body, mapping_registry, literal_mapping_registry,
opt)
else else
values = request_document(body, mapping_registry, literal_mapping_registry) values = request_document(body, mapping_registry,
literal_mapping_registry, opt)
end end
result = receiver.method(@name.intern).call(*values) result = receiver.method(@name.intern).call(*values)
return result if result.is_a?(SOAPFault) return result if result.is_a?(SOAPFault)
if @response_style == :rpc if @response_style == :rpc
response_rpc(result, mapping_registry, literal_mapping_registry) response_rpc(result, mapping_registry, literal_mapping_registry, opt)
else else
response_doc(result, mapping_registry, literal_mapping_registry) response_doc(result, mapping_registry, literal_mapping_registry, opt)
end end
end end
@ -394,61 +409,61 @@ private
raise NotImplementedError.new('must be defined in derived class') raise NotImplementedError.new('must be defined in derived class')
end end
def request_rpc(body, mapping_registry, literal_mapping_registry) def request_rpc(body, mapping_registry, literal_mapping_registry, opt)
request = body.request request = body.request
unless request.is_a?(SOAPStruct) unless request.is_a?(SOAPStruct)
raise RPCRoutingError.new("not an RPC style") raise RPCRoutingError.new("not an RPC style")
end end
if @request_use == :encoded if @request_use == :encoded
request_rpc_enc(request, mapping_registry) request_rpc_enc(request, mapping_registry, opt)
else else
request_rpc_lit(request, literal_mapping_registry) request_rpc_lit(request, literal_mapping_registry, opt)
end end
end end
def request_document(body, mapping_registry, literal_mapping_registry) def request_document(body, mapping_registry, literal_mapping_registry, opt)
# ToDo: compare names with @doc_request_qnames # ToDo: compare names with @doc_request_qnames
if @request_use == :encoded if @request_use == :encoded
request_doc_enc(body, mapping_registry) request_doc_enc(body, mapping_registry, opt)
else else
request_doc_lit(body, literal_mapping_registry) request_doc_lit(body, literal_mapping_registry, opt)
end end
end end
def request_rpc_enc(request, mapping_registry) def request_rpc_enc(request, mapping_registry, opt)
param = Mapping.soap2obj(request, mapping_registry) param = Mapping.soap2obj(request, mapping_registry, nil, opt)
request.collect { |key, value| request.collect { |key, value|
param[key] param[key]
} }
end end
def request_rpc_lit(request, mapping_registry) def request_rpc_lit(request, mapping_registry, opt)
request.collect { |key, value| request.collect { |key, value|
Mapping.soap2obj(value, mapping_registry) Mapping.soap2obj(value, mapping_registry, nil, opt)
} }
end end
def request_doc_enc(body, mapping_registry) def request_doc_enc(body, mapping_registry, opt)
body.collect { |key, value| body.collect { |key, value|
Mapping.soap2obj(value, mapping_registry) Mapping.soap2obj(value, mapping_registry, nil, opt)
} }
end end
def request_doc_lit(body, mapping_registry) def request_doc_lit(body, mapping_registry, opt)
body.collect { |key, value| body.collect { |key, value|
Mapping.soap2obj(value, mapping_registry) Mapping.soap2obj(value, mapping_registry, nil, opt)
} }
end end
def response_rpc(result, mapping_registry, literal_mapping_registry) def response_rpc(result, mapping_registry, literal_mapping_registry, opt)
if @response_use == :encoded if @response_use == :encoded
response_rpc_enc(result, mapping_registry) response_rpc_enc(result, mapping_registry, opt)
else else
response_rpc_lit(result, literal_mapping_registry) response_rpc_lit(result, literal_mapping_registry, opt)
end end
end end
def response_doc(result, mapping_registry, literal_mapping_registry) def response_doc(result, mapping_registry, literal_mapping_registry, opt)
if @doc_response_qnames.size == 1 and !result.is_a?(Array) if @doc_response_qnames.size == 1 and !result.is_a?(Array)
result = [result] result = [result]
end end
@ -457,34 +472,13 @@ private
"but #{result.size} given" "but #{result.size} given"
end end
if @response_use == :encoded if @response_use == :encoded
response_doc_enc(result, mapping_registry) response_doc_enc(result, mapping_registry, opt)
else else
response_doc_lit(result, literal_mapping_registry) response_doc_lit(result, literal_mapping_registry, opt)
end end
end end
def response_rpc_enc(result, mapping_registry) def response_rpc_enc(result, mapping_registry, opt)
soap_response =
@rpc_method_factory.create_method_response(@rpc_response_qname)
if soap_response.have_outparam?
unless result.is_a?(Array)
raise RPCRoutingError.new("out parameter was not returned")
end
outparams = {}
i = 1
soap_response.output_params.each do |outparam|
outparams[outparam] = Mapping.obj2soap(result[i], mapping_registry)
i += 1
end
soap_response.set_outparam(outparams)
soap_response.retval = Mapping.obj2soap(result[0], mapping_registry)
else
soap_response.retval = Mapping.obj2soap(result, mapping_registry)
end
soap_response
end
def response_rpc_lit(result, mapping_registry)
soap_response = soap_response =
@rpc_method_factory.create_method_response(@rpc_response_qname) @rpc_method_factory.create_method_response(@rpc_response_qname)
if soap_response.have_outparam? if soap_response.have_outparam?
@ -495,30 +489,60 @@ private
i = 1 i = 1
soap_response.output_params.each do |outparam| soap_response.output_params.each do |outparam|
outparams[outparam] = Mapping.obj2soap(result[i], mapping_registry, outparams[outparam] = Mapping.obj2soap(result[i], mapping_registry,
XSD::QName.new(nil, outparam)) nil, opt)
i += 1 i += 1
end end
soap_response.set_outparam(outparams) soap_response.set_outparam(outparams)
soap_response.retval = Mapping.obj2soap(result[0], mapping_registry, soap_response.retval = Mapping.obj2soap(result[0], mapping_registry,
XSD::QName.new(nil, soap_response.elename)) nil, opt)
else else
soap_response.retval = Mapping.obj2soap(result, mapping_registry, soap_response.retval = Mapping.obj2soap(result, mapping_registry, nil,
XSD::QName.new(nil, soap_response.elename)) opt)
end end
soap_response soap_response
end end
def response_doc_enc(result, mapping_registry) def response_rpc_lit(result, mapping_registry, opt)
soap_response =
@rpc_method_factory.create_method_response(@rpc_response_qname)
if soap_response.have_outparam?
unless result.is_a?(Array)
raise RPCRoutingError.new("out parameter was not returned")
end
outparams = {}
i = 1
soap_response.output_params.each do |outparam|
outparams[outparam] = Mapping.obj2soap(result[i], mapping_registry,
XSD::QName.new(nil, outparam), opt)
i += 1
end
soap_response.set_outparam(outparams)
soap_response.retval = Mapping.obj2soap(result[0], mapping_registry,
XSD::QName.new(nil, soap_response.elename), opt)
else
soap_response.retval = Mapping.obj2soap(result, mapping_registry,
XSD::QName.new(nil, soap_response.elename), opt)
end
soap_response
end
def response_doc_enc(result, mapping_registry, opt)
(0...result.size).collect { |idx| (0...result.size).collect { |idx|
ele = Mapping.obj2soap(result[idx], mapping_registry) ele = Mapping.obj2soap(result[idx], mapping_registry, nil, opt)
ele.elename = @doc_response_qnames[idx] ele.elename = @doc_response_qnames[idx]
ele ele
} }
end end
def response_doc_lit(result, mapping_registry) def response_doc_lit(result, mapping_registry, opt)
(0...result.size).collect { |idx| (0...result.size).collect { |idx|
mapping_registry.obj2soap(result[idx], @doc_response_qnames[idx]) ele = Mapping.obj2soap(result[idx], mapping_registry,
@doc_response_qnames[idx])
ele.encodingstyle = LiteralNamespace
if ele.respond_to?(:qualified)
ele.qualified = @doc_response_qualified[idx]
end
ele
} }
end end

View file

@ -84,6 +84,7 @@ public
begin begin
conn_data = ::SOAP::StreamHandler::ConnectionData.new conn_data = ::SOAP::StreamHandler::ConnectionData.new
setup_req(conn_data, req) setup_req(conn_data, req)
@router.external_ces = @options[:external_ces]
conn_data = @router.route(conn_data) conn_data = @router.route(conn_data)
setup_res(conn_data, req, res) setup_res(conn_data, req, res)
rescue Exception => e rescue Exception => e

View file

@ -13,7 +13,7 @@ require 'xsd/charset'
module SOAP module SOAP
VERSION = Version = '1.5.4' VERSION = Version = '1.5.5'
PropertyName = 'soap/property' PropertyName = 'soap/property'
EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/' EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/'
@ -40,21 +40,21 @@ AttrOffset = 'offset'
AttrPosition = 'position' AttrPosition = 'position'
ValueArray = 'Array' ValueArray = 'Array'
EleEnvelopeName = XSD::QName.new(EnvelopeNamespace, EleEnvelope) EleEnvelopeName = XSD::QName.new(EnvelopeNamespace, EleEnvelope).freeze
EleHeaderName = XSD::QName.new(EnvelopeNamespace, EleHeader) EleHeaderName = XSD::QName.new(EnvelopeNamespace, EleHeader).freeze
EleBodyName = XSD::QName.new(EnvelopeNamespace, EleBody) EleBodyName = XSD::QName.new(EnvelopeNamespace, EleBody).freeze
EleFaultName = XSD::QName.new(EnvelopeNamespace, EleFault) EleFaultName = XSD::QName.new(EnvelopeNamespace, EleFault).freeze
EleFaultStringName = XSD::QName.new(nil, EleFaultString) EleFaultStringName = XSD::QName.new(nil, EleFaultString).freeze
EleFaultActorName = XSD::QName.new(nil, EleFaultActor) EleFaultActorName = XSD::QName.new(nil, EleFaultActor).freeze
EleFaultCodeName = XSD::QName.new(nil, EleFaultCode) EleFaultCodeName = XSD::QName.new(nil, EleFaultCode).freeze
EleFaultDetailName = XSD::QName.new(nil, EleFaultDetail) EleFaultDetailName = XSD::QName.new(nil, EleFaultDetail).freeze
AttrMustUnderstandName = XSD::QName.new(EnvelopeNamespace, AttrMustUnderstand) AttrMustUnderstandName = XSD::QName.new(EnvelopeNamespace, AttrMustUnderstand).freeze
AttrEncodingStyleName = XSD::QName.new(EnvelopeNamespace, AttrEncodingStyle) AttrEncodingStyleName = XSD::QName.new(EnvelopeNamespace, AttrEncodingStyle).freeze
AttrRootName = XSD::QName.new(EncodingNamespace, AttrRoot) AttrRootName = XSD::QName.new(EncodingNamespace, AttrRoot).freeze
AttrArrayTypeName = XSD::QName.new(EncodingNamespace, AttrArrayType) AttrArrayTypeName = XSD::QName.new(EncodingNamespace, AttrArrayType).freeze
AttrOffsetName = XSD::QName.new(EncodingNamespace, AttrOffset) AttrOffsetName = XSD::QName.new(EncodingNamespace, AttrOffset).freeze
AttrPositionName = XSD::QName.new(EncodingNamespace, AttrPosition) AttrPositionName = XSD::QName.new(EncodingNamespace, AttrPosition).freeze
ValueArrayName = XSD::QName.new(EncodingNamespace, ValueArray) ValueArrayName = XSD::QName.new(EncodingNamespace, ValueArray).freeze
Base64Literal = 'base64' Base64Literal = 'base64'
@ -76,6 +76,7 @@ class ArrayStoreError < Error; end
class RPCRoutingError < Error; end class RPCRoutingError < Error; end
class EmptyResponseError < Error; end class EmptyResponseError < Error; end
class ResponseFormatError < Error; end
class UnhandledMustUnderstandHeaderError < Error; end class UnhandledMustUnderstandHeaderError < Error; end

View file

@ -20,18 +20,6 @@ module SOAP
class StreamHandler class StreamHandler
Client = begin
require 'http-access2'
if HTTPAccess2::VERSION < "2.0"
raise LoadError.new("http-access/2.0 or later is required.")
end
HTTPAccess2::Client
rescue LoadError
warn("Loading http-access2 failed. Net/http is used.") if $DEBUG
require 'soap/netHttpClient'
SOAP::NetHttpClient
end
RUBY_VERSION_STRING = "ruby #{ RUBY_VERSION } (#{ RUBY_RELEASE_DATE }) [#{ RUBY_PLATFORM }]" RUBY_VERSION_STRING = "ruby #{ RUBY_VERSION } (#{ RUBY_RELEASE_DATE }) [#{ RUBY_PLATFORM }]"
class ConnectionData class ConnectionData
@ -70,12 +58,27 @@ end
class HTTPStreamHandler < StreamHandler class HTTPStreamHandler < StreamHandler
include SOAP include SOAP
begin
require 'http-access2'
if HTTPAccess2::VERSION < "2.0"
raise LoadError.new("http-access/2.0 or later is required.")
end
Client = HTTPAccess2::Client
RETRYABLE = true
rescue LoadError
warn("Loading http-access2 failed. Net/http is used.") if $DEBUG
require 'soap/netHttpClient'
Client = SOAP::NetHttpClient
RETRYABLE = false
end
public public
attr_reader :client attr_reader :client
attr_accessor :wiredump_file_base attr_accessor :wiredump_file_base
NofRetry = 10 # [times] MAX_RETRY_COUNT = 10 # [times]
def initialize(options) def initialize(options)
super() super()
@ -119,7 +122,7 @@ private
def set_options def set_options
HTTPConfigLoader.set_options(@client, @options) HTTPConfigLoader.set_options(@client, @options)
@charset = @options["charset"] || XSD::Charset.charset_label($KCODE) @charset = @options["charset"] || XSD::Charset.xml_encoding_label
@options.add_hook("charset") do |key, value| @options.add_hook("charset") do |key, value|
@charset = value @charset = value
end end
@ -140,6 +143,7 @@ private
end end
def set_cookie_store_file(value) def set_cookie_store_file(value)
value = nil if value and value.empty?
@cookie_store = value @cookie_store = value
@client.set_cookie_store(@cookie_store) if @cookie_store @client.set_cookie_store(@cookie_store) if @cookie_store
end end
@ -161,7 +165,20 @@ private
send_string = conn_data.send_string send_string = conn_data.send_string
@wiredump_dev << "Wire dump:\n\n" if @wiredump_dev @wiredump_dev << "Wire dump:\n\n" if @wiredump_dev
begin begin
res = @client.post(endpoint_url, send_string, extra) retry_count = 0
while true
res = @client.post(endpoint_url, send_string, extra)
if RETRYABLE and HTTP::Status.redirect?(res.status)
retry_count += 1
if retry_count >= MAX_RETRY_COUNT
raise HTTPStreamError.new("redirect count exceeded")
end
endpoint_url = res.header["location"][0]
puts "redirected to #{endpoint_url}" if $DEBUG
else
break
end
end
rescue rescue
@client.reset(endpoint_url) @client.reset(endpoint_url)
raise raise

View file

@ -120,9 +120,8 @@ private
if result.length == 0 if result.length == 0
return parts.dup return parts.dup
end end
if parts.length != result.length # result length can be shorter than parts's.
raise RuntimeError.new("Incomplete prarmeterOrder list.") # return part must not be a part of the parameterOrder.
end
result result
end end
end end

View file

@ -36,6 +36,14 @@ class Param < Info
root.message(@message) or raise RuntimeError.new("#{@message} not found") root.message(@message) or raise RuntimeError.new("#{@message} not found")
end end
def soapbody_use
if @soapbody
@soapbody.use || :literal
else
raise RuntimeError.new("soap:body not found")
end
end
def parse_element(element) def parse_element(element)
case element case element
when SOAPBodyName when SOAPBodyName

View file

@ -36,7 +36,11 @@ class Body < Info
when PartsAttrName when PartsAttrName
@parts = value.source @parts = value.source
when UseAttrName when UseAttrName
@use = value.source if ['literal', 'encoded'].include?(value.source)
@use = value.source.intern
else
raise RuntimeError.new("unknown use of soap:body: #{value.source}")
end
when EncodingStyleAttrName when EncodingStyleAttrName
@encodingstyle = value.source @encodingstyle = value.source
when NamespaceAttrName when NamespaceAttrName

View file

@ -53,12 +53,12 @@ Methods = [
<<-EOD <<-EOD
super(*arg) super(*arg)
servant = #{class_name}.new servant = #{class_name}.new
#{class_name}::Methods.each do |name_as, name, param_def, soapaction, namespace, style| #{class_name}::Methods.each do |definitions|
if style == :document opt = definitions.last
@router.add_document_operation(servant, soapaction, name, param_def) if opt[:request_style] == :document
@router.add_document_operation(servant, *definitions)
else else
qname = XSD::QName.new(namespace, name_as) @router.add_rpc_operation(servant, *definitions)
@router.add_rpc_operation(servant, qname, soapaction, name, param_def)
end end
end end
self.mapping_registry = #{class_name}::MappingRegistry self.mapping_registry = #{class_name}::MappingRegistry

View file

@ -57,7 +57,8 @@ private
def dump_element def dump_element
@elements.collect { |ele| @elements.collect { |ele|
if ele.local_complextype if ele.local_complextype
dump_classdef(ele.name, ele.local_complextype) dump_classdef(ele.name, ele.local_complextype,
ele.elementform == 'qualified')
elsif ele.local_simpletype elsif ele.local_simpletype
dump_simpletypedef(ele.name, ele.local_simpletype) dump_simpletypedef(ele.name, ele.local_simpletype)
else else
@ -117,7 +118,7 @@ private
c.dump c.dump
end end
def dump_classdef(qname, typedef) def dump_classdef(qname, typedef, qualified = false)
if @faulttypes and @faulttypes.index(qname) if @faulttypes and @faulttypes.index(qname)
c = XSD::CodeGen::ClassDef.new(create_class_name(qname), c = XSD::CodeGen::ClassDef.new(create_class_name(qname),
'::StandardError') '::StandardError')
@ -127,6 +128,7 @@ private
c.comment = "#{qname}" c.comment = "#{qname}"
c.def_classvar('schema_type', ndq(qname.name)) c.def_classvar('schema_type', ndq(qname.name))
c.def_classvar('schema_ns', ndq(qname.namespace)) c.def_classvar('schema_ns', ndq(qname.namespace))
c.def_classvar('schema_qualified', dq('true')) if qualified
schema_element = [] schema_element = []
init_lines = '' init_lines = ''
params = [] params = []
@ -158,7 +160,10 @@ private
else else
params << "#{varname} = nil" params << "#{varname} = nil"
end end
eleqname = (varname == name) ? nil : element.name # nil means @@schema_ns + varname
eleqname =
(varname == name && element.name.namespace == qname.namespace) ?
nil : element.name
schema_element << [varname, eleqname, type] schema_element << [varname, eleqname, type]
end end
unless typedef.attributes.empty? unless typedef.attributes.empty?
@ -256,13 +261,50 @@ private
raise RuntimeError.new("cannot define name of #{attribute}") raise RuntimeError.new("cannot define name of #{attribute}")
end end
DEFAULT_ITEM_NAME = XSD::QName.new(nil, 'item')
def dump_arraydef(complextype) def dump_arraydef(complextype)
qname = complextype.name qname = complextype.name
c = XSD::CodeGen::ClassDef.new(create_class_name(qname), '::Array') c = XSD::CodeGen::ClassDef.new(create_class_name(qname), '::Array')
c.comment = "#{qname}" c.comment = "#{qname}"
type = complextype.child_type child_type = complextype.child_type
c.def_classvar('schema_type', ndq(type.name)) c.def_classvar('schema_type', ndq(child_type.name))
c.def_classvar('schema_ns', ndq(type.namespace)) c.def_classvar('schema_ns', ndq(child_type.namespace))
child_element = complextype.find_aryelement
schema_element = []
if child_type == XSD::AnyTypeName
type = nil
elsif child_element and (klass = element_basetype(child_element))
type = klass.name
elsif child_type
type = create_class_name(child_type)
else
type = nil
end
if child_element
if child_element.map_as_array?
type << '[]' if type
end
child_element_name = child_element.name
else
child_element_name = DEFAULT_ITEM_NAME
end
schema_element << [child_element_name.name, child_element_name, type]
c.def_classvar('schema_element',
'[' +
schema_element.collect { |varname, name, type|
'[' +
(
if name
varname.dump + ', [' + ndq(type) + ', ' + dqname(name) + ']'
else
varname.dump + ', ' + ndq(type)
end
) +
']'
}.join(', ') +
']'
)
c.dump c.dump
end end
end end

View file

@ -42,8 +42,8 @@ private
endpoint_url = ARGV.shift endpoint_url = ARGV.shift
obj = #{ drv_name }.new(endpoint_url) obj = #{ drv_name }.new(endpoint_url)
# Uncomment the below line to see SOAP wiredumps. # run ruby with -d to see SOAP wiredumps.
# obj.wiredump_dev = STDERR obj.wiredump_dev = STDERR if $DEBUG
__EOD__ __EOD__
@definitions.porttype(name).operations.each do |operation| @definitions.porttype(name).operations.each do |operation|

View file

@ -106,18 +106,43 @@ class ComplexType < Info
end end
end end
if check_array_content(complexcontent.content) if check_array_content(complexcontent.content)
return complexcontent.content.elements[0].type return element_simpletype(complexcontent.content.elements[0])
end end
elsif check_array_content(content) elsif check_array_content(content)
return content.elements[0].type return element_simpletype(content.elements[0])
end end
raise RuntimeError.new("Assert: Unknown array definition.") raise RuntimeError.new("Assert: Unknown array definition.")
end end
def find_aryelement
unless compoundtype == :TYPE_ARRAY
raise RuntimeError.new("Assert: not for array")
end
if complexcontent
if check_array_content(complexcontent.content)
return complexcontent.content.elements[0]
end
elsif check_array_content(content)
return content.elements[0]
end
nil # use default item name
end
private private
def element_simpletype(element)
if element.type
element.type
elsif element.local_simpletype
element.local_simpletype.base
else
nil
end
end
def check_array_content(content) def check_array_content(content)
content.elements.size == 1 and content.elements[0].maxoccurs != '1' content and content.elements.size == 1 and
content.elements[0].maxoccurs != '1'
end end
def content_arytype def content_arytype

View file

@ -69,18 +69,18 @@ Methods = [
end end
c.def_privatemethod("init_methods") do c.def_privatemethod("init_methods") do
<<-EOD <<-EOD
Methods.each do |name_as, name, params, soapaction, namespace, style| Methods.each do |definitions|
qname = XSD::QName.new(namespace, name_as) opt = definitions.last
if style == :document if opt[:request_style] == :document
@proxy.add_document_method(soapaction, name, params) add_document_operation(*definitions)
add_document_method_interface(name, params)
else else
@proxy.add_rpc_method(qname, soapaction, name, params) add_rpc_operation(*definitions)
add_rpc_method_interface(name, params) qname = definitions[0]
end name = definitions[2]
if name_as != name and name_as.capitalize == name.capitalize if qname.name != name and qname.name.capitalize == name.capitalize
::SOAP::Mapping.define_singleton_method(self, name_as) do |*arg| ::SOAP::Mapping.define_singleton_method(self, qname.name) do |*arg|
__send__(name, *arg) __send__(name, *arg)
end
end end
end end
end end

View file

@ -46,18 +46,18 @@ class MethodDefCreator
def collect_rpcparameter(operation) def collect_rpcparameter(operation)
result = operation.inputparts.collect { |part| result = operation.inputparts.collect { |part|
collect_type(part.type) collect_type(part.type)
param_set(::SOAP::RPC::SOAPMethod::IN, rpcdefinedtype(part), part.name) param_set(::SOAP::RPC::SOAPMethod::IN, part.name, rpcdefinedtype(part))
} }
outparts = operation.outputparts outparts = operation.outputparts
if outparts.size > 0 if outparts.size > 0
retval = outparts[0] retval = outparts[0]
collect_type(retval.type) collect_type(retval.type)
result << param_set(::SOAP::RPC::SOAPMethod::RETVAL, result << param_set(::SOAP::RPC::SOAPMethod::RETVAL, retval.name,
rpcdefinedtype(retval), retval.name) rpcdefinedtype(retval))
cdr(outparts).each { |part| cdr(outparts).each { |part|
collect_type(part.type) collect_type(part.type)
result << param_set(::SOAP::RPC::SOAPMethod::OUT, rpcdefinedtype(part), result << param_set(::SOAP::RPC::SOAPMethod::OUT, part.name,
part.name) rpcdefinedtype(part))
} }
end end
result result
@ -66,12 +66,12 @@ class MethodDefCreator
def collect_documentparameter(operation) def collect_documentparameter(operation)
param = [] param = []
operation.inputparts.each do |input| operation.inputparts.each do |input|
param << param_set(::SOAP::RPC::SOAPMethod::IN, param << param_set(::SOAP::RPC::SOAPMethod::IN, input.name,
documentdefinedtype(input), input.name) documentdefinedtype(input), elementqualified(input))
end end
operation.outputparts.each do |output| operation.outputparts.each do |output|
param << param_set(::SOAP::RPC::SOAPMethod::OUT, param << param_set(::SOAP::RPC::SOAPMethod::OUT, output.name,
documentdefinedtype(output), output.name) documentdefinedtype(output), elementqualified(output))
end end
param param
end end
@ -82,23 +82,38 @@ private
name = safemethodname(operation.name.name) name = safemethodname(operation.name.name)
name_as = operation.name.name name_as = operation.name.name
style = binding.soapoperation_style style = binding.soapoperation_style
inputuse = binding.input.soapbody_use
outputuse = binding.output.soapbody_use
namespace = binding.input.soapbody.namespace namespace = binding.input.soapbody.namespace
if style == :rpc if style == :rpc
qname = XSD::QName.new(namespace, name_as)
paramstr = param2str(collect_rpcparameter(operation)) paramstr = param2str(collect_rpcparameter(operation))
else else
qname = nil
paramstr = param2str(collect_documentparameter(operation)) paramstr = param2str(collect_documentparameter(operation))
end end
if paramstr.empty? if paramstr.empty?
paramstr = '[]' paramstr = '[]'
else else
paramstr = "[\n" << paramstr.gsub(/^/, ' ') << "\n ]" paramstr = "[ " << paramstr.split(/\r?\n/).join("\n ") << " ]"
end end
return <<__EOD__ definitions = <<__EOD__
[#{dq(name_as)}, #{dq(name)}, #{ndq(binding.soapaction)},
#{dq(name)},
#{paramstr}, #{paramstr},
#{ndq(binding.soapaction)}, #{ndq(namespace)}, #{sym(style.id2name)} { :request_style => #{sym(style.id2name)}, :request_use => #{sym(inputuse.id2name)},
] :response_style => #{sym(style.id2name)}, :response_use => #{sym(outputuse.id2name)} }
__EOD__ __EOD__
if style == :rpc
return <<__EOD__
[ #{qname.dump},
#{definitions}]
__EOD__
else
return <<__EOD__
[ #{definitions}]
__EOD__
end
end end
def rpcdefinedtype(part) def rpcdefinedtype(part)
@ -144,8 +159,22 @@ __EOD__
end end
end end
def param_set(io_type, type, name) def elementqualified(part)
[io_type, type, name] if mapped = basetype_mapped_class(part.type)
false
elsif definedtype = @simpletypes[part.type]
false
elsif definedtype = @elements[part.element]
definedtype.elementform == 'qualified'
elsif definedtype = @complextypes[part.type]
false
else
raise RuntimeError.new("part: #{part.name} cannot be resolved")
end
end
def param_set(io_type, name, type, ele = nil)
[io_type, name, type, ele]
end end
def collect_type(type) def collect_type(type)
@ -161,7 +190,12 @@ __EOD__
def param2str(params) def param2str(params)
params.collect { |param| params.collect { |param|
"[#{dq(param[0])}, #{dq(param[2])}, #{type2str(param[1])}]" io, name, type, ele = param
unless ele.nil?
"[#{dq(io)}, #{dq(name)}, #{type2str(type)}, #{ele2str(ele)}]"
else
"[#{dq(io)}, #{dq(name)}, #{type2str(type)}]"
end
}.join(",\n") }.join(",\n")
end end
@ -173,6 +207,15 @@ __EOD__
end end
end end
def ele2str(ele)
qualified = ele
if qualified
"true"
else
"false"
end
end
def cdr(ary) def cdr(ary)
result = ary.dup result = ary.dup
result.shift result.shift

View file

@ -55,12 +55,12 @@ Methods = [
<<-EOD <<-EOD
super(*arg) super(*arg)
servant = #{class_name}.new servant = #{class_name}.new
#{class_name}::Methods.each do |name_as, name, param_def, soapaction, namespace, style| #{class_name}::Methods.each do |definitions|
if style == :document opt = definitions.last
@router.add_document_operation(servant, soapaction, name, param_def) if opt[:request_style] == :document
@router.add_document_operation(servant, *definitions)
else else
qname = XSD::QName.new(namespace, name_as) @router.add_rpc_operation(servant, *definitions)
@router.add_rpc_operation(servant, qname, soapaction, name, param_def)
end end
end end
self.mapping_registry = #{class_name}::MappingRegistry self.mapping_registry = #{class_name}::MappingRegistry

View file

@ -29,6 +29,10 @@ class All < Info
parent.targetnamespace parent.targetnamespace
end end
def elementformdefault
parent.elementformdefault
end
def <<(element) def <<(element)
@elements << element @elements << element
end end

View file

@ -18,9 +18,8 @@ class Attribute < Info
if RUBY_VERSION > "1.7.0" if RUBY_VERSION > "1.7.0"
def attr_reader_ref(symbol) def attr_reader_ref(symbol)
name = symbol.to_s name = symbol.to_s
iv = "@#{name}"
define_method(name) { define_method(name) {
instance_variable_get(iv) || instance_variable_get("@#{name}") ||
(refelement ? refelement.__send__(name) : nil) (refelement ? refelement.__send__(name) : nil)
} }
end end
@ -94,7 +93,11 @@ class Attribute < Info
when FormAttrName when FormAttrName
@form = value.source @form = value.source
when NameAttrName when NameAttrName
@name = XSD::QName.new(targetnamespace, value.source) if directelement?
@name = XSD::QName.new(targetnamespace, value.source)
else
@name = XSD::QName.new(nil, value.source)
end
when TypeAttrName when TypeAttrName
@type = value @type = value
when DefaultAttrName when DefaultAttrName
@ -111,6 +114,12 @@ class Attribute < Info
nil nil
end end
end end
private
def directelement?
parent.is_a?(Schema)
end
end end

View file

@ -29,6 +29,10 @@ class Choice < Info
parent.targetnamespace parent.targetnamespace
end end
def elementformdefault
parent.elementformdefault
end
def <<(element) def <<(element)
@elements << element @elements << element
end end

View file

@ -37,7 +37,13 @@ class ComplexType < Info
end end
def targetnamespace def targetnamespace
parent.is_a?(WSDL::XMLSchema::Element) ? nil : parent.targetnamespace # inner elements can be qualified
# parent.is_a?(WSDL::XMLSchema::Element) ? nil : parent.targetnamespace
parent.targetnamespace
end
def elementformdefault
parent.elementformdefault
end end
AnyAsElement = Element.new(XSD::QName.new(nil, 'any'), XSD::AnyTypeName) AnyAsElement = Element.new(XSD::QName.new(nil, 'any'), XSD::AnyTypeName)

View file

@ -18,9 +18,8 @@ class Element < Info
if RUBY_VERSION > "1.7.0" if RUBY_VERSION > "1.7.0"
def attr_reader_ref(symbol) def attr_reader_ref(symbol)
name = symbol.to_s name = symbol.to_s
iv = "@#{name}"
define_method(name) { define_method(name) {
instance_variable_get(iv) || instance_variable_get("@#{name}") ||
(refelement ? refelement.__send__(name) : nil) (refelement ? refelement.__send__(name) : nil)
} }
end end
@ -37,6 +36,7 @@ class Element < Info
end end
attr_writer :name # required attr_writer :name # required
attr_writer :form
attr_writer :type attr_writer :type
attr_writer :local_simpletype attr_writer :local_simpletype
attr_writer :local_complextype attr_writer :local_complextype
@ -46,6 +46,7 @@ class Element < Info
attr_writer :nillable attr_writer :nillable
attr_reader_ref :name attr_reader_ref :name
attr_reader_ref :form
attr_reader_ref :type attr_reader_ref :type
attr_reader_ref :local_simpletype attr_reader_ref :local_simpletype
attr_reader_ref :local_complextype attr_reader_ref :local_complextype
@ -59,6 +60,7 @@ class Element < Info
def initialize(name = nil, type = nil) def initialize(name = nil, type = nil)
super() super()
@name = name @name = name
@form = nil
@type = type @type = type
@local_simpletype = @local_complextype = nil @local_simpletype = @local_complextype = nil
@constraint = nil @constraint = nil
@ -70,18 +72,21 @@ class Element < Info
end end
def refelement def refelement
@refelement ||= root.collect_elements[@ref] @refelement ||= (@ref ? root.collect_elements[@ref] : nil)
end end
def targetnamespace def targetnamespace
parent.targetnamespace parent.targetnamespace
end end
def elementform def elementformdefault
# ToDo: must be overwritten.
parent.elementformdefault parent.elementformdefault
end end
def elementform
self.form.nil? ? parent.elementformdefault : self.form
end
def parse_element(element) def parse_element(element)
case element case element
when SimpleTypeName when SimpleTypeName
@ -102,7 +107,14 @@ class Element < Info
def parse_attr(attr, value) def parse_attr(attr, value)
case attr case attr
when NameAttrName when NameAttrName
@name = XSD::QName.new(targetnamespace, value.source) # namespace may be nil
if directelement? or elementform == 'qualified'
@name = XSD::QName.new(targetnamespace, value.source)
else
@name = XSD::QName.new(nil, value.source)
end
when FormAttrName
@form = value.source
when TypeAttrName when TypeAttrName
@type = value @type = value
when RefAttrName when RefAttrName
@ -110,14 +122,16 @@ class Element < Info
when MaxOccursAttrName when MaxOccursAttrName
if parent.is_a?(All) if parent.is_a?(All)
if value.source != '1' if value.source != '1'
raise Parser::AttrConstraintError.new("cannot parse #{value} for #{attr}") raise Parser::AttrConstraintError.new(
"cannot parse #{value} for #{attr}")
end end
end end
@maxoccurs = value.source @maxoccurs = value.source
when MinOccursAttrName when MinOccursAttrName
if parent.is_a?(All) if parent.is_a?(All)
unless ['0', '1'].include?(value.source) unless ['0', '1'].include?(value.source)
raise Parser::AttrConstraintError.new("cannot parse #{value} for #{attr}") raise Parser::AttrConstraintError.new(
"cannot parse #{value} for #{attr}")
end end
end end
@minoccurs = value.source @minoccurs = value.source
@ -127,6 +141,12 @@ class Element < Info
nil nil
end end
end end
private
def directelement?
parent.is_a?(Schema)
end
end end

View file

@ -1,5 +1,5 @@
# WSDL4R - XMLSchema schema definition for WSDL. # WSDL4R - XMLSchema schema definition for WSDL.
# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. # Copyright (C) 2002, 2003-2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can # This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license; # redistribute it and/or modify it under the same terms of Ruby's license;
@ -34,7 +34,8 @@ class Schema < Info
@elements = XSD::NamedElements.new @elements = XSD::NamedElements.new
@attributes = XSD::NamedElements.new @attributes = XSD::NamedElements.new
@imports = [] @imports = []
@elementformdefault = "qualified" @attributeformdefault = "unqualified"
@elementformdefault = "unqualified"
@importedschema = {} @importedschema = {}
@location = nil @location = nil
@root = self @root = self

View file

@ -29,6 +29,10 @@ class Sequence < Info
parent.targetnamespace parent.targetnamespace
end end
def elementformdefault
parent.elementformdefault
end
def <<(element) def <<(element)
@elements << element @elements << element
end end

View file

@ -1,5 +1,5 @@
# XSD4R - Charset handling library. # XSD4R - Charset handling library.
# Copyright (C) 2001, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. # Copyright (C) 2001, 2003, 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can # This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license; # redistribute it and/or modify it under the same terms of Ruby's license;
@ -10,7 +10,7 @@ module XSD
module Charset module Charset
@encoding = $KCODE @internal_encoding = $KCODE
class XSDError < StandardError; end class XSDError < StandardError; end
class CharsetError < XSDError; end class CharsetError < XSDError; end
@ -24,27 +24,40 @@ public
# #
EncodingConvertMap = {} EncodingConvertMap = {}
def Charset.init def Charset.init
EncodingConvertMap[['UTF8', 'X_ISO8859_1']] =
Proc.new { |str| str.unpack('U*').pack('C*') }
EncodingConvertMap[['X_ISO8859_1', 'UTF8']] =
Proc.new { |str| str.unpack('C*').pack('U*') }
begin begin
require 'xsd/iconvcharset' require 'xsd/iconvcharset'
@encoding = 'UTF8' @internal_encoding = 'UTF8'
sjtag = (/(mswin|bccwin|mingw|cygwin|emx)/ =~ RUBY_PLATFORM) ? 'cp932' : 'shift_jis' sjtag = (/(mswin|bccwin|mingw|cygwin|emx)/ =~ RUBY_PLATFORM) ? 'cp932' :
EncodingConvertMap[['UTF8', 'EUC' ]] = Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "utf-8", str) } 'shift_jis'
EncodingConvertMap[['EUC' , 'UTF8']] = Proc.new { |str| IconvCharset.safe_iconv("utf-8", "euc-jp", str) } EncodingConvertMap[['UTF8', 'EUC' ]] =
EncodingConvertMap[['EUC' , 'SJIS']] = Proc.new { |str| IconvCharset.safe_iconv(sjtag, "euc-jp", str) } Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "utf-8", str) }
EncodingConvertMap[['UTF8', 'SJIS']] = Proc.new { |str| IconvCharset.safe_iconv(sjtag, "utf-8", str) } EncodingConvertMap[['EUC' , 'UTF8']] =
EncodingConvertMap[['SJIS', 'UTF8']] = Proc.new { |str| IconvCharset.safe_iconv("utf-8", sjtag, str) } Proc.new { |str| IconvCharset.safe_iconv("utf-8", "euc-jp", str) }
EncodingConvertMap[['SJIS', 'EUC' ]] = Proc.new { |str| IconvCharset.safe_iconv("euc-jp", sjtag, str) } EncodingConvertMap[['EUC' , 'SJIS']] =
Proc.new { |str| IconvCharset.safe_iconv(sjtag, "euc-jp", str) }
EncodingConvertMap[['UTF8', 'SJIS']] =
Proc.new { |str| IconvCharset.safe_iconv(sjtag, "utf-8", str) }
EncodingConvertMap[['SJIS', 'UTF8']] =
Proc.new { |str| IconvCharset.safe_iconv("utf-8", sjtag, str) }
EncodingConvertMap[['SJIS', 'EUC' ]] =
Proc.new { |str| IconvCharset.safe_iconv("euc-jp", sjtag, str) }
rescue LoadError rescue LoadError
begin begin
require 'nkf' require 'nkf'
EncodingConvertMap[['EUC' , 'SJIS']] = Proc.new { |str| NKF.nkf('-sXm0', str) } EncodingConvertMap[['EUC' , 'SJIS']] =
EncodingConvertMap[['SJIS', 'EUC' ]] = Proc.new { |str| NKF.nkf('-eXm0', str) } Proc.new { |str| NKF.nkf('-sXm0', str) }
EncodingConvertMap[['SJIS', 'EUC' ]] =
Proc.new { |str| NKF.nkf('-eXm0', str) }
rescue LoadError rescue LoadError
end end
begin begin
require 'uconv' require 'uconv'
@encoding = 'UTF8' @internal_encoding = 'UTF8'
EncodingConvertMap[['UTF8', 'EUC' ]] = Uconv.method(:u8toeuc) EncodingConvertMap[['UTF8', 'EUC' ]] = Uconv.method(:u8toeuc)
EncodingConvertMap[['UTF8', 'SJIS']] = Uconv.method(:u8tosjis) EncodingConvertMap[['UTF8', 'SJIS']] = Uconv.method(:u8tosjis)
EncodingConvertMap[['EUC' , 'UTF8']] = Uconv.method(:euctou8) EncodingConvertMap[['EUC' , 'UTF8']] = Uconv.method(:euctou8)
@ -60,6 +73,8 @@ public
'EUC' => 'euc-jp', 'EUC' => 'euc-jp',
'SJIS' => 'shift_jis', 'SJIS' => 'shift_jis',
'UTF8' => 'utf-8', 'UTF8' => 'utf-8',
'X_ISO_8859_1' => 'iso-8859-1',
'X_UNKNOWN' => nil,
} }
@ -67,24 +82,24 @@ public
## handlers ## handlers
# #
def Charset.encoding def Charset.encoding
@encoding @internal_encoding
end end
def Charset.encoding=(encoding) def Charset.encoding=(encoding)
warn("xsd charset is set to #{encoding}") if $DEBUG warn("xsd charset is set to #{encoding}") if $DEBUG
@encoding = encoding @internal_encoding = encoding
end end
def Charset.encoding_label def Charset.xml_encoding_label
charset_label(@encoding) charset_label(@internal_encoding)
end end
def Charset.encoding_to_xml(str, charset) def Charset.encoding_to_xml(str, charset)
encoding_conv(str, @encoding, charset_str(charset)) encoding_conv(str, @internal_encoding, charset_str(charset))
end end
def Charset.encoding_from_xml(str, charset) def Charset.encoding_from_xml(str, charset)
encoding_conv(str, charset_str(charset), @encoding) encoding_conv(str, charset_str(charset), @internal_encoding)
end end
def Charset.encoding_conv(str, enc_from, enc_to) def Charset.encoding_conv(str, enc_from, enc_to)
@ -94,7 +109,7 @@ public
converter.call(str) converter.call(str)
else else
raise CharsetConversionError.new( raise CharsetConversionError.new(
"Converter not found: #{ enc_from } -> #{ enc_to }") "Converter not found: #{enc_from} -> #{enc_to}")
end end
end end
@ -104,26 +119,26 @@ public
def Charset.charset_str(label) def Charset.charset_str(label)
if CharsetMap.respond_to?(:key) if CharsetMap.respond_to?(:key)
CharsetMap.key(label.downcase) CharsetMap.key(label.downcase) || 'X_UNKNOWN'
else else
CharsetMap.index(label.downcase) CharsetMap.index(label.downcase) || 'X_UNKNOWN'
end end
end end
# us_ascii = '[\x00-\x7F]' # us_ascii = '[\x00-\x7F]'
us_ascii = '[\x9\xa\xd\x20-\x7F]' # XML 1.0 restricted. us_ascii = '[\x9\xa\xd\x20-\x7F]' # XML 1.0 restricted.
USASCIIRegexp = Regexp.new("\\A#{ us_ascii }*\\z", nil, "NONE") USASCIIRegexp = Regexp.new("\\A#{us_ascii}*\\z", nil, "NONE")
twobytes_euc = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])' twobytes_euc = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])'
threebytes_euc = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])' threebytes_euc = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])'
character_euc = "(?:#{ us_ascii }|#{ twobytes_euc }|#{ threebytes_euc })" character_euc = "(?:#{us_ascii}|#{twobytes_euc}|#{threebytes_euc})"
EUCRegexp = Regexp.new("\\A#{ character_euc }*\\z", nil, "NONE") EUCRegexp = Regexp.new("\\A#{character_euc}*\\z", nil, "NONE")
# onebyte_sjis = '[\x00-\x7F\xA1-\xDF]' # onebyte_sjis = '[\x00-\x7F\xA1-\xDF]'
onebyte_sjis = '[\x9\xa\xd\x20-\x7F\xA1-\xDF]' # XML 1.0 restricted. onebyte_sjis = '[\x9\xa\xd\x20-\x7F\xA1-\xDF]' # XML 1.0 restricted.
twobytes_sjis = '(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])' twobytes_sjis = '(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])'
character_sjis = "(?:#{ onebyte_sjis }|#{ twobytes_sjis })" character_sjis = "(?:#{onebyte_sjis}|#{twobytes_sjis})"
SJISRegexp = Regexp.new("\\A#{ character_sjis }*\\z", nil, "NONE") SJISRegexp = Regexp.new("\\A#{character_sjis}*\\z", nil, "NONE")
# 0xxxxxxx # 0xxxxxxx
# 110yyyyy 10xxxxxx # 110yyyyy 10xxxxxx
@ -132,8 +147,9 @@ public
threebytes_utf8 = '(?:[\xE0-\xEF][\x80-\xBF][\x80-\xBF])' threebytes_utf8 = '(?:[\xE0-\xEF][\x80-\xBF][\x80-\xBF])'
# 11110uuu 10uuuzzz 10yyyyyy 10xxxxxx # 11110uuu 10uuuzzz 10yyyyyy 10xxxxxx
fourbytes_utf8 = '(?:[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])' fourbytes_utf8 = '(?:[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])'
character_utf8 = "(?:#{ us_ascii }|#{ twobytes_utf8 }|#{ threebytes_utf8 }|#{ fourbytes_utf8 })" character_utf8 =
UTF8Regexp = Regexp.new("\\A#{ character_utf8 }*\\z", nil, "NONE") "(?:#{us_ascii}|#{twobytes_utf8}|#{threebytes_utf8}|#{fourbytes_utf8})"
UTF8Regexp = Regexp.new("\\A#{character_utf8}*\\z", nil, "NONE")
def Charset.is_us_ascii(str) def Charset.is_us_ascii(str)
USASCIIRegexp =~ str USASCIIRegexp =~ str
@ -162,7 +178,7 @@ public
when 'SJIS' when 'SJIS'
is_sjis(str) is_sjis(str)
else else
raise UnknownCharsetError.new("Unknown charset: #{ code }") raise UnknownCharsetError.new("Unknown charset: #{code}")
end end
end end
end end

View file

@ -1,5 +1,5 @@
# XSD4R - Code generation support # XSD4R - Code generation support
# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. # Copyright (C) 2004, 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can # This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license; # redistribute it and/or modify it under the same terms of Ruby's license;
@ -10,7 +10,8 @@ module XSD
module CodeGen module CodeGen
# from the file 'keywords' in 1.9. # from the file 'keywords' in 1.9.
KEYWORD = %w( KEYWORD = {}
%w(
__LINE__ __LINE__
__FILE__ __FILE__
BEGIN BEGIN
@ -51,7 +52,7 @@ until
when when
while while
yield yield
) ).each { |k| KEYWORD[k] = nil }
module GenSupport module GenSupport
def capitalize(target) def capitalize(target)
@ -96,12 +97,12 @@ module GenSupport
module_function :safemethodname? module_function :safemethodname?
def safevarname(name) def safevarname(name)
safename = name.scan(/[a-zA-Z0-9_]+/).join('_') safename = uncapitalize(name.scan(/[a-zA-Z0-9_]+/).join('_'))
safename = uncapitalize(safename)
if /^[a-z]/ !~ safename or keyword?(safename) if /^[a-z]/ !~ safename or keyword?(safename)
safename = "v_#{safename}" "v_#{safename}"
else
safename
end end
safename
end end
module_function :safevarname module_function :safevarname
@ -111,7 +112,7 @@ module GenSupport
module_function :safevarname? module_function :safevarname?
def keyword?(word) def keyword?(word)
KEYWORD.include?(word) KEYWORD.key?(word)
end end
module_function :keyword? module_function :keyword?

View file

@ -560,23 +560,20 @@ module XSDDateTimeImpl
def screen_data(t) def screen_data(t)
# convert t to a DateTime as an internal representation. # convert t to a DateTime as an internal representation.
if t.is_a?(DateTime) if t.respond_to?(:to_datetime) # 1.9 or later
t.to_datetime
elsif t.is_a?(DateTime)
t t
elsif t.is_a?(Date) elsif t.is_a?(Date)
if t.respond_to?(:to_datetime) # from 1.9 t = screen_data_str(t)
t.to_datetime t <<= 12 if t.year < 0
else t
t = screen_data_str(t)
t <<= 12 if t.year < 0
t
end
elsif t.is_a?(Time) elsif t.is_a?(Time)
sec, min, hour, mday, month, year = t.to_a[0..5] jd = DateTime.civil_to_jd(t.year, t.mon, t.mday, DateTime::ITALY)
diffday = t.usec.to_r / 1000000 / SecInDay fr = DateTime.time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) +
t.usec.to_r / 1000000 / SecInDay
of = t.utc_offset.to_r / SecInDay of = t.utc_offset.to_r / SecInDay
data = DateTime.civil(year, month, mday, hour, min, sec, of) DateTime.new0(DateTime.jd_to_ajd(jd, fr, of), of, DateTime::ITALY)
data += diffday
data
else else
screen_data_str(t) screen_data_str(t)
end end

View file

@ -72,7 +72,7 @@ public
if (name.namespace == @default_namespace) if (name.namespace == @default_namespace)
name.name name.name
elsif @ns2tag.key?(name.namespace) elsif @ns2tag.key?(name.namespace)
@ns2tag[name.namespace] + ':' << name.name "#{@ns2tag[name.namespace]}:#{name.name}"
else else
raise FormatError.new("namespace: #{name.namespace} not defined yet") raise FormatError.new("namespace: #{name.namespace} not defined yet")
end end

View file

@ -31,9 +31,6 @@ class QName
end end
def match(rhs) def match(rhs)
unless self.class === rhs
return false
end
if rhs.namespace and (rhs.namespace != @namespace) if rhs.namespace and (rhs.namespace != @namespace)
return false return false
end end
@ -44,7 +41,7 @@ class QName
end end
def ==(rhs) def ==(rhs)
(self.class === rhs && @namespace == rhs.namespace && @name == rhs.name) !rhs.nil? and @namespace == rhs.namespace and @name == rhs.name
end end
def ===(rhs) def ===(rhs)
@ -73,6 +70,8 @@ class QName
NormalizedNameRegexp =~ str NormalizedNameRegexp =~ str
self.new($1, $2) self.new($1, $2)
end end
EMPTY = QName.new.freeze
end end

View file

@ -179,14 +179,14 @@ __EOP__
cfg["protocol.http.ssl_config.ca_file"] = File.join(DIR, "ca.cert") cfg["protocol.http.ssl_config.ca_file"] = File.join(DIR, "ca.cert")
cfg["protocol.http.ssl_config.ca_file"] = File.join(DIR, "subca.cert") cfg["protocol.http.ssl_config.ca_file"] = File.join(DIR, "subca.cert")
#cfg.timeout = 123 #cfg.timeout = 123
assert_equal("Hello World, from ssl client", @client.hello_world("ssl client"))
#
cfg["protocol.http.ssl_config.ciphers"] = "!ALL" cfg["protocol.http.ssl_config.ciphers"] = "!ALL"
#
begin begin
@client.hello_world("ssl client") @client.hello_world("ssl client")
assert(false) assert(false)
rescue OpenSSL::SSL::SSLError => ssle rescue OpenSSL::SSL::SSLError => ssle
assert_equal("no ciphers available", ssle.message) # depends on OpenSSL version. (?:0.9.8|0.9.7)
assert_match(/\A(?:SSL_CTX_set_cipher_list:: no cipher match|no ciphers available)\z/, ssle.message)
end end
# #
cfg["protocol.http.ssl_config.ciphers"] = "ALL" cfg["protocol.http.ssl_config.ciphers"] = "ALL"
@ -201,7 +201,7 @@ private
def setup_server def setup_server
svrcmd = "#{q(RUBY)} " svrcmd = "#{q(RUBY)} "
svrcmd << "-d " if $DEBUG #svrcmd << "-d " if $DEBUG
svrcmd << File.join(DIR, "sslsvr.rb") svrcmd << File.join(DIR, "sslsvr.rb")
svrout = IO.popen(svrcmd) svrout = IO.popen(svrcmd)
@serverpid = Integer(svrout.gets.chomp) @serverpid = Integer(svrout.gets.chomp)

View file

@ -47,11 +47,14 @@ class TestFile < Test::Unit::TestCase
@client.reset_stream @client.reset_stream
end end
def test_file def test_get_file
assert_equal( assert_equal(
File.open(THIS_FILE) { |f| f.read }, File.open(THIS_FILE) { |f| f.read },
@client.get_file['file'].content @client.get_file['file'].content
) )
end
def test_put_file
assert_equal( assert_equal(
"File 'foo' was received ok.", "File 'foo' was received ok.",
@client.put_file('foo', @client.put_file('foo',

View file

@ -1,5 +1,6 @@
require 'test/unit' require 'test/unit'
require 'soap/baseData' require 'soap/baseData'
require 'soap/mapping'
module SOAP module SOAP
@ -36,7 +37,7 @@ class TestSOAPElement < Test::Unit::TestCase
assert_equal(LiteralNamespace, obj.encodingstyle) assert_equal(LiteralNamespace, obj.encodingstyle)
assert_equal({}, obj.extraattr) assert_equal({}, obj.extraattr)
assert_equal([], obj.precedents) assert_equal([], obj.precedents)
assert_equal(false, obj.qualified) assert_equal(nil, obj.qualified)
assert_equal(nil, obj.text) assert_equal(nil, obj.text)
assert(obj.members.empty?) assert(obj.members.empty?)

View file

@ -98,7 +98,7 @@ __EOX__
end end
def parse_req_header(str) def parse_req_header(str)
if ::SOAP::StreamHandler::Client.to_s == 'SOAP::NetHttpClient' if ::SOAP::HTTPStreamHandler::Client.to_s == 'SOAP::NetHttpClient'
str = eval(str.split(/\r?\n/)[4][3..-1]) str = eval(str.split(/\r?\n/)[4][3..-1])
end end
parse_req_header_http_access2(str) parse_req_header_http_access2(str)

View file

@ -73,8 +73,7 @@ class TestCalc < Test::Unit::TestCase
assert_equal(0.3, @client.add(0.1, 0.2)) assert_equal(0.3, @client.add(0.1, 0.2))
end end
# test for backward compatibility def test_old_driver
def __NOTEST__test_old_driver
@client = ::SOAP::WSDLDriverFactory.new(@wsdl).create_driver @client = ::SOAP::WSDLDriverFactory.new(@wsdl).create_driver
@client.wiredump_dev = STDOUT if $DEBUG @client.wiredump_dev = STDOUT if $DEBUG
@client.endpoint_url = "http://localhost:#{Port}/" @client.endpoint_url = "http://localhost:#{Port}/"

View file

@ -5,7 +5,7 @@ class Echoele
@@schema_type = "echoele" @@schema_type = "echoele"
@@schema_ns = "urn:docrpc" @@schema_ns = "urn:docrpc"
@@schema_attribute = {XSD::QName.new(nil, "attr_string") => "SOAP::SOAPString", XSD::QName.new(nil, "attr-int") => "SOAP::SOAPInt"} @@schema_attribute = {XSD::QName.new(nil, "attr_string") => "SOAP::SOAPString", XSD::QName.new(nil, "attr-int") => "SOAP::SOAPInt"}
@@schema_element = [["struct1", "Echo_struct"], ["struct_2", ["Echo_struct", XSD::QName.new(nil, "struct-2")]]] @@schema_element = [["struct1", ["Echo_struct", XSD::QName.new(nil, "struct1")]], ["struct_2", ["Echo_struct", XSD::QName.new(nil, "struct-2")]]]
attr_accessor :struct1 attr_accessor :struct1
attr_accessor :struct_2 attr_accessor :struct_2
@ -38,7 +38,7 @@ class Echo_response
@@schema_type = "echo_response" @@schema_type = "echo_response"
@@schema_ns = "urn:docrpc" @@schema_ns = "urn:docrpc"
@@schema_attribute = {XSD::QName.new(nil, "attr_string") => "SOAP::SOAPString", XSD::QName.new(nil, "attr-int") => "SOAP::SOAPInt"} @@schema_attribute = {XSD::QName.new(nil, "attr_string") => "SOAP::SOAPString", XSD::QName.new(nil, "attr-int") => "SOAP::SOAPInt"}
@@schema_element = [["struct1", "Echo_struct"], ["struct_2", ["Echo_struct", XSD::QName.new(nil, "struct-2")]]] @@schema_element = [["struct1", ["Echo_struct", XSD::QName.new(nil, "struct1")]], ["struct_2", ["Echo_struct", XSD::QName.new(nil, "struct-2")]]]
attr_accessor :struct1 attr_accessor :struct1
attr_accessor :struct_2 attr_accessor :struct_2
@ -70,18 +70,18 @@ end
class Echo_struct class Echo_struct
@@schema_type = "echo_struct" @@schema_type = "echo_struct"
@@schema_ns = "urn:docrpc" @@schema_ns = "urn:docrpc"
@@schema_attribute = {XSD::QName.new("urn:docrpc", "m_attr") => "SOAP::SOAPString"} @@schema_attribute = {XSD::QName.new(nil, "m_attr") => "SOAP::SOAPString"}
@@schema_element = [["m_string", "SOAP::SOAPString"], ["m_datetime", "SOAP::SOAPDateTime"]] @@schema_element = [["m_string", ["SOAP::SOAPString", XSD::QName.new(nil, "m_string")]], ["m_datetime", ["SOAP::SOAPDateTime", XSD::QName.new(nil, "m_datetime")]]]
attr_accessor :m_string attr_accessor :m_string
attr_accessor :m_datetime attr_accessor :m_datetime
def xmlattr_m_attr def xmlattr_m_attr
(@__xmlattr ||= {})[XSD::QName.new("urn:docrpc", "m_attr")] (@__xmlattr ||= {})[XSD::QName.new(nil, "m_attr")]
end end
def xmlattr_m_attr=(value) def xmlattr_m_attr=(value)
(@__xmlattr ||= {})[XSD::QName.new("urn:docrpc", "m_attr")] = value (@__xmlattr ||= {})[XSD::QName.new(nil, "m_attr")] = value
end end
def initialize(m_string = nil, m_datetime = nil) def initialize(m_string = nil, m_datetime = nil)

View file

@ -4,7 +4,7 @@ require 'xsd/qname'
class Person class Person
@@schema_type = "Person" @@schema_type = "Person"
@@schema_ns = "http://www.jin.gr.jp/~nahi/xmlns/sample/Person" @@schema_ns = "http://www.jin.gr.jp/~nahi/xmlns/sample/Person"
@@schema_element = [["familyname", "SOAP::SOAPString"], ["givenname", "SOAP::SOAPString"], ["var1", "SOAP::SOAPInt"], ["var2", "SOAP::SOAPDouble"], ["var3", "SOAP::SOAPString"]] @@schema_element = [["familyname", ["SOAP::SOAPString", XSD::QName.new(nil, "familyname")]], ["givenname", ["SOAP::SOAPString", XSD::QName.new(nil, "givenname")]], ["var1", ["SOAP::SOAPInt", XSD::QName.new(nil, "var1")]], ["var2", ["SOAP::SOAPDouble", XSD::QName.new(nil, "var2")]], ["var3", ["SOAP::SOAPString", XSD::QName.new(nil, "var3")]]]
attr_accessor :familyname attr_accessor :familyname
attr_accessor :givenname attr_accessor :givenname

View file